commit 04256ba3414c3eb7f01aa84d4deaf5d618e94ecb Author: xuecong <> Date: Mon Nov 8 14:45:41 2021 +0800 v1.0.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b0877db --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pids +*.pid +*.seed +*.pid.lock +node_modules/ +.npm +dist +.DS_Store +*.swp +.cwfont.manifest +.ejyyrc diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..aa9ce4d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + +Copyright (C) 2007 Free Software Foundation, Inc. +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) <2017> <西安众邦网络科技有限公司> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..5b6f0e6 --- /dev/null +++ b/README.MD @@ -0,0 +1,126 @@ +![输入图片说明](readme/logo.jpg) + +

🔥🔥🔥「e家宜业」开源物业管理系统

+

+ 无加密,无阉割,喜欢的话就点右上角 "Star" 支持一下吧,每一个"Star",都是我们持续更新的动力! +

+ +## 项目介绍 + +「e家宜业」是一整套智慧物业解决方案。实现了微信公众号、小程序、PC、H5、智能硬件多端打通,旨在提升物业公司效率、规范物业服务流程、提升物业服务满意度、加强小区智慧化建设、便捷业主服务。 后端采用Koa + Typescript轻量级构建,支持分布式部署;前端使用vue + view-design开发。 + +希望通过开源促进产品的发展,能够结识有趣的灵魂,有想法的朋友。 + +官网地址:[https://ejyy.chowa.cn](https://ejyy.chowa.cn) +QQ交流群:786743759 + +## 技术亮点 + +* 自主独立研发,无阉割、无加密、真正的开源 +* web中台页面采用view-design开发,清爽易用 +* 轻量级开发方案,借助node.js高io、异步、cluster等特性 +* 完善的权限管理,精细到每一个菜单 +* 对接公众号和小程序,数据打通 +* 精细的ui界面和流畅的交互动画 +* 前后分离,二次开发方便 +* 支持定时任务和长连接 +* 可对接小区硬件设备 + +## 页面展示 + +### web端 +![web1](readme/web1.png) +![web2](readme/web2.jpg) +![web3](readme/web3.jpg) +![web4](readme/web4.jpg) +![web5](readme/web5.jpg) +![web6](readme/web6.jpg) +![web7](readme/web7.jpg) +![web8](readme/web8.jpg) +![web9](readme/web9.jpg) +![web10](readme/web10.jpg) +![web11](readme/web11.jpg) + +### 业主端 + +

+ + + + + + + + +

+ +### 员工端 +

+ + + + + +

+ +## 如何部署 + +### 服务器环境推荐要求 +* Nignx +* Node.js 12.1.0 +* MySQL 5.7 +* Redis + +### 部署文档 +- [部署前的准备](resource/README.MD) +- [服务端部署](server/README.MD) +- [web端部署](web/README.MD) +- [业主端小程序](ower-mp/README.MD) +- [员工端小程序](employee-mp/README.MD) +- [公众号模板消息](oa/README.MD) +- [短信消息模板](sms/README.MD) +- [小区硬件接入](iot/README.MD) +## 演示 + +### web中台 +> 演示版为saas多物业公司版本,小区开通上略有差异 + +[https://pc.ejyy.chowa.cn](https://pc.ejyy.chowa.cn) + +账号/密码:guest/guest123 + +### 微信公众号 +![oa](readme/oa-qrcode.jpg) + +### 业主小程序 +![oa](readme/ump-qrcode.jpg) + +### 物业员工小程序 +![oa](readme/pmp-qrcode.jpg) + + +## 开源版使用说明 + +1.允许用于个人学习、教学案例、公益事业; + +2.如果商用必须保留版权信息(请尊重开源,开源不易),请自觉遵守,未经授权修改版权信息后自负,如果需要去版权请进群联系管理员或者微信扫描下方二维码; + +3.禁止将本项目的代码和资源进行任何形式的出售,产生的一切任何后果责任由侵权者自负。 + + +## 参与开发 + +[欢迎反馈问题](https://github.com/chowa/ejyy/issues) +[欢迎提交代码](https://github.com/chowa/ejyy/pulls) + +## 定制和二次开发 + +>请加微信,请备注来意 + +![wechat](readme/author.jpg) + +## 支持 + +开源不易,欢迎给我打赏 ———— 以激励我持续更新和维护项目 + + diff --git a/employee-mp/.prettierignore b/employee-mp/.prettierignore new file mode 100644 index 0000000..225c381 --- /dev/null +++ b/employee-mp/.prettierignore @@ -0,0 +1,2 @@ +*.png +*.jpg diff --git a/employee-mp/README.MD b/employee-mp/README.MD new file mode 100644 index 0000000..1b9ac1c --- /dev/null +++ b/employee-mp/README.MD @@ -0,0 +1,34 @@ +## 「e家宜业」员工端小程序 + +> 请将本目录下`project.config.json`中的appid修改为对应的appid后发布,发布前记得前往小程序控制台配置api、上传下载白名单 + +### 配置文件 + +详见本目录下`src/config.js` + +```js +// 服务端域名 +export const API_HOST = ''; + +// 对象存储域名 +export const ASSETS_HOST = ''; + +// 本地存储 token 字段名 +export const TOKEN_NAME = 'EJYY-TOKEN'; + +// 本地存储 用户id 字段名 +export const USER_ID = 'USER_ID'; + +// 服务端权限认证字段(修改请修改服务端配置 token.pc) +export const AUTH_HEADER_NAME = 'ejyy-pc-token'; + +// 微信最低版本 +export const WECHAT_VERSION = '7.0.0'; + +// 微信sdk最低版本 +export const SDK_VERSION = '2.16.0'; + +// 小程序版本 +export const VERSION = '1.1.7'; + +``` diff --git a/employee-mp/package.json b/employee-mp/package.json new file mode 100644 index 0000000..e9dc723 --- /dev/null +++ b/employee-mp/package.json @@ -0,0 +1,9 @@ +{ + "name": "ejyy-employee-mp", + "version": "1.0.0", + "description": "员工端小程序", + "author": "jixuecong@chowa.cn", + "scripts": { + "lint": "prettier --write src/*.js src/* src/**/* src/**/**/* src/**/**/**/* src/**/**/**/**/*" + } +} diff --git a/employee-mp/prettier.config.js b/employee-mp/prettier.config.js new file mode 100644 index 0000000..48389cf --- /dev/null +++ b/employee-mp/prettier.config.js @@ -0,0 +1,32 @@ +module.exports = { + printWidth: 120, + tabWidth: 4, + useTabs: false, + singleQuote: true, + semi: true, + trailingComma: 'none', + bracketSpacing: true, + jsxBracketSameLine: false, + arrowParens: 'avoid', + htmlWhitespaceSensitivity: 'ignore', + overrides: [ + { + files: '*.wxml', + options: { + parser: 'html' + } + }, + { + files: '*.wxss', + options: { + parser: 'css' + } + }, + { + files: '*.wxs', + options: { + 'parser': 'babel' + } + } + ] +}; diff --git a/employee-mp/project.config.json b/employee-mp/project.config.json new file mode 100644 index 0000000..0cf8013 --- /dev/null +++ b/employee-mp/project.config.json @@ -0,0 +1,74 @@ +{ + "packOptions": { + "ignore": [] + }, + "miniprogramRoot": "src/", + "setting": { + "urlCheck": false, + "es6": true, + "enhance": false, + "postcss": true, + "preloadBackgroundData": false, + "minified": true, + "newFeature": true, + "coverView": true, + "nodeModules": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": false, + "scopeDataCheck": false, + "uglifyFileName": true, + "checkInvalidKey": true, + "checkSiteMap": true, + "uploadWithSourceMap": true, + "compileHotReLoad": false, + "lazyloadPlaceholderEnable": false, + "useMultiFrameRuntime": true, + "useApiHook": true, + "useApiHostProcess": true, + "babelSetting": { + "ignore": [], + "disablePlugins": [], + "outputPath": "" + }, + "enableEngineNative": false, + "useIsolateContext": true, + "userConfirmedBundleSwitch": false, + "packNpmManually": false, + "packNpmRelationList": [], + "minifyWXSS": true, + "disableUseStrict": false, + "showES6CompileOption": false, + "useCompilerPlugins": false + }, + "compileType": "miniprogram", + "libVersion": "2.16.0", + "appid": "wx66c9783ee867a8cb", + "projectname": "employee-mp@by ejyy", + "debugOptions": { + "hidedInDevtools": [] + }, + "isGameTourist": false, + "simulatorType": "wechat", + "simulatorPluginLibVersion": {}, + "condition": { + "search": { + "list": [] + }, + "conversation": { + "list": [] + }, + "plugin": { + "list": [] + }, + "game": { + "currentL": -1, + "list": [] + }, + "gamePlugin": { + "list": [] + }, + "miniprogram": { + "list": [] + } + } +} diff --git a/employee-mp/project.private.config.json b/employee-mp/project.private.config.json new file mode 100644 index 0000000..04d8e3e --- /dev/null +++ b/employee-mp/project.private.config.json @@ -0,0 +1,54 @@ +{ + "setting": {}, + "condition": { + "plugin": { + "list": [] + }, + "game": { + "list": [] + }, + "gamePlugin": { + "list": [] + }, + "miniprogram": { + "list": [ + { + "name": "pages/home/index", + "pathName": "pages/home/index", + "query": "", + "scene": 1011 + }, + { + "name": "pages/vistor/index", + "pathName": "pages/vistor/index", + "query": "", + "scene": null + }, + { + "name": "pages/home/repair", + "pathName": "pages/home/repair", + "query": "id=2", + "scene": null + }, + { + "name": "pages/home/index", + "pathName": "pages/home/index", + "query": "", + "scene": 1011 + }, + { + "name": "疫情", + "pathName": "pages/epidemic/index", + "query": "", + "scene": 1011 + }, + { + "name": "", + "pathName": "pages/material/index", + "query": "id=1", + "scene": null + } + ] + } + } +} \ No newline at end of file diff --git a/employee-mp/src/app.js b/employee-mp/src/app.js new file mode 100644 index 0000000..94fa1f7 --- /dev/null +++ b/employee-mp/src/app.js @@ -0,0 +1,163 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import utils from './utils/index'; + +App({ + data: { + globalFetching: true, + userInfo: { + access: [] + }, + postInfo: { + community_list: [], + default_community_id: null + }, + systemInfo: {}, + navBarHeight: 'auto' + }, + + onLaunch() { + // 检查更新 + this.checkUpdate(); + + // 适配 + this.adaptive(); + + // 检查网络 + this.checkNetwork(); + }, + + onShow(opts) { + if (utils.storage.isLogin()) { + this.getUserInfo(); + } else { + const query = []; + for (let key in opts.query) { + query.push(`${key}=${opts.query[key]}`); + } + const redirect = encodeURIComponent(`/${opts.path}${query.length ? '?' : ''}${query.join('&')}`); + + return wx.redirectTo({ + url: `/pages/login/index?redirect=${redirect}` + }); + } + }, + + onPageNotFound() { + wx.redirectTo({ + url: '/pages/error/general' + }); + }, + + checkUpdate() { + const updateManager = wx.getUpdateManager(); + + updateManager.onCheckForUpdate(res => { + if (!res.hasUpdate) { + return; + } + + wx.showLoading({ + title: '版本更新中…', + mask: true + }); + + updateManager.onUpdateReady(() => { + wx.hideLoading(); + wx.showModal({ + title: '更新提示', + content: '新版本已经准备好,是否重启应用?', + success(res) { + if (res.confirm) { + updateManager.applyUpdate(); + } + } + }); + }); + + updateManager.onUpdateFailed(() => { + wx.hideLoading(); + wx.showToast({ + title: '更新失败', + icon: 'error' + }); + }); + }); + }, + + adaptive() { + const systemInfo = wx.getSystemInfoSync(); + + // 导航胶囊 + const { top, height } = wx.getMenuButtonBoundingClientRect(); + + this.data.systemInfo = systemInfo; + this.data.systemInfo.navBarHeight = (top - systemInfo.statusBarHeight) * 2 + height; + }, + + checkNetwork() { + wx.getNetworkType({ + success: res => { + // 未连接网络 + if (res.networkType === 'none') { + wx.redirectTo({ url: '/pages/error/network' }); + } + } + }); + }, + + getUserInfo() { + return utils + .request({ + url: '/user/info', + method: 'get' + }) + .then(res => { + this.updateData({ + userInfo: res.data.userInfo, + postInfo: res.data.postInfo, + globalFetching: false + }); + }); + }, + + onDataFuns: [], + + on(event, fn) { + if (event === 'data') { + this.onDataFuns.push(fn); + this.dataEmitter(); + } + }, + off(event, fn) { + if (event === 'data') { + this.onDataFuns.splice( + this.onDataFuns.findIndex(rfn => fn === rfn), + 1 + ); + } + }, + dataEmitter() { + this.onDataFuns.forEach(fn => { + fn(this.data); + }); + }, + updateData(data) { + this.data = { + ...this.data, + ...data + }; + + this.dataEmitter(); + } +}); diff --git a/employee-mp/src/app.json b/employee-mp/src/app.json new file mode 100644 index 0000000..8e91f76 --- /dev/null +++ b/employee-mp/src/app.json @@ -0,0 +1,58 @@ +{ + "entryPagePath": "pages/home/index", + "pages": [ + "pages/home/index", + "pages/login/index", + "pages/error/network", + "pages/error/general", + "pages/repair/index", + "pages/repair/detail", + "pages/complain/index", + "pages/complain/detail", + "pages/colleague/index", + "pages/colleague/detail", + "pages/epidemic/index", + "pages/vistor/index", + "pages/mission/index", + "pages/mission/detail", + "pages/mission/submit", + "pages/mission/report", + "pages/ower/index", + "pages/ower/detail", + "pages/fitment/index", + "pages/move_car/index", + "pages/move_car/concat", + "pages/inform/index", + "pages/party/index", + "pages/meeting/index", + "pages/sign/begin", + "pages/sign/finish", + "pages/leave/approve", + "pages/leave/index", + "pages/refound/approve", + "pages/refound/index", + "pages/purchase/index", + "pages/purchase/approve", + "pages/party/detail", + "pages/inform/detail", + "pages/leave/detail", + "pages/purchase/detail", + "pages/refound/detail", + "pages/refound/item", + "pages/purchase/item", + "pages/material/index" + ], + "window": { + "navigationBarBackgroundColor": "#ffffff", + "navigationBarTextStyle": "black", + "navigationBarTitleText": "e家宜业物业端", + "backgroundColor": "#f7f8fa", + "backgroundTextStyle": "light" + }, + "permission": { + "scope.userLocation": { + "desc": "你的位置信息将用于上下班打卡功能" + } + }, + "sitemapLocation": "sitemap.json" +} diff --git a/employee-mp/src/app.wxss b/employee-mp/src/app.wxss new file mode 100644 index 0000000..272f4ed --- /dev/null +++ b/employee-mp/src/app.wxss @@ -0,0 +1,53 @@ +view, +image, +page, +input, +textarea, +swiper { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +video, +image { + display: block; +} + +.placeholder { + color: #c8c9cc; +} + +.section { + margin-top: 20px; +} + +.btn-ml { + margin-left: 10px; +} + +.container { + min-height: 100vh; + background: #f7f8fc; + position: relative; + overflow: hidden; + -webkit-font-smoothing: antialiased; + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); +} + +image { + width: 100%; + height: 100%; +} + +.load-more { + display: flex; + align-items: center; + justify-content: center; + padding: 16px 0; +} + +.text-lighter { + color: #999; +} diff --git a/employee-mp/src/assets/common/chowa.png b/employee-mp/src/assets/common/chowa.png new file mode 100644 index 0000000..02c658c Binary files /dev/null and b/employee-mp/src/assets/common/chowa.png differ diff --git a/employee-mp/src/assets/common/logo.png b/employee-mp/src/assets/common/logo.png new file mode 100644 index 0000000..353e5ea Binary files /dev/null and b/employee-mp/src/assets/common/logo.png differ diff --git a/employee-mp/src/assets/login/welcome.jpg b/employee-mp/src/assets/login/welcome.jpg new file mode 100644 index 0000000..1839ee8 Binary files /dev/null and b/employee-mp/src/assets/login/welcome.jpg differ diff --git a/employee-mp/src/assets/recommand.jpg b/employee-mp/src/assets/recommand.jpg new file mode 100644 index 0000000..9990534 Binary files /dev/null and b/employee-mp/src/assets/recommand.jpg differ diff --git a/employee-mp/src/components/action-sheet/index.js b/employee-mp/src/components/action-sheet/index.js new file mode 100644 index 0000000..969ff68 --- /dev/null +++ b/employee-mp/src/components/action-sheet/index.js @@ -0,0 +1,74 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType } from '../mixins/open-type'; +CwComponent({ + mixins: [button, openType], + props: { + show: Boolean, + title: String, + cancelText: String, + description: String, + round: { + type: Boolean, + value: true + }, + zIndex: { + type: Number, + value: 100 + }, + actions: { + type: Array, + value: [] + }, + overlay: { + type: Boolean, + value: true + }, + closeOnClickOverlay: { + type: Boolean, + value: true + }, + closeOnClickAction: { + type: Boolean, + value: true + }, + safeAreaInsetBottom: { + type: Boolean, + value: true + } + }, + methods: { + onSelect(event) { + const { index } = event.currentTarget.dataset; + const item = this.data.actions[index]; + if (item && !item.disabled && !item.loading) { + this.$emit('select', item); + if (this.data.closeOnClickAction) { + this.onClose(); + } + } + }, + onCancel() { + this.$emit('cancel'); + }, + onClose() { + this.$emit('close'); + }, + onClickOverlay() { + this.$emit('click-overlay'); + this.onClose(); + } + } +}); diff --git a/employee-mp/src/components/action-sheet/index.json b/employee-mp/src/components/action-sheet/index.json new file mode 100644 index 0000000..87be8cb --- /dev/null +++ b/employee-mp/src/components/action-sheet/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon/index", + "cw-popup": "../popup/index", + "cw-loading": "../loading/index" + } +} diff --git a/employee-mp/src/components/action-sheet/index.wxml b/employee-mp/src/components/action-sheet/index.wxml new file mode 100644 index 0000000..53ac4fa --- /dev/null +++ b/employee-mp/src/components/action-sheet/index.wxml @@ -0,0 +1,65 @@ + + + + + {{ title }} + + + + {{ description }} + + + + + + + + + + {{ cancelText }} + + + diff --git a/employee-mp/src/components/action-sheet/index.wxss b/employee-mp/src/components/action-sheet/index.wxss new file mode 100644 index 0000000..8a694ed --- /dev/null +++ b/employee-mp/src/components/action-sheet/index.wxss @@ -0,0 +1,80 @@ +@import '../common/index.wxss'; + +.cw-action-sheet { + max-height: 90% !important; + color: #323233; +} + +.cw-action-sheet__cancel, +.cw-action-sheet__item { + padding: 14px 16px; + text-align: center; + font-size: 16px; + line-height: 22px; + background-color: #fff; +} + +.cw-action-sheet__cancel--hover, +.cw-action-sheet__item--hover { + background-color: #f2f3f5; +} + +.cw-action-sheet__cancel:after, +.cw-action-sheet__item:after { + border-width: 0; +} + +.cw-action-sheet__cancel { + color: #646566; +} + +.cw-action-sheet__gap { + display: block; + height: 8px; + background-color: #f7f8fa; +} + +.cw-action-sheet__item--disabled { + color: #c8c9cc; +} + +.cw-action-sheet__item--disabled.cw-action-sheet__item--hover { + background-color: #fff; +} + +.cw-action-sheet__subname { + margin-top: 8px; + font-size: 12px; + color: #969799; + line-height: 20px; +} + +.cw-action-sheet__header { + text-align: center; + font-weight: 500; + font-size: 16px; + line-height: 48px; +} + +.cw-action-sheet__description { + text-align: center; + padding: 20px 16px; + color: #969799; + font-size: 14px; + line-height: 20px; +} + +.cw-action-sheet__close { + position: absolute !important; + top: 0; + right: 0; + line-height: inherit !important; + padding: 0 16px; + font-size: 22px !important; + color: #c8c9cc; +} + +.cw-action-sheet__loading { + display: -webkit-flex !important; + display: flex !important; +} diff --git a/employee-mp/src/components/button/index.js b/employee-mp/src/components/button/index.js new file mode 100644 index 0000000..4c65d37 --- /dev/null +++ b/employee-mp/src/components/button/index.js @@ -0,0 +1,70 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType } from '../mixins/open-type'; +import { canIUseFormFieldButton } from '../common/version'; +const mixins = [button, openType]; +if (canIUseFormFieldButton()) { + mixins.push('wx://form-field-button'); +} +CwComponent({ + mixins, + classes: ['hover-class', 'loading-class'], + data: { + baseStyle: '' + }, + props: { + formType: String, + icon: String, + classPrefix: { + type: String, + value: 'cw-icon' + }, + plain: Boolean, + block: Boolean, + round: Boolean, + square: Boolean, + loading: Boolean, + hairline: Boolean, + disabled: Boolean, + loadingText: String, + customStyle: String, + loadingType: { + type: String, + value: 'circular' + }, + type: { + type: String, + value: 'default' + }, + dataset: null, + size: { + type: String, + value: 'normal' + }, + loadingSize: { + type: String, + value: '20px' + }, + color: String + }, + methods: { + onClick() { + if (!this.data.loading) { + this.$emit('click'); + } + }, + noop() {} + } +}); diff --git a/employee-mp/src/components/button/index.json b/employee-mp/src/components/button/index.json new file mode 100644 index 0000000..8b00ed6 --- /dev/null +++ b/employee-mp/src/components/button/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon/index", + "cw-loading": "../loading/index" + } +} diff --git a/employee-mp/src/components/button/index.wxml b/employee-mp/src/components/button/index.wxml new file mode 100644 index 0000000..a237571 --- /dev/null +++ b/employee-mp/src/components/button/index.wxml @@ -0,0 +1,53 @@ + + + + diff --git a/employee-mp/src/components/button/index.wxs b/employee-mp/src/components/button/index.wxs new file mode 100644 index 0000000..76c5358 --- /dev/null +++ b/employee-mp/src/components/button/index.wxs @@ -0,0 +1,38 @@ +var style = require('../wxs/style.wxs'); + +function rootStyle(data) { + if (!data.color) { + return data.customStyle; + } + + var properties = { + color: data.plain ? data.color : '#fff', + background: data.plain ? null : data.color + }; + + // hide border when color is linear-gradient + if (data.color.indexOf('gradient') !== -1) { + properties.border = 0; + } else { + properties['border-color'] = data.color; + } + + return style([properties, data.customStyle]); +} + +function loadingColor(data) { + if (data.plain) { + return data.color ? data.color : '#c9c9c9'; + } + + if (data.type === 'default') { + return '#c9c9c9'; + } + + return '#fff'; +} + +module.exports = { + rootStyle: rootStyle, + loadingColor: loadingColor +}; diff --git a/employee-mp/src/components/button/index.wxss b/employee-mp/src/components/button/index.wxss new file mode 100644 index 0000000..d3fdf18 --- /dev/null +++ b/employee-mp/src/components/button/index.wxss @@ -0,0 +1,180 @@ +@import '../common/index.wxss'; + +.cw-button { + position: relative; + display: -webkit-inline-flex; + display: inline-flex; + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center; + box-sizing: border-box; + padding: 0; + text-align: center; + vertical-align: middle; + -webkit-appearance: none; + -webkit-text-size-adjust: 100%; + height: 44px; + line-height: 20px; + font-size: 16px; + transition: opacity 0.2s; + border-radius: 2px; +} + +.cw-button:before { + position: absolute; + top: 50%; + left: 50%; + width: 100%; + height: 100%; + border: inherit; + border-radius: inherit; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + opacity: 0; + content: ' '; + background-color: #000; + border-color: #000; +} + +.cw-button:after { + border-width: 0; +} + +.cw-button--active:before { + opacity: 0.15; +} + +.cw-button--unclickable:after { + display: none; +} + +.cw-button--default { + color: #323233; + background: #fff; + border: 1px solid #ebedf0; +} + +.cw-button--primary { + color: #fff; + background: #07c160; + border: 1px solid #07c160; +} + +.cw-button--info { + color: #fff; + background: #1989fa; + border: 1px solid #1989fa; +} + +.cw-button--danger { + color: #fff; + background: #ee0a24; + border: 1px solid #ee0a24; +} + +.cw-button--warning { + color: #fff; + background: #ff976a; + border: 1px solid #ff976a; +} + +.cw-button--plain { + background: #fff; +} + +.cw-button--plain.cw-button--primary { + color: #07c160; +} + +.cw-button--plain.cw-button--info { + color: #1989fa; +} + +.cw-button--plain.cw-button--danger { + color: #ee0a24; +} + +.cw-button--plain.cw-button--warning { + color: #ff976a; +} + +.cw-button--large { + width: 100%; + height: 50px; +} + +.cw-button--normal { + padding: 0 15px; + font-size: 14px; +} + +.cw-button--small { + min-width: 60px; + height: 30px; + padding: 0 8px; + font-size: 12px; +} + +.cw-button--mini { + display: inline-block; + min-width: 50px; + height: 22px; + font-size: 10px; +} + +.cw-button--mini + .cw-button--mini { + margin-left: 5px; +} + +.cw-button--block { + display: -webkit-flex; + display: flex; + width: 100%; +} + +.cw-button--round { + border-radius: 999px; +} + +.cw-button--square { + border-radius: 0; +} + +.cw-button--disabled { + opacity: 0.5; +} + +.cw-button__text { + display: inline; +} + +.cw-button__icon + .cw-button__text:not(:empty), +.cw-button__loading-text { + margin-left: 4px; +} + +.cw-button__icon { + min-width: 1em; + line-height: inherit !important; + vertical-align: top; +} + +.cw-button--hairline { + padding-top: 1px; + border-width: 0; +} + +.cw-button--hairline:after { + border-color: inherit; + border-width: 1px; + border-radius: 4px; +} + +.cw-button--hairline.cw-button--round:after { + border-radius: 999px; +} + +.cw-button--hairline.cw-button--square:after { + border-radius: 0; +} diff --git a/employee-mp/src/components/calendar/calendar.wxml b/employee-mp/src/components/calendar/calendar.wxml new file mode 100644 index 0000000..64825bb --- /dev/null +++ b/employee-mp/src/components/calendar/calendar.wxml @@ -0,0 +1,48 @@ + +
+ +
+ + + + + + + + + + + + {{ computed.getButtonDisabled(type, currentDate) ? confirmDisabledText : confirmText }} + + +
diff --git a/employee-mp/src/components/calendar/components/header/index.js b/employee-mp/src/components/calendar/components/header/index.js new file mode 100644 index 0000000..ebbb18d --- /dev/null +++ b/employee-mp/src/components/calendar/components/header/index.js @@ -0,0 +1,28 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../../../common/component'; +CwComponent({ + props: { + title: { + type: String, + value: '日期选择' + }, + subtitle: String, + showTitle: Boolean, + showSubtitle: Boolean + }, + data: { + weekdays: ['日', '一', '二', '三', '四', '五', '六'] + }, + methods: {} +}); diff --git a/employee-mp/src/components/calendar/components/header/index.json b/employee-mp/src/components/calendar/components/header/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/calendar/components/header/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/calendar/components/header/index.wxml b/employee-mp/src/components/calendar/components/header/index.wxml new file mode 100644 index 0000000..242fbe6 --- /dev/null +++ b/employee-mp/src/components/calendar/components/header/index.wxml @@ -0,0 +1,16 @@ + + + + {{ title }} + + + + {{ subtitle }} + + + + + {{ item }} + + + diff --git a/employee-mp/src/components/calendar/components/header/index.wxss b/employee-mp/src/components/calendar/components/header/index.wxss new file mode 100644 index 0000000..9f06053 --- /dev/null +++ b/employee-mp/src/components/calendar/components/header/index.wxss @@ -0,0 +1,37 @@ +@import '../../../common/index.wxss'; + +.cw-calendar__header { + -webkit-flex-shrink: 0; + flex-shrink: 0; + box-shadow: 0 2px 10px rgba(125, 126, 128, 0.16); +} + +.cw-calendar__header-subtitle, +.cw-calendar__header-title { + text-align: center; + height: 44px; + font-weight: 500; + line-height: 44px; +} + +.cw-calendar__header-title + .cw-calendar__header-title, +.cw-calendar__header-title:empty { + display: none; +} + +.cw-calendar__header-title:empty + .cw-calendar__header-title { + display: block !important; +} + +.cw-calendar__weekdays { + display: -webkit-flex; + display: flex; +} + +.cw-calendar__weekday { + -webkit-flex: 1; + flex: 1; + text-align: center; + font-size: 12px; + line-height: 30px; +} diff --git a/employee-mp/src/components/calendar/components/month/index.js b/employee-mp/src/components/calendar/components/month/index.js new file mode 100644 index 0000000..ee50515 --- /dev/null +++ b/employee-mp/src/components/calendar/components/month/index.js @@ -0,0 +1,160 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../../../common/component'; +import { getMonthEndDay, compareDay, getPrevDay, getNextDay } from '../../utils'; +CwComponent({ + props: { + date: { + type: null, + observer: 'setDays' + }, + type: { + type: String, + observer: 'setDays' + }, + color: String, + minDate: { + type: null, + observer: 'setDays' + }, + maxDate: { + type: null, + observer: 'setDays' + }, + showMark: Boolean, + rowHeight: null, + formatter: { + type: null, + observer: 'setDays' + }, + currentDate: { + type: null, + observer: 'setDays' + }, + allowSameDay: Boolean, + showSubtitle: Boolean, + showMonthTitle: Boolean + }, + data: { + visible: true, + days: [] + }, + methods: { + onClick(event) { + const { index } = event.currentTarget.dataset; + const item = this.data.days[index]; + if (item.type !== 'disabled') { + this.$emit('click', item); + } + }, + setDays() { + const days = []; + const startDate = new Date(this.data.date); + const year = startDate.getFullYear(); + const month = startDate.getMonth(); + const totalDay = getMonthEndDay(startDate.getFullYear(), startDate.getMonth() + 1); + for (let day = 1; day <= totalDay; day++) { + const date = new Date(year, month, day); + const type = this.getDayType(date); + let config = { + date, + type, + text: day, + bottomInfo: this.getBottomInfo(type) + }; + if (this.data.formatter) { + config = this.data.formatter(config); + } + days.push(config); + } + this.setData({ days }); + }, + getMultipleDayType(day) { + const { currentDate } = this.data; + if (!Array.isArray(currentDate)) { + return ''; + } + const isSelected = date => currentDate.some(item => compareDay(item, date) === 0); + if (isSelected(day)) { + const prevDay = getPrevDay(day); + const nextDay = getNextDay(day); + const prevSelected = isSelected(prevDay); + const nextSelected = isSelected(nextDay); + if (prevSelected && nextSelected) { + return 'multiple-middle'; + } + if (prevSelected) { + return 'end'; + } + return nextSelected ? 'start' : 'multiple-selected'; + } + return ''; + }, + getRangeDayType(day) { + const { currentDate, allowSameDay } = this.data; + if (!Array.isArray(currentDate)) { + return; + } + const [startDay, endDay] = currentDate; + if (!startDay) { + return; + } + const compareToStart = compareDay(day, startDay); + if (!endDay) { + return compareToStart === 0 ? 'start' : ''; + } + const compareToEnd = compareDay(day, endDay); + if (compareToStart === 0 && compareToEnd === 0 && allowSameDay) { + return 'start-end'; + } + if (compareToStart === 0) { + return 'start'; + } + if (compareToEnd === 0) { + return 'end'; + } + if (compareToStart > 0 && compareToEnd < 0) { + return 'middle'; + } + }, + getDayType(day) { + const { type, minDate, maxDate, currentDate } = this.data; + if (compareDay(day, minDate) < 0 || compareDay(day, maxDate) > 0) { + return 'disabled'; + } + if (type === 'single') { + return compareDay(day, currentDate) === 0 ? 'selected' : ''; + } + if (type === 'multiple') { + return this.getMultipleDayType(day); + } + /* istanbul ignore else */ + if (type === 'range') { + return this.getRangeDayType(day); + } + }, + getBottomInfo(type) { + if (this.data.type === 'range') { + if (type === 'start') { + return '开始'; + } + if (type === 'end') { + return '结束'; + } + if (type === 'start-end') { + return '开始/结束'; + } + } + } + } +}); diff --git a/employee-mp/src/components/calendar/components/month/index.json b/employee-mp/src/components/calendar/components/month/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/calendar/components/month/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/calendar/components/month/index.wxml b/employee-mp/src/components/calendar/components/month/index.wxml new file mode 100644 index 0000000..468ebb2 --- /dev/null +++ b/employee-mp/src/components/calendar/components/month/index.wxml @@ -0,0 +1,43 @@ + + + + + + {{ computed.formatMonthTitle(date) }} + + + + + {{ computed.getMark(date) }} + + + + + {{ item.topInfo }} + {{ item.text }} + + {{ item.bottomInfo }} + + + + + {{ item.topInfo }} + {{ item.text }} + + {{ item.bottomInfo }} + + + + + diff --git a/employee-mp/src/components/calendar/components/month/index.wxs b/employee-mp/src/components/calendar/components/month/index.wxs new file mode 100644 index 0000000..38f4dec --- /dev/null +++ b/employee-mp/src/components/calendar/components/month/index.wxs @@ -0,0 +1,58 @@ +var utils = require('../../utils.wxs'); + +function getMark(date) { + return getDate(date).getMonth() + 1; +} + +var ROW_HEIGHT = 64; + +function getDayStyle(type, index, date, rowHeight, color) { + var style = []; + var offset = getDate(date).getDay(); + + if (index === 0) { + style.push(['margin-left', (100 * offset) / 7 + '%']); + } + + if (rowHeight !== ROW_HEIGHT) { + style.push(['height', rowHeight + 'px']); + } + + if (color) { + if (type === 'start' || type === 'end' || type === 'multiple-selected' || type === 'multiple-middle') { + style.push(['background', color]); + } else if (type === 'middle') { + style.push(['color', color]); + } + } + + return style + .map(function(item) { + return item.join(':'); + }) + .join(';'); +} + +function formatMonthTitle(date) { + date = getDate(date); + return date.getFullYear() + '年' + (date.getMonth() + 1) + '月'; +} + +function getMonthStyle(visible, date, rowHeight) { + if (!visible) { + date = getDate(date); + + var totalDay = utils.getMonthEndDay(date.getFullYear(), date.getMonth() + 1); + var offset = getDate(date).getDay(); + var padding = Math.ceil((totalDay + offset) / 7) * rowHeight; + + return 'padding-bottom:' + padding + 'px'; + } +} + +module.exports = { + getMark: getMark, + getDayStyle: getDayStyle, + formatMonthTitle: formatMonthTitle, + getMonthStyle: getMonthStyle +}; diff --git a/employee-mp/src/components/calendar/components/month/index.wxss b/employee-mp/src/components/calendar/components/month/index.wxss new file mode 100644 index 0000000..72c14e7 --- /dev/null +++ b/employee-mp/src/components/calendar/components/month/index.wxss @@ -0,0 +1,132 @@ +@import '../../../common/index.wxss'; + +.cw-calendar { + display: -webkit-flex; + display: flex; + -webkit-flex-direction: column; + flex-direction: column; + height: 100%; + background-color: #fff; +} + +.cw-calendar__month-title { + text-align: center; + height: 44px; + font-weight: 500; + font-size: 14px; + line-height: 44px; +} + +.cw-calendar__days { + position: relative; + display: -webkit-flex; + display: flex; + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + -webkit-user-select: none; + user-select: none; +} + +.cw-calendar__month-mark { + position: absolute; + top: 50%; + left: 50%; + z-index: 0; + -webkit-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); + pointer-events: none; + color: rgba(242, 243, 245, 0.8); + font-size: 160px; +} + +.cw-calendar__day, +.cw-calendar__selected-day { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center; + text-align: center; +} + +.cw-calendar__day { + position: relative; + width: 14.285%; + height: 64px; + font-size: 16px; +} + +.cw-calendar__day--end, +.cw-calendar__day--multiple-middle, +.cw-calendar__day--multiple-selected, +.cw-calendar__day--start, +.cw-calendar__day--start-end { + color: #fff; + background-color: #ee0a24; +} + +.cw-calendar__day--start { + border-radius: 4px 0 0 4px; +} + +.cw-calendar__day--end { + border-radius: 0 4px 4px 0; +} + +.cw-calendar__day--multiple-selected, +.cw-calendar__day--start-end { + border-radius: 4px; +} + +.cw-calendar__day--middle { + color: #ee0a24; +} + +.cw-calendar__day--middle:after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-color: currentColor; + content: ''; + opacity: 0.1; +} + +.cw-calendar__day--disabled { + cursor: default; + color: #c8c9cc; +} + +.cw-calendar__bottom-info, +.cw-calendar__top-info { + position: absolute; + right: 0; + left: 0; + font-size: 10px; + line-height: 14px; +} + +@media (max-width: 350px) { + .cw-calendar__bottom-info, + .cw-calendar__top-info { + font-size: 9px; + } +} + +.cw-calendar__top-info { + top: 6px; +} + +.cw-calendar__bottom-info { + bottom: 6px; +} + +.cw-calendar__selected-day { + width: 54px; + height: 54px; + color: #fff; + background-color: #ee0a24; + border-radius: 4px; +} diff --git a/employee-mp/src/components/calendar/index.js b/employee-mp/src/components/calendar/index.js new file mode 100644 index 0000000..6d43a7f --- /dev/null +++ b/employee-mp/src/components/calendar/index.js @@ -0,0 +1,289 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { + ROW_HEIGHT, + getNextDay, + compareDay, + copyDates, + calcDateNum, + formatMonthTitle, + compareMonth, + getMonths, + getDayByOffset +} from './utils'; +import Toast from '../toast/toast'; +import { requestAnimationFrame } from '../common/utils'; +CwComponent({ + props: { + title: { + type: String, + value: '日期选择' + }, + color: String, + show: { + type: Boolean, + observer(val) { + if (val) { + this.initRect(); + this.scrollIntoView(); + } + } + }, + formatter: null, + confirmText: { + type: String, + value: '确定' + }, + rangePrompt: String, + defaultDate: { + type: null, + observer(val) { + this.setData({ currentDate: val }); + this.scrollIntoView(); + } + }, + allowSameDay: Boolean, + confirmDisabledText: String, + type: { + type: String, + value: 'single', + observer: 'reset' + }, + minDate: { + type: null, + value: Date.now() + }, + maxDate: { + type: null, + value: new Date(new Date().getFullYear(), new Date().getMonth() + 6, new Date().getDate()).getTime() + }, + position: { + type: String, + value: 'bottom' + }, + rowHeight: { + type: null, + value: ROW_HEIGHT + }, + round: { + type: Boolean, + value: true + }, + poppable: { + type: Boolean, + value: true + }, + showMark: { + type: Boolean, + value: true + }, + showTitle: { + type: Boolean, + value: true + }, + showConfirm: { + type: Boolean, + value: true + }, + showSubtitle: { + type: Boolean, + value: true + }, + safeAreaInsetBottom: { + type: Boolean, + value: true + }, + closeOnClickOverlay: { + type: Boolean, + value: true + }, + maxRange: { + type: null, + value: null + } + }, + data: { + subtitle: '', + currentDate: null, + scrollIntoView: '' + }, + created() { + this.setData({ + currentDate: this.getInitialDate() + }); + }, + mounted() { + if (this.data.show || !this.data.poppable) { + this.initRect(); + this.scrollIntoView(); + } + }, + methods: { + reset() { + this.setData({ currentDate: this.getInitialDate() }); + this.scrollIntoView(); + }, + initRect() { + if (this.contentObserver != null) { + this.contentObserver.disconnect(); + } + const contentObserver = this.createIntersectionObserver({ + thresholds: [0, 0.1, 0.9, 1], + observeAll: true + }); + this.contentObserver = contentObserver; + contentObserver.relativeTo('.cw-calendar__body'); + contentObserver.observe('.month', res => { + if (res.boundingClientRect.top <= res.relativeRect.top) { + // @ts-ignore + this.setData({ subtitle: formatMonthTitle(res.dataset.date) }); + } + }); + }, + getInitialDate() { + const { type, defaultDate, minDate } = this.data; + if (type === 'range') { + const [startDay, endDay] = defaultDate || []; + return [startDay || minDate, endDay || getNextDay(new Date(minDate)).getTime()]; + } + if (type === 'multiple') { + return defaultDate || [minDate]; + } + return defaultDate || minDate; + }, + scrollIntoView() { + requestAnimationFrame(() => { + const { currentDate, type, show, poppable, minDate, maxDate } = this.data; + // @ts-ignore + const targetDate = type === 'single' ? currentDate : currentDate[0]; + const displayed = show || !poppable; + if (!targetDate || !displayed) { + return; + } + const months = getMonths(minDate, maxDate); + months.some((month, index) => { + if (compareMonth(month, targetDate) === 0) { + this.setData({ scrollIntoView: `month${index}` }); + return true; + } + return false; + }); + }); + }, + onOpen() { + this.$emit('open'); + }, + onOpened() { + this.$emit('opened'); + }, + onClose() { + this.$emit('close'); + }, + onClosed() { + this.$emit('closed'); + }, + onClickDay(event) { + const { date } = event.detail; + const { type, currentDate, allowSameDay } = this.data; + if (type === 'range') { + // @ts-ignore + const [startDay, endDay] = currentDate; + if (startDay && !endDay) { + const compareToStart = compareDay(date, startDay); + if (compareToStart === 1) { + this.select([startDay, date], true); + } else if (compareToStart === -1) { + this.select([date, null]); + } else if (allowSameDay) { + this.select([date, date]); + } + } else { + this.select([date, null]); + } + } else if (type === 'multiple') { + let selectedIndex; + // @ts-ignore + const selected = currentDate.some((dateItem, index) => { + const equal = compareDay(dateItem, date) === 0; + if (equal) { + selectedIndex = index; + } + return equal; + }); + if (selected) { + // @ts-ignore + const cancelDate = currentDate.splice(selectedIndex, 1); + this.setData({ currentDate }); + this.unselect(cancelDate); + } else { + // @ts-ignore + this.select([...currentDate, date]); + } + } else { + this.select(date, true); + } + }, + unselect(dateArray) { + const date = dateArray[0]; + if (date) { + this.$emit('unselect', copyDates(date)); + } + }, + select(date, complete) { + if (complete && this.data.type === 'range') { + const valid = this.checkRange(date); + if (!valid) { + // auto selected to max range if showConfirm + if (this.data.showConfirm) { + this.emit([date[0], getDayByOffset(date[0], this.data.maxRange - 1)]); + } else { + this.emit(date); + } + return; + } + } + this.emit(date); + if (complete && !this.data.showConfirm) { + this.onConfirm(); + } + }, + emit(date) { + const getTime = date => (date instanceof Date ? date.getTime() : date); + this.setData({ + currentDate: Array.isArray(date) ? date.map(getTime) : getTime(date) + }); + this.$emit('select', copyDates(date)); + }, + checkRange(date) { + const { maxRange, rangePrompt } = this.data; + if (maxRange && calcDateNum(date) > maxRange) { + Toast({ + context: this, + message: rangePrompt || `选择天数不能超过 ${maxRange} 天` + }); + return false; + } + return true; + }, + onConfirm() { + if (this.data.type === 'range' && !this.checkRange(this.data.currentDate)) { + return; + } + wx.nextTick(() => { + // @ts-ignore + this.$emit('confirm', copyDates(this.data.currentDate)); + }); + } + } +}); diff --git a/employee-mp/src/components/calendar/index.json b/employee-mp/src/components/calendar/index.json new file mode 100644 index 0000000..02c03b3 --- /dev/null +++ b/employee-mp/src/components/calendar/index.json @@ -0,0 +1,10 @@ +{ + "component": true, + "usingComponents": { + "header": "./components/header/index", + "month": "./components/month/index", + "cw-button": "../button/index", + "cw-popup": "../popup/index", + "cw-toast": "../toast/index" + } +} diff --git a/employee-mp/src/components/calendar/index.wxml b/employee-mp/src/components/calendar/index.wxml new file mode 100644 index 0000000..2a09586 --- /dev/null +++ b/employee-mp/src/components/calendar/index.wxml @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/employee-mp/src/components/calendar/index.wxs b/employee-mp/src/components/calendar/index.wxs new file mode 100644 index 0000000..9829f71 --- /dev/null +++ b/employee-mp/src/components/calendar/index.wxs @@ -0,0 +1,36 @@ +var utils = require('./utils.wxs'); + +function getMonths(minDate, maxDate) { + var months = []; + var cursor = getDate(minDate); + + cursor.setDate(1); + + do { + months.push(cursor.getTime()); + cursor.setMonth(cursor.getMonth() + 1); + } while (utils.compareMonth(cursor, getDate(maxDate)) !== 1); + + return months; +} + +function getButtonDisabled(type, currentDate) { + if (currentDate == null) { + return true; + } + + if (type === 'range') { + return !currentDate[0] || !currentDate[1]; + } + + if (type === 'multiple') { + return !currentDate.length; + } + + return !currentDate; +} + +module.exports = { + getMonths: getMonths, + getButtonDisabled: getButtonDisabled +}; diff --git a/employee-mp/src/components/calendar/index.wxss b/employee-mp/src/components/calendar/index.wxss new file mode 100644 index 0000000..69b368d --- /dev/null +++ b/employee-mp/src/components/calendar/index.wxss @@ -0,0 +1,56 @@ +@import '../common/index.wxss'; + +.cw-calendar { + display: -webkit-flex; + display: flex; + -webkit-flex-direction: column; + flex-direction: column; + height: 100%; + background-color: #fff; +} + +.cw-calendar__close-icon { + top: 11px; +} + +.cw-calendar__popup--bottom, +.cw-calendar__popup--top { + height: 80%; +} + +.cw-calendar__popup--left, +.cw-calendar__popup--right { + height: 100%; +} + +.cw-calendar__body { + -webkit-flex: 1; + flex: 1; + overflow: auto; + -webkit-overflow-scrolling: touch; +} + +.cw-calendar__footer { + -webkit-flex-shrink: 0; + flex-shrink: 0; + padding: 0 16px; +} + +.cw-calendar__footer--safe-area-inset-bottom { + padding-bottom: env(safe-area-inset-bottom); +} + +.cw-calendar__footer + .cw-calendar__footer, +.cw-calendar__footer:empty { + display: none; +} + +.cw-calendar__footer:empty + .cw-calendar__footer { + display: block !important; +} + +.cw-calendar__confirm { + height: 36px !important; + margin: 7px 0 !important; + line-height: 34px !important; +} diff --git a/employee-mp/src/components/calendar/utils.js b/employee-mp/src/components/calendar/utils.js new file mode 100644 index 0000000..34af769 --- /dev/null +++ b/employee-mp/src/components/calendar/utils.js @@ -0,0 +1,90 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export const ROW_HEIGHT = 64; +export function formatMonthTitle(date) { + if (!(date instanceof Date)) { + date = new Date(date); + } + return `${date.getFullYear()}年${date.getMonth() + 1}月`; +} +export function compareMonth(date1, date2) { + if (!(date1 instanceof Date)) { + date1 = new Date(date1); + } + if (!(date2 instanceof Date)) { + date2 = new Date(date2); + } + const year1 = date1.getFullYear(); + const year2 = date2.getFullYear(); + const month1 = date1.getMonth(); + const month2 = date2.getMonth(); + if (year1 === year2) { + return month1 === month2 ? 0 : month1 > month2 ? 1 : -1; + } + return year1 > year2 ? 1 : -1; +} +export function compareDay(day1, day2) { + if (!(day1 instanceof Date)) { + day1 = new Date(day1); + } + if (!(day2 instanceof Date)) { + day2 = new Date(day2); + } + const compareMonthResult = compareMonth(day1, day2); + if (compareMonthResult === 0) { + const date1 = day1.getDate(); + const date2 = day2.getDate(); + return date1 === date2 ? 0 : date1 > date2 ? 1 : -1; + } + return compareMonthResult; +} +export function getDayByOffset(date, offset) { + date = new Date(date); + date.setDate(date.getDate() + offset); + return date; +} +export function getPrevDay(date) { + return getDayByOffset(date, -1); +} +export function getNextDay(date) { + return getDayByOffset(date, 1); +} +export function calcDateNum(date) { + const day1 = new Date(date[0]).getTime(); + const day2 = new Date(date[1]).getTime(); + return (day2 - day1) / (1000 * 60 * 60 * 24) + 1; +} +export function copyDates(dates) { + if (Array.isArray(dates)) { + return dates.map(date => { + if (date === null) { + return date; + } + return new Date(date); + }); + } + return new Date(dates); +} +export function getMonthEndDay(year, month) { + return 32 - new Date(year, month - 1, 32).getDate(); +} +export function getMonths(minDate, maxDate) { + const months = []; + const cursor = new Date(minDate); + cursor.setDate(1); + do { + months.push(cursor.getTime()); + cursor.setMonth(cursor.getMonth() + 1); + } while (compareMonth(cursor, maxDate) !== 1); + return months; +} diff --git a/employee-mp/src/components/calendar/utils.wxs b/employee-mp/src/components/calendar/utils.wxs new file mode 100644 index 0000000..8574070 --- /dev/null +++ b/employee-mp/src/components/calendar/utils.wxs @@ -0,0 +1,24 @@ +function getMonthEndDay(year, month) { + return 32 - getDate(year, month - 1, 32).getDate(); +} + +function compareMonth(date1, date2) { + date1 = getDate(date1); + date2 = getDate(date2); + + var year1 = date1.getFullYear(); + var year2 = date2.getFullYear(); + var month1 = date1.getMonth(); + var month2 = date2.getMonth(); + + if (year1 === year2) { + return month1 === month2 ? 0 : month1 > month2 ? 1 : -1; + } + + return year1 > year2 ? 1 : -1; +} + +module.exports = { + getMonthEndDay: getMonthEndDay, + compareMonth: compareMonth +}; diff --git a/employee-mp/src/components/car-number/index.js b/employee-mp/src/components/car-number/index.js new file mode 100644 index 0000000..2cbcd92 --- /dev/null +++ b/employee-mp/src/components/car-number/index.js @@ -0,0 +1,103 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; + +CwComponent({ + props: { + isNewEnergy: Boolean + }, + data: { + // 省份简写 + provinces: [ + ['京', '沪', '粤', '津', '冀', '晋', '蒙', '辽', '吉', '黑'], + ['苏', '浙', '皖', '闽', '赣', '鲁', '豫', '鄂', '湘'], + ['桂', '琼', '渝', '川', '贵', '云', '藏'], + ['陕', '甘', '青', '宁', '新'] + ], + // 车牌输入 + numbers: [ + ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'], + ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K'], + ['L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V'], + ['W', 'X', 'Y', 'Z', '港', '澳', '学'] + ], + carNumber: [], + keyboardVisible: false + }, + methods: { + // 选中点击设置 + bindChoose(e) { + const { carNumber, isNewEnergy } = this.data; + + if ((carNumber.length === 7 && !isNewEnergy) || (carNumber.length === 8 && isNewEnergy)) { + return; + } + + this.setData( + { + carNumber: carNumber.concat(e.target.dataset.val) + }, + () => { + if ( + (this.data.carNumber.length === 7 && !isNewEnergy) || + (this.data.carNumber.length === 8 && isNewEnergy) + ) { + this.$emit('change', this.data.carNumber.join('')); + } else { + this.$emit('change', ''); + } + } + ); + }, + bindDelChoose() { + const { carNumber } = this.data; + + if (carNumber.length > 0) { + carNumber.pop(); + this.setData({ + carNumber + }); + } + }, + closeKeyboard() { + this.setData({ + keyboardVisible: false + }); + }, + openKeyboard() { + const query = this.createSelectorQuery(); + + query.select('.cw-car-number-items').boundingClientRect(); + query.exec(res => { + wx.pageScrollTo({ + scrollTop: res[0].top, + duration: 500 + }); + }); + + this.setData({ + keyboardVisible: true + }); + }, + clear() { + this.setData( + { + carNumber: [] + }, + () => { + this.$emit('change', ''); + } + ); + } + } +}); diff --git a/employee-mp/src/components/car-number/index.json b/employee-mp/src/components/car-number/index.json new file mode 100644 index 0000000..85e5843 --- /dev/null +++ b/employee-mp/src/components/car-number/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon/index" + } +} diff --git a/employee-mp/src/components/car-number/index.wxml b/employee-mp/src/components/car-number/index.wxml new file mode 100644 index 0000000..c5bec9e --- /dev/null +++ b/employee-mp/src/components/car-number/index.wxml @@ -0,0 +1,63 @@ + + + + {{carNumber[0] || ""}} + {{carNumber[1] || ""}} + + + {{carNumber[2] || ''}} + {{carNumber[3] || ''}} + {{carNumber[4] || ''}} + {{carNumber[5] || ''}} + {{carNumber[6] || ''}} + + + {{carNumber[7] || ''}} + + + + + + diff --git a/employee-mp/src/components/car-number/index.wxss b/employee-mp/src/components/car-number/index.wxss new file mode 100644 index 0000000..fcb88f7 --- /dev/null +++ b/employee-mp/src/components/car-number/index.wxss @@ -0,0 +1,140 @@ +/* 虚拟键盘 */ +.cw-keyboard { + height: auto; + background: #d1d5d9; + position: fixed; + bottom: 0; + width: 100%; + left: 0; + padding-bottom: constant(safe-area-inset-bottom); + padding-bottom: env(safe-area-inset-bottom); + z-index: 60; +} + +.cw-keyboard-item { + padding: 10rpx 0 5rpx 0; + position: relative; + display: block; +} + +/* 关闭虚拟键盘 */ +.cw-keyboard-close { + height: 70rpx; + background-color: #eee; + overflow: hidden; +} + +.cw-keyboard-close-btn { + float: right; + line-height: 70rpx; + font-size: 20px; + padding-right: 30rpx; +} + +/* 虚拟键盘-省缩写 */ +/* 虚拟键盘-行 */ +.cw-keyboard-line { + margin: 0 auto; + text-align: center; +} + +.cw-iscarnumber .cw-keyboard-line { + text-align: left; + margin-left: 5rpx; +} + +/* 虚拟键盘-单个按钮 */ +.cw-keyboard-btn { + font-size: 17px; + color: #333333; + background: #fff; + display: inline-block; + padding: 18rpx 0; + width: 63rpx; + text-align: center; + box-shadow: 0 2rpx 0 0 #999999; + border-radius: 10rpx; + margin: 5rpx 6rpx; +} + +.cw-keyboard-btn:active { + background: #f5f5f5; +} + +/* 虚拟键盘-删除按钮 */ +.cw-keyboard-del { + font-size: 22px; + color: #333333; + background: #a7b0bc; + display: inline-block; + padding: 8rpx 0; + text-align: center; + width: 96rpx; + box-shadow: 0 2rpx 0 0 #999999; + border-radius: 10rpx; + margin: 5rpx; + position: absolute; + bottom: 5rpx; + right: 6rpx; +} + +.cw-keyboard-del-font { + font-size: 25px; +} + +/* 车牌号码 */ +.cw-car-number-items { + text-align: left; + color: #323232; +} + +.cw-car-number-items-box { + width: 152rpx; + height: 90rpx; + border: 2rpx solid #cccccc; + border-radius: 4rpx; + display: inline-block; + vertical-align: middle; + position: relative; + margin-right: 30rpx; + text-align: right; +} + +.cw-car-number-items-box-list { + width: 72rpx; + height: 70rpx; + line-height: 70rpx; + text-align: center; + display: inline-block; + font-size: 18px; + margin: 10rpx 0; + vertical-align: middle; +} + +.cw-car-number-items-province { + border-right: 1rpx solid #ccc; +} + +.cw-car-number-items-box::after { + content: ''; + width: 6rpx; + height: 6rpx; + position: absolute; + right: -22rpx; + top: 40rpx; + border-radius: 50%; + background-color: #ccc; +} + +.cw-car-number-item { + width: 76rpx; + height: 90rpx; + font-size: 18px; + text-align: center; + border: 2rpx solid #cccccc; + border-radius: 4rpx; + line-height: 90rpx; + display: inline-block; + margin: 0 4rpx; + vertical-align: middle; +} diff --git a/employee-mp/src/components/card/index.js b/employee-mp/src/components/card/index.js new file mode 100644 index 0000000..0db9618 --- /dev/null +++ b/employee-mp/src/components/card/index.js @@ -0,0 +1,54 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { link } from '../mixins/link'; +import { CwComponent } from '../common/component'; +CwComponent({ + classes: ['num-class', 'desc-class', 'thumb-class', 'title-class', 'price-class', 'origin-price-class'], + mixins: [link], + props: { + tag: String, + num: String, + desc: String, + thumb: String, + title: String, + price: { + type: String, + observer: 'updatePrice' + }, + centered: Boolean, + lazyLoad: Boolean, + thumbLink: String, + originPrice: String, + thumbMode: { + type: String, + value: 'aspectFit' + }, + currency: { + type: String, + value: '¥' + } + }, + methods: { + updatePrice() { + const { price } = this.data; + const priceArr = price.toString().split('.'); + this.setData({ + integerStr: priceArr[0], + decimalStr: priceArr[1] ? `.${priceArr[1]}` : '' + }); + }, + onClickThumb() { + this.jumpLink('thumbLink'); + } + } +}); diff --git a/employee-mp/src/components/card/index.json b/employee-mp/src/components/card/index.json new file mode 100644 index 0000000..c273f07 --- /dev/null +++ b/employee-mp/src/components/card/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-tag": "../tag/index" + } +} diff --git a/employee-mp/src/components/card/index.wxml b/employee-mp/src/components/card/index.wxml new file mode 100644 index 0000000..55d976d --- /dev/null +++ b/employee-mp/src/components/card/index.wxml @@ -0,0 +1,53 @@ + + + + + + + + + {{ tag }} + + + + + + + {{ title }} + + + {{ desc }} + + + + + + + + + {{ currency }} + {{ integerStr }} + {{ decimalStr }} + + + + {{ currency }} {{ originPrice }} + + + x {{ num }} + + + + + + + + + + diff --git a/employee-mp/src/components/card/index.wxss b/employee-mp/src/components/card/index.wxss new file mode 100644 index 0000000..79ba17d --- /dev/null +++ b/employee-mp/src/components/card/index.wxss @@ -0,0 +1,120 @@ +@import '../common/index.wxss'; + +.cw-card { + position: relative; + box-sizing: border-box; + padding: 8px 16px; + font-size: 12px; + color: #323233; + background-color: #fafafa; +} + +.cw-card__header { + display: -webkit-flex; + display: flex; +} + +.cw-card__header--center { + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center; +} + +.cw-card__thumb { + position: relative; + -webkit-flex: none; + flex: none; + width: 88px; + height: 88px; + margin-right: 8px; +} + +.cw-card__thumb:empty { + display: none; +} + +.cw-card__img { + width: 100%; + height: 100%; + border-radius: 8px; +} + +.cw-card__content { + position: relative; + display: -webkit-flex; + display: flex; + -webkit-flex: 1; + flex: 1; + -webkit-flex-direction: column; + flex-direction: column; + -webkit-justify-content: space-between; + justify-content: space-between; + min-width: 0; + min-height: 88px; +} + +.cw-card__content--center { + -webkit-justify-content: center; + justify-content: center; +} + +.cw-card__desc, +.cw-card__title { + word-wrap: break-word; +} + +.cw-card__title { + font-weight: 700; + line-height: 16px; +} + +.cw-card__desc { + line-height: 20px; + color: #646566; +} + +.cw-card__bottom { + line-height: 20px; +} + +.cw-card__price { + display: inline-block; + font-weight: 700; + color: #ee0a24; + font-size: 12px; +} + +.cw-card__price-integer { + font-size: 16px; +} + +.cw-card__price-decimal, +.cw-card__price-integer { + font-family: Avenir-Heavy, PingFang SC, Helvetica Neue, Arial, sans-serif; +} + +.cw-card__origin-price { + display: inline-block; + margin-left: 5px; + text-decoration: line-through; + font-size: 10px; + color: #646566; +} + +.cw-card__num { + float: right; +} + +.cw-card__tag { + position: absolute !important; + top: 2px; + left: 0; +} + +.cw-card__footer { + -webkit-flex: none; + flex: none; + width: 100%; + text-align: right; +} diff --git a/employee-mp/src/components/cell-group/index.js b/employee-mp/src/components/cell-group/index.js new file mode 100644 index 0000000..7d2bca2 --- /dev/null +++ b/employee-mp/src/components/cell-group/index.js @@ -0,0 +1,22 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +CwComponent({ + props: { + title: String, + border: { + type: Boolean, + value: true + } + } +}); diff --git a/employee-mp/src/components/cell-group/index.json b/employee-mp/src/components/cell-group/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/cell-group/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/cell-group/index.wxml b/employee-mp/src/components/cell-group/index.wxml new file mode 100644 index 0000000..750ccd7 --- /dev/null +++ b/employee-mp/src/components/cell-group/index.wxml @@ -0,0 +1,6 @@ + + {{ title }} + + + + diff --git a/employee-mp/src/components/cell-group/index.wxss b/employee-mp/src/components/cell-group/index.wxss new file mode 100644 index 0000000..44fbfb9 --- /dev/null +++ b/employee-mp/src/components/cell-group/index.wxss @@ -0,0 +1,8 @@ +@import '../common/index.wxss'; + +.cw-cell-group__title { + padding: 16px 16px 8px; + font-size: 14px; + line-height: 16px; + color: #969799; +} diff --git a/employee-mp/src/components/cell/index.js b/employee-mp/src/components/cell/index.js new file mode 100644 index 0000000..a1a8c17 --- /dev/null +++ b/employee-mp/src/components/cell/index.js @@ -0,0 +1,45 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { link } from '../mixins/link'; +import { CwComponent } from '../common/component'; +CwComponent({ + classes: ['title-class', 'label-class', 'value-class', 'right-icon-class', 'hover-class'], + mixins: [link], + props: { + title: null, + value: null, + icon: String, + size: String, + label: String, + center: Boolean, + isLink: Boolean, + isDetail: Boolean, + required: Boolean, + clickable: Boolean, + titleWidth: String, + customStyle: String, + arrowDirection: String, + useLabelSlot: Boolean, + border: { + type: Boolean, + value: true + }, + titleStyle: String + }, + methods: { + onClick(event) { + this.$emit('click', event.detail); + this.jumpLink(); + } + } +}); diff --git a/employee-mp/src/components/cell/index.json b/employee-mp/src/components/cell/index.json new file mode 100644 index 0000000..85e5843 --- /dev/null +++ b/employee-mp/src/components/cell/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon/index" + } +} diff --git a/employee-mp/src/components/cell/index.wxml b/employee-mp/src/components/cell/index.wxml new file mode 100644 index 0000000..38ddc18 --- /dev/null +++ b/employee-mp/src/components/cell/index.wxml @@ -0,0 +1,38 @@ + + + + + + + + + {{ title }} + + + + + {{ label }} + + + + + {{ value }} + + + + + + + + diff --git a/employee-mp/src/components/cell/index.wxs b/employee-mp/src/components/cell/index.wxs new file mode 100644 index 0000000..e4f2f16 --- /dev/null +++ b/employee-mp/src/components/cell/index.wxs @@ -0,0 +1,16 @@ +var style = require('../wxs/style.wxs'); +var addUnit = require('../wxs/add-unit.wxs'); + +function titleStyle(data) { + return style([ + { + 'max-width': addUnit(data.titleWidth), + 'min-width': addUnit(data.titleWidth) + }, + data.titleStyle + ]); +} + +module.exports = { + titleStyle: titleStyle +}; diff --git a/employee-mp/src/components/cell/index.wxss b/employee-mp/src/components/cell/index.wxss new file mode 100644 index 0000000..ccca3d4 --- /dev/null +++ b/employee-mp/src/components/cell/index.wxss @@ -0,0 +1,141 @@ +@import '../common/index.wxss'; + +.cw-cell { + position: relative; + display: -webkit-flex; + display: flex; + box-sizing: border-box; + width: 100%; + padding: 10px 16px; + font-size: 14px; + line-height: 24px; + color: #323233; + background-color: #fff; +} + +.cw-cell:after { + position: absolute; + box-sizing: border-box; + -webkit-transform-origin: center; + transform-origin: center; + content: ' '; + pointer-events: none; + right: 16px; + bottom: 0; + left: 16px; + border-bottom: 1px solid #ebedf0; + transform: scaleY(0.5); +} + +.cw-cell--borderless:after { + display: none; +} + +.cw-cell-group { + background-color: #fff; +} + +.cw-cell__label { + margin-top: 3px; + font-size: 12px; + line-height: 18px; + color: #969799; +} + +.cw-cell__value { + overflow: hidden; + text-align: right; + vertical-align: middle; + color: #969799; + margin-left: 12px; +} + +.cw-cell__value.only { + margin-left: 0; +} + +.cw-cell__title { + flex: auto; +} +.cw-cell__value { + flex: auto; +} + +.cw-cell--detail .cw-cell__title { + flex: none; +} + +.cw-cell--detail .cw-cell__value { + color: #323233; +} + +.cw-cell__title:empty, +.cw-cell__value:empty { + display: none; +} + +.cw-cell__left-icon-wrap, +.cw-cell__right-icon-wrap { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + height: 24px; + font-size: 16px; +} + +.cw-cell__left-icon-wrap { + margin-right: 4px; +} + +.cw-cell__right-icon-wrap { + margin-left: 4px; + color: #969799; +} + +.cw-cell__left-icon { + vertical-align: middle; +} + +.cw-cell__left-icon, +.cw-cell__right-icon { + line-height: 24px; +} + +.cw-cell--clickable.cw-cell--hover { + background-color: #f2f3f5; +} + +.cw-cell--required { + overflow: visible; +} + +.cw-cell--required:before { + position: absolute; + content: '*'; + left: 8px; + font-size: 14px; + color: #ee0a24; +} + +.cw-cell--center { + -webkit-align-items: center; + align-items: center; +} + +.cw-cell--large { + padding-top: 12px; + padding-bottom: 12px; +} + +.cw-cell--large .cw-cell__title { + font-size: 16px; +} + +.cw-cell--large .cw-cell__value { + font-size: 16px; +} + +.cw-cell--large .cw-cell__label { + font-size: 14px; +} diff --git a/employee-mp/src/components/checkbox-group/index.js b/employee-mp/src/components/checkbox-group/index.js new file mode 100644 index 0000000..021607e --- /dev/null +++ b/employee-mp/src/components/checkbox-group/index.js @@ -0,0 +1,43 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { useChildren } from '../common/relation'; +import { CwComponent } from '../common/component'; +CwComponent({ + field: true, + relation: useChildren('checkbox', function(target) { + this.updateChild(target); + }), + props: { + max: Number, + value: { + type: Array, + observer: 'updateChildren' + }, + disabled: { + type: Boolean, + observer: 'updateChildren' + } + }, + methods: { + updateChildren() { + this.children.forEach(child => this.updateChild(child)); + }, + updateChild(child) { + const { value, disabled } = this.data; + child.setData({ + value: value.indexOf(child.data.name) !== -1, + parentDisabled: disabled + }); + } + } +}); diff --git a/employee-mp/src/components/checkbox-group/index.json b/employee-mp/src/components/checkbox-group/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/checkbox-group/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/checkbox-group/index.wxml b/employee-mp/src/components/checkbox-group/index.wxml new file mode 100644 index 0000000..4fa864c --- /dev/null +++ b/employee-mp/src/components/checkbox-group/index.wxml @@ -0,0 +1 @@ + diff --git a/employee-mp/src/components/checkbox-group/index.wxss b/employee-mp/src/components/checkbox-group/index.wxss new file mode 100644 index 0000000..ecfdfde --- /dev/null +++ b/employee-mp/src/components/checkbox-group/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; diff --git a/employee-mp/src/components/checkbox/index.js b/employee-mp/src/components/checkbox/index.js new file mode 100644 index 0000000..0aa5d65 --- /dev/null +++ b/employee-mp/src/components/checkbox/index.js @@ -0,0 +1,87 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { useParent } from '../common/relation'; +import { CwComponent } from '../common/component'; +function emit(target, value) { + target.$emit('input', value); + target.$emit('change', value); +} +CwComponent({ + field: true, + relation: useParent('checkbox-group'), + classes: ['icon-class', 'label-class'], + props: { + name: null, + value: Boolean, + disabled: Boolean, + useIconSlot: Boolean, + checkedColor: String, + labelPosition: { + type: String, + value: 'right' + }, + labelDisabled: Boolean, + shape: { + type: String, + value: 'round' + }, + iconSize: { + type: null, + value: 20 + } + }, + data: { + parentDisabled: false + }, + methods: { + emitChange(value) { + if (this.parent) { + this.setParentValue(this.parent, value); + } else { + emit(this, value); + } + }, + toggle() { + const { parentDisabled, disabled, value } = this.data; + if (!disabled && !parentDisabled) { + this.emitChange(!value); + } + }, + onClickLabel() { + const { labelDisabled, parentDisabled, disabled, value } = this.data; + if (!disabled && !labelDisabled && !parentDisabled) { + this.emitChange(!value); + } + }, + setParentValue(parent, value) { + const parentValue = parent.data.value.slice(); + const { name } = this.data; + const { max } = parent.data; + if (value) { + if (max && parentValue.length >= max) { + return; + } + if (parentValue.indexOf(name) === -1) { + parentValue.push(name); + emit(parent, parentValue); + } + } else { + const index = parentValue.indexOf(name); + if (index !== -1) { + parentValue.splice(index, 1); + emit(parent, parentValue); + } + } + } + } +}); diff --git a/employee-mp/src/components/checkbox/index.json b/employee-mp/src/components/checkbox/index.json new file mode 100644 index 0000000..85e5843 --- /dev/null +++ b/employee-mp/src/components/checkbox/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon/index" + } +} diff --git a/employee-mp/src/components/checkbox/index.wxml b/employee-mp/src/components/checkbox/index.wxml new file mode 100644 index 0000000..7b2810b --- /dev/null +++ b/employee-mp/src/components/checkbox/index.wxml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + diff --git a/employee-mp/src/components/checkbox/index.wxs b/employee-mp/src/components/checkbox/index.wxs new file mode 100644 index 0000000..67c9f66 --- /dev/null +++ b/employee-mp/src/components/checkbox/index.wxs @@ -0,0 +1,19 @@ +var style = require('../wxs/style.wxs'); +var addUnit = require('../wxs/add-unit.wxs'); + +function iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) { + var styles = { + 'font-size': addUnit(iconSize) + }; + + if (checkedColor && value && !disabled && !parentDisabled) { + styles['border-color'] = checkedColor; + styles['background-color'] = checkedColor; + } + + return style(styles); +} + +module.exports = { + iconStyle: iconStyle +}; diff --git a/employee-mp/src/components/checkbox/index.wxss b/employee-mp/src/components/checkbox/index.wxss new file mode 100644 index 0000000..3a45bfb --- /dev/null +++ b/employee-mp/src/components/checkbox/index.wxss @@ -0,0 +1,77 @@ +@import '../common/index.wxss'; + +.cw-checkbox { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + overflow: hidden; + -webkit-user-select: none; + user-select: none; +} + +.cw-checkbox__icon-wrap, +.cw-checkbox__label { + line-height: 20px; +} + +.cw-checkbox__icon-wrap { + -webkit-flex: none; + flex: none; +} + +.cw-checkbox__icon { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center; + box-sizing: border-box; + width: 1em; + height: 1em; + color: transparent; + text-align: center; + transition-property: color, border-color, background-color; + font-size: 20px; + border: 1px solid #c8c9cc; + transition-duration: 0.2s; +} + +.cw-checkbox__icon--round { + border-radius: 100%; +} + +.cw-checkbox__icon--checked { + color: #fff; + background-color: #1989fa; + border-color: #1989fa; +} + +.cw-checkbox__icon--disabled { + background-color: #ebedf0; + border-color: #c8c9cc; +} + +.cw-checkbox__icon--disabled.cw-checkbox__icon--checked { + color: #c8c9cc; +} + +.cw-checkbox__label { + word-wrap: break-word; + margin-left: 10px; + color: #323233; +} + +.cw-checkbox__label--left { + float: left; + margin: 0 10px 0 0; +} + +.cw-checkbox__label--disabled { + color: #c8c9cc; +} + +.cw-checkbox__label:empty { + margin: 0; +} diff --git a/employee-mp/src/components/circle/canvas.js b/employee-mp/src/components/circle/canvas.js new file mode 100644 index 0000000..2c43b2d --- /dev/null +++ b/employee-mp/src/components/circle/canvas.js @@ -0,0 +1,55 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export function adaptor(ctx) { + // @ts-ignore + return Object.assign(ctx, { + setStrokeStyle(val) { + ctx.strokeStyle = val; + }, + setLineWidth(val) { + ctx.lineWidth = val; + }, + setLineCap(val) { + ctx.lineCap = val; + }, + setFillStyle(val) { + ctx.fillStyle = val; + }, + setFontSize(val) { + ctx.font = String(val); + }, + setGlobalAlpha(val) { + ctx.globalAlpha = val; + }, + setLineJoin(val) { + ctx.lineJoin = val; + }, + setTextAlign(val) { + ctx.textAlign = val; + }, + setMiterLimit(val) { + ctx.miterLimit = val; + }, + setShadow(offsetX, offsetY, blur, color) { + ctx.shadowOffsetX = offsetX; + ctx.shadowOffsetY = offsetY; + ctx.shadowBlur = blur; + ctx.shadowColor = color; + }, + setTextBaseline(val) { + ctx.textBaseline = val; + }, + createCircularGradient() {}, + draw() {} + }); +} diff --git a/employee-mp/src/components/circle/index.js b/employee-mp/src/components/circle/index.js new file mode 100644 index 0000000..af95f4e --- /dev/null +++ b/employee-mp/src/components/circle/index.js @@ -0,0 +1,194 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { BLUE, WHITE } from '../common/color'; +import { CwComponent } from '../common/component'; +import { getSystemInfoSync } from '../common/utils'; +import { isObj } from '../common/validator'; +import { canIUseCanvas2d } from '../common/version'; +import { adaptor } from './canvas'; +function format(rate) { + return Math.min(Math.max(rate, 0), 100); +} +const PERIMETER = 2 * Math.PI; +const BEGIN_ANGLE = -Math.PI / 2; +const STEP = 1; +CwComponent({ + props: { + text: String, + lineCap: { + type: String, + value: 'round' + }, + value: { + type: Number, + value: 0, + observer: 'reRender' + }, + speed: { + type: Number, + value: 50 + }, + size: { + type: Number, + value: 100, + observer() { + this.drawCircle(this.currentValue); + } + }, + fill: String, + layerColor: { + type: String, + value: WHITE + }, + color: { + type: null, + value: BLUE, + observer() { + this.setHoverColor().then(() => { + this.drawCircle(this.currentValue); + }); + } + }, + type: { + type: String, + value: '' + }, + strokeWidth: { + type: Number, + value: 4 + }, + clockwise: { + type: Boolean, + value: true + } + }, + data: { + hoverColor: BLUE + }, + methods: { + getContext() { + const { type, size } = this.data; + if (type === '' || !canIUseCanvas2d()) { + const ctx = wx.createCanvasContext('cw-circle', this); + return Promise.resolve(ctx); + } + const dpr = getSystemInfoSync().pixelRatio; + return new Promise(resolve => { + wx.createSelectorQuery() + .in(this) + .select('#cw-circle') + .node() + .exec(res => { + const canvas = res[0].node; + const ctx = canvas.getContext(type); + if (!this.inited) { + this.inited = true; + canvas.width = size * dpr; + canvas.height = size * dpr; + ctx.scale(dpr, dpr); + } + resolve(adaptor(ctx)); + }); + }); + }, + setHoverColor() { + const { color, size } = this.data; + if (isObj(color)) { + return this.getContext().then(context => { + const LinearColor = context.createLinearGradient(size, 0, 0, 0); + Object.keys(color) + .sort((a, b) => parseFloat(a) - parseFloat(b)) + .map(key => LinearColor.addColorStop(parseFloat(key) / 100, color[key])); + this.hoverColor = LinearColor; + }); + } + this.hoverColor = color; + return Promise.resolve(); + }, + presetCanvas(context, strokeStyle, beginAngle, endAngle, fill) { + const { strokeWidth, lineCap, clockwise, size } = this.data; + const position = size / 2; + const radius = position - strokeWidth / 2; + context.setStrokeStyle(strokeStyle); + context.setLineWidth(strokeWidth); + context.setLineCap(lineCap); + context.beginPath(); + context.arc(position, position, radius, beginAngle, endAngle, !clockwise); + context.stroke(); + if (fill) { + context.setFillStyle(fill); + context.fill(); + } + }, + renderLayerCircle(context) { + const { layerColor, fill } = this.data; + this.presetCanvas(context, layerColor, 0, PERIMETER, fill); + }, + renderHoverCircle(context, formatValue) { + const { clockwise } = this.data; + // 结束角度 + const progress = PERIMETER * (formatValue / 100); + const endAngle = clockwise ? BEGIN_ANGLE + progress : 3 * Math.PI - (BEGIN_ANGLE + progress); + this.presetCanvas(context, this.hoverColor, BEGIN_ANGLE, endAngle); + }, + drawCircle(currentValue) { + const { size } = this.data; + this.getContext().then(context => { + context.clearRect(0, 0, size, size); + this.renderLayerCircle(context); + const formatValue = format(currentValue); + if (formatValue !== 0) { + this.renderHoverCircle(context, formatValue); + } + context.draw(); + }); + }, + reRender() { + // tofector 动画暂时没有想到好的解决方案 + const { value, speed } = this.data; + if (speed <= 0 || speed > 1000) { + this.drawCircle(value); + return; + } + this.clearInterval(); + this.currentValue = this.currentValue || 0; + this.interval = setInterval(() => { + if (this.currentValue !== value) { + if (this.currentValue < value) { + this.currentValue += STEP; + } else { + this.currentValue -= STEP; + } + this.drawCircle(this.currentValue); + } else { + this.clearInterval(); + } + }, 1000 / speed); + }, + clearInterval() { + if (this.interval) { + clearInterval(this.interval); + this.interval = null; + } + } + }, + mounted() { + this.currentValue = this.data.value; + this.setHoverColor().then(() => { + this.drawCircle(this.currentValue); + }); + }, + destroyed() { + this.clearInterval(); + } +}); diff --git a/employee-mp/src/components/circle/index.json b/employee-mp/src/components/circle/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/circle/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/circle/index.wxml b/employee-mp/src/components/circle/index.wxml new file mode 100644 index 0000000..7cbceb7 --- /dev/null +++ b/employee-mp/src/components/circle/index.wxml @@ -0,0 +1,15 @@ + + + + + + + + {{ text }} + diff --git a/employee-mp/src/components/circle/index.wxss b/employee-mp/src/components/circle/index.wxss new file mode 100644 index 0000000..8d02a25 --- /dev/null +++ b/employee-mp/src/components/circle/index.wxss @@ -0,0 +1,17 @@ +@import '../common/index.wxss'; + +.cw-circle { + position: relative; + display: inline-block; + text-align: center; +} + +.cw-circle__text { + position: absolute; + top: 50%; + left: 0; + width: 100%; + -webkit-transform: translateY(-50%); + transform: translateY(-50%); + color: #323233; +} diff --git a/employee-mp/src/components/col/index.js b/employee-mp/src/components/col/index.js new file mode 100644 index 0000000..b65ad27 --- /dev/null +++ b/employee-mp/src/components/col/index.js @@ -0,0 +1,21 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { useParent } from '../common/relation'; +import { CwComponent } from '../common/component'; +CwComponent({ + relation: useParent('row'), + props: { + span: Number, + offset: Number + } +}); diff --git a/employee-mp/src/components/col/index.json b/employee-mp/src/components/col/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/col/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/col/index.wxml b/employee-mp/src/components/col/index.wxml new file mode 100644 index 0000000..71f3735 --- /dev/null +++ b/employee-mp/src/components/col/index.wxml @@ -0,0 +1,9 @@ + + + + + + diff --git a/employee-mp/src/components/col/index.wxs b/employee-mp/src/components/col/index.wxs new file mode 100644 index 0000000..ff756ac --- /dev/null +++ b/employee-mp/src/components/col/index.wxs @@ -0,0 +1,17 @@ +var style = require('../wxs/style.wxs'); +var addUnit = require('../wxs/add-unit.wxs'); + +function rootStyle(data) { + if (!data.gutter) { + return ''; + } + + return style({ + 'padding-right': addUnit(data.gutter / 2), + 'padding-left': addUnit(data.gutter / 2) + }); +} + +module.exports = { + rootStyle: rootStyle +}; diff --git a/employee-mp/src/components/col/index.wxss b/employee-mp/src/components/col/index.wxss new file mode 100644 index 0000000..42c1046 --- /dev/null +++ b/employee-mp/src/components/col/index.wxss @@ -0,0 +1,198 @@ +@import '../common/index.wxss'; + +.cw-col { + float: left; + box-sizing: border-box; +} + +.cw-col--1 { + width: 4.16666667%; +} + +.cw-col--offset-1 { + margin-left: 4.16666667%; +} + +.cw-col--2 { + width: 8.33333333%; +} + +.cw-col--offset-2 { + margin-left: 8.33333333%; +} + +.cw-col--3 { + width: 12.5%; +} + +.cw-col--offset-3 { + margin-left: 12.5%; +} + +.cw-col--4 { + width: 16.66666667%; +} + +.cw-col--offset-4 { + margin-left: 16.66666667%; +} + +.cw-col--5 { + width: 20.83333333%; +} + +.cw-col--offset-5 { + margin-left: 20.83333333%; +} + +.cw-col--6 { + width: 25%; +} + +.cw-col--offset-6 { + margin-left: 25%; +} + +.cw-col--7 { + width: 29.16666667%; +} + +.cw-col--offset-7 { + margin-left: 29.16666667%; +} + +.cw-col--8 { + width: 33.33333333%; +} + +.cw-col--offset-8 { + margin-left: 33.33333333%; +} + +.cw-col--9 { + width: 37.5%; +} + +.cw-col--offset-9 { + margin-left: 37.5%; +} + +.cw-col--10 { + width: 41.66666667%; +} + +.cw-col--offset-10 { + margin-left: 41.66666667%; +} + +.cw-col--11 { + width: 45.83333333%; +} + +.cw-col--offset-11 { + margin-left: 45.83333333%; +} + +.cw-col--12 { + width: 50%; +} + +.cw-col--offset-12 { + margin-left: 50%; +} + +.cw-col--13 { + width: 54.16666667%; +} + +.cw-col--offset-13 { + margin-left: 54.16666667%; +} + +.cw-col--14 { + width: 58.33333333%; +} + +.cw-col--offset-14 { + margin-left: 58.33333333%; +} + +.cw-col--15 { + width: 62.5%; +} + +.cw-col--offset-15 { + margin-left: 62.5%; +} + +.cw-col--16 { + width: 66.66666667%; +} + +.cw-col--offset-16 { + margin-left: 66.66666667%; +} + +.cw-col--17 { + width: 70.83333333%; +} + +.cw-col--offset-17 { + margin-left: 70.83333333%; +} + +.cw-col--18 { + width: 75%; +} + +.cw-col--offset-18 { + margin-left: 75%; +} + +.cw-col--19 { + width: 79.16666667%; +} + +.cw-col--offset-19 { + margin-left: 79.16666667%; +} + +.cw-col--20 { + width: 83.33333333%; +} + +.cw-col--offset-20 { + margin-left: 83.33333333%; +} + +.cw-col--21 { + width: 87.5%; +} + +.cw-col--offset-21 { + margin-left: 87.5%; +} + +.cw-col--22 { + width: 91.66666667%; +} + +.cw-col--offset-22 { + margin-left: 91.66666667%; +} + +.cw-col--23 { + width: 95.83333333%; +} + +.cw-col--offset-23 { + margin-left: 95.83333333%; +} + +.cw-col--24 { + width: 100%; +} + +.cw-col--offset-24 { + margin-left: 100%; +} diff --git a/employee-mp/src/components/collapse-item/animate.js b/employee-mp/src/components/collapse-item/animate.js new file mode 100644 index 0000000..1693ee8 --- /dev/null +++ b/employee-mp/src/components/collapse-item/animate.js @@ -0,0 +1,90 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { canIUseAnimate } from '../common/version'; +import { getRect } from '../common/utils'; +function useAnimate(context, expanded, mounted, height) { + const selector = '.cw-collapse-item__wrapper'; + if (expanded) { + context.animate( + selector, + [ + { height: 0, ease: 'ease-in-out', offset: 0 }, + { height: `${height}px`, ease: 'ease-in-out', offset: 1 }, + { height: `auto`, ease: 'ease-in-out', offset: 1 } + ], + mounted ? 300 : 0, + () => { + context.clearAnimation(selector); + } + ); + return; + } + context.animate( + selector, + [ + { height: `${height}px`, ease: 'ease-in-out', offset: 0 }, + { height: 0, ease: 'ease-in-out', offset: 1 } + ], + 300, + () => { + context.clearAnimation(selector); + } + ); +} +function useAnimation(context, expanded, mounted, height) { + const animation = wx.createAnimation({ + duration: 0, + timingFunction: 'ease-in-out' + }); + if (expanded) { + if (height === 0) { + animation + .height('auto') + .top(1) + .step(); + } else { + animation + .height(height) + .top(1) + .step({ + duration: mounted ? 300 : 1 + }) + .height('auto') + .step(); + } + context.setData({ + animation: animation.export() + }); + return; + } + animation + .height(height) + .top(0) + .step({ duration: 1 }) + .height(0) + .step({ + duration: 300 + }); + context.setData({ + animation: animation.export() + }); +} +export function setContentAnimate(context, expanded, mounted) { + getRect(context, '.cw-collapse-item__content') + .then(rect => rect.height) + .then(height => { + canIUseAnimate() + ? useAnimate(context, expanded, mounted, height) + : useAnimation(context, expanded, mounted, height); + }); +} diff --git a/employee-mp/src/components/collapse-item/index.js b/employee-mp/src/components/collapse-item/index.js new file mode 100644 index 0000000..ef7b3af --- /dev/null +++ b/employee-mp/src/components/collapse-item/index.js @@ -0,0 +1,69 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { useParent } from '../common/relation'; +import { setContentAnimate } from './animate'; +CwComponent({ + classes: ['title-class', 'content-class'], + relation: useParent('collapse'), + props: { + name: null, + title: null, + value: null, + icon: String, + label: String, + disabled: Boolean, + clickable: Boolean, + border: { + type: Boolean, + value: true + }, + isLink: { + type: Boolean, + value: true + } + }, + data: { + expanded: false + }, + mounted() { + this.updateExpanded(); + this.mounted = true; + }, + methods: { + updateExpanded() { + if (!this.parent) { + return; + } + const { value, accordion } = this.parent.data; + const { children = [] } = this.parent; + const { name } = this.data; + const index = children.indexOf(this); + const currentName = name == null ? index : name; + const expanded = accordion ? value === currentName : (value || []).some(name => name === currentName); + if (expanded !== this.data.expanded) { + setContentAnimate(this, expanded, this.mounted); + } + this.setData({ index, expanded }); + }, + onClick() { + if (this.data.disabled) { + return; + } + const { name, expanded } = this.data; + const index = this.parent.children.indexOf(this); + const currentName = name == null ? index : name; + this.parent.switch(currentName, !expanded); + } + } +}); diff --git a/employee-mp/src/components/collapse-item/index.json b/employee-mp/src/components/collapse-item/index.json new file mode 100644 index 0000000..51e706d --- /dev/null +++ b/employee-mp/src/components/collapse-item/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-cell": "../cell/index" + } +} diff --git a/employee-mp/src/components/collapse-item/index.wxml b/employee-mp/src/components/collapse-item/index.wxml new file mode 100644 index 0000000..9ed8147 --- /dev/null +++ b/employee-mp/src/components/collapse-item/index.wxml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + diff --git a/employee-mp/src/components/collapse-item/index.wxss b/employee-mp/src/components/collapse-item/index.wxss new file mode 100644 index 0000000..98290e4 --- /dev/null +++ b/employee-mp/src/components/collapse-item/index.wxss @@ -0,0 +1,35 @@ +@import '../common/index.wxss'; + +.cw-collapse-item__title .cw-cell__right-icon { + -webkit-transform: rotate(90deg); + transform: rotate(90deg); + transition: -webkit-transform 0.3s; + transition: transform 0.3s; + transition: transform 0.3s, -webkit-transform 0.3s; +} + +.cw-collapse-item__title--expanded .cw-cell__right-icon { + -webkit-transform: rotate(-90deg); + transform: rotate(-90deg); +} + +.cw-collapse-item__title--disabled .cw-cell, +.cw-collapse-item__title--disabled .cw-cell__right-icon { + color: #c8c9cc !important; +} + +.cw-collapse-item__title--disabled .cw-cell--hover { + background-color: #fff !important; +} + +.cw-collapse-item__wrapper { + overflow: hidden; +} + +.cw-collapse-item__content { + padding: 15px; + color: #969799; + font-size: 13px; + line-height: 1.5; + background-color: #fff; +} diff --git a/employee-mp/src/components/collapse/index.js b/employee-mp/src/components/collapse/index.js new file mode 100644 index 0000000..887a974 --- /dev/null +++ b/employee-mp/src/components/collapse/index.js @@ -0,0 +1,54 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { useChildren } from '../common/relation'; +CwComponent({ + relation: useChildren('collapse-item'), + props: { + value: { + type: null, + observer: 'updateExpanded' + }, + accordion: { + type: Boolean, + observer: 'updateExpanded' + }, + border: { + type: Boolean, + value: true + } + }, + methods: { + updateExpanded() { + this.children.forEach(child => { + child.updateExpanded(); + }); + }, + switch(name, expanded) { + const { accordion, value } = this.data; + const changeItem = name; + if (!accordion) { + name = expanded ? (value || []).concat(name) : (value || []).filter(activeName => activeName !== name); + } else { + name = expanded ? name : ''; + } + if (expanded) { + this.$emit('open', changeItem); + } else { + this.$emit('close', changeItem); + } + this.$emit('change', name); + this.$emit('input', name); + } + } +}); diff --git a/employee-mp/src/components/collapse/index.json b/employee-mp/src/components/collapse/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/collapse/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/collapse/index.wxml b/employee-mp/src/components/collapse/index.wxml new file mode 100644 index 0000000..9874045 --- /dev/null +++ b/employee-mp/src/components/collapse/index.wxml @@ -0,0 +1,3 @@ + + + diff --git a/employee-mp/src/components/collapse/index.wxss b/employee-mp/src/components/collapse/index.wxss new file mode 100644 index 0000000..ecfdfde --- /dev/null +++ b/employee-mp/src/components/collapse/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; diff --git a/employee-mp/src/components/colleague/index.js b/employee-mp/src/components/colleague/index.js new file mode 100644 index 0000000..b97f60f --- /dev/null +++ b/employee-mp/src/components/colleague/index.js @@ -0,0 +1,61 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import utils from '../../utils/index'; + +const app = getApp(); + +CwComponent({ + props: { + show: Boolean + }, + data: { + map: {} + }, + beforeCreate() { + utils + .request({ + url: '/option/colleague', + method: 'post', + data: { + community_id: app.data.postInfo.default_community_id + } + }) + .then(res => { + const map = {}; + + res.data.list.forEach(item => { + if (item.department in map) { + map[item.department].users.push(item); + } else { + map[item.department] = { + name: item.department, + users: [item] + }; + } + }); + + this.setData({ map }); + }); + }, + methods: { + onClose() { + this.$emit('close'); + }, + select(e) { + const { id, name } = e.currentTarget.dataset; + + this.$emit('select', { id, name }); + } + } +}); diff --git a/employee-mp/src/components/colleague/index.json b/employee-mp/src/components/colleague/index.json new file mode 100644 index 0000000..20ebe64 --- /dev/null +++ b/employee-mp/src/components/colleague/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "usingComponents": { + "cw-cell": "../cell", + "cw-cell-group": "../cell-group", + "cw-popup": "../popup" + } +} diff --git a/employee-mp/src/components/colleague/index.wxml b/employee-mp/src/components/colleague/index.wxml new file mode 100644 index 0000000..c174951 --- /dev/null +++ b/employee-mp/src/components/colleague/index.wxml @@ -0,0 +1,17 @@ + + + + + diff --git a/employee-mp/src/components/colleague/index.wxss b/employee-mp/src/components/colleague/index.wxss new file mode 100644 index 0000000..e69de29 diff --git a/employee-mp/src/components/common/color.js b/employee-mp/src/components/common/color.js new file mode 100644 index 0000000..1770115 --- /dev/null +++ b/employee-mp/src/components/common/color.js @@ -0,0 +1,19 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export const RED = '#ee0a24'; +export const BLUE = '#1989fa'; +export const WHITE = '#fff'; +export const GREEN = '#07c160'; +export const ORANGE = '#ff976a'; +export const GRAY = '#323233'; +export const GRAY_DARK = '#969799'; diff --git a/employee-mp/src/components/common/component.js b/employee-mp/src/components/common/component.js new file mode 100644 index 0000000..2954f8a --- /dev/null +++ b/employee-mp/src/components/common/component.js @@ -0,0 +1,57 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { basic } from '../mixins/basic'; +function mapKeys(source, target, map) { + Object.keys(map).forEach(key => { + if (source[key]) { + target[map[key]] = source[key]; + } + }); +} +function CwComponent(cwtOptions) { + const options = {}; + mapKeys(cwtOptions, options, { + data: 'data', + props: 'properties', + mixins: 'behaviors', + methods: 'methods', + beforeCreate: 'created', + created: 'attached', + mounted: 'ready', + destroyed: 'detached', + classes: 'externalClasses' + }); + // add default externalClasses + options.externalClasses = options.externalClasses || []; + options.externalClasses.push('custom-class'); + // add default behaviors + options.behaviors = options.behaviors || []; + options.behaviors.push(basic); + // add relations + const { relation } = cwtOptions; + if (relation) { + options.relations = relation.relations; + options.behaviors.push(relation.mixin); + } + // map field to form-field behavior + if (cwtOptions.field) { + options.behaviors.push('wx://form-field'); + } + // add default options + options.options = { + multipleSlots: true, + addGlobalClass: true + }; + Component(options); +} +export { CwComponent }; diff --git a/employee-mp/src/components/common/index.wxss b/employee-mp/src/components/common/index.wxss new file mode 100644 index 0000000..03a567a --- /dev/null +++ b/employee-mp/src/components/common/index.wxss @@ -0,0 +1,83 @@ +.cw-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} + +.cw-multi-ellipsis--l2 { + -webkit-line-clamp: 2; +} + +.cw-multi-ellipsis--l2, +.cw-multi-ellipsis--l3 { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-box-orient: vertical; +} + +.cw-multi-ellipsis--l3 { + -webkit-line-clamp: 3; +} + +.cw-clearfix:after { + display: table; + clear: both; + content: ''; +} + +.cw-hairline, +.cw-hairline--bottom, +.cw-hairline--left, +.cw-hairline--right, +.cw-hairline--surround, +.cw-hairline--top, +.cw-hairline--top-bottom { + position: relative; +} + +.cw-hairline--bottom:after, +.cw-hairline--left:after, +.cw-hairline--right:after, +.cw-hairline--surround:after, +.cw-hairline--top-bottom:after, +.cw-hairline--top:after, +.cw-hairline:after { + position: absolute; + box-sizing: border-box; + -webkit-transform-origin: center; + transform-origin: center; + content: ' '; + pointer-events: none; + top: -50%; + right: -50%; + bottom: -50%; + left: -50%; + border: 0 solid #ebedf0; + -webkit-transform: scale(0.5); + transform: scale(0.5); +} + +.cw-hairline--top:after { + border-top-width: 1px; +} + +.cw-hairline--left:after { + border-left-width: 1px; +} + +.cw-hairline--right:after { + border-right-width: 1px; +} + +.cw-hairline--bottom:after { + border-bottom-width: 1px; +} + +.cw-hairline--top-bottom:after { + border-width: 1px 0; +} + +.cw-hairline--surround:after { + border-width: 1px; +} diff --git a/employee-mp/src/components/common/relation.js b/employee-mp/src/components/common/relation.js new file mode 100644 index 0000000..3303480 --- /dev/null +++ b/employee-mp/src/components/common/relation.js @@ -0,0 +1,74 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export function useParent(name, onEffect) { + const path = `../${name}/index`; + return { + relations: { + [path]: { + type: 'ancestor', + linked() { + onEffect && onEffect.call(this); + }, + linkChanged() { + onEffect && onEffect.call(this); + }, + unlinked() { + onEffect && onEffect.call(this); + } + } + }, + mixin: Behavior({ + created() { + Object.defineProperty(this, 'parent', { + get: () => this.getRelationNodes(path)[0] + }); + Object.defineProperty(this, 'index', { + // @ts-ignore + get: () => { + var _a, _b; + return (_b = (_a = this.parent) === null || _a === void 0 ? void 0 : _a.children) === null || + _b === void 0 + ? void 0 + : _b.indexOf(this); + } + }); + } + }) + }; +} +export function useChildren(name, onEffect) { + const path = `../${name}/index`; + return { + relations: { + [path]: { + type: 'descendant', + linked(target) { + onEffect && onEffect.call(this, target); + }, + linkChanged(target) { + onEffect && onEffect.call(this, target); + }, + unlinked(target) { + onEffect && onEffect.call(this, target); + } + } + }, + mixin: Behavior({ + created() { + Object.defineProperty(this, 'children', { + get: () => this.getRelationNodes(path) || [] + }); + } + }) + }; +} diff --git a/employee-mp/src/components/common/style/clearfix.wxss b/employee-mp/src/components/common/style/clearfix.wxss new file mode 100644 index 0000000..23dc673 --- /dev/null +++ b/employee-mp/src/components/common/style/clearfix.wxss @@ -0,0 +1,5 @@ +.cw-clearfix:after { + display: table; + clear: both; + content: ''; +} diff --git a/employee-mp/src/components/common/style/ellipsis.wxss b/employee-mp/src/components/common/style/ellipsis.wxss new file mode 100644 index 0000000..aa123da --- /dev/null +++ b/employee-mp/src/components/common/style/ellipsis.wxss @@ -0,0 +1,18 @@ +.cw-ellipsis { + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +} +.cw-multi-ellipsis--l2 { + -webkit-line-clamp: 2; +} +.cw-multi-ellipsis--l2, +.cw-multi-ellipsis--l3 { + display: -webkit-box; + overflow: hidden; + text-overflow: ellipsis; + -webkit-box-orient: vertical; +} +.cw-multi-ellipsis--l3 { + -webkit-line-clamp: 3; +} diff --git a/employee-mp/src/components/common/style/hairline.wxss b/employee-mp/src/components/common/style/hairline.wxss new file mode 100644 index 0000000..b0894a8 --- /dev/null +++ b/employee-mp/src/components/common/style/hairline.wxss @@ -0,0 +1,55 @@ +.cw-hairline, +.cw-hairline--bottom, +.cw-hairline--left, +.cw-hairline--right, +.cw-hairline--surround, +.cw-hairline--top, +.cw-hairline--top-bottom { + position: relative; +} + +.cw-hairline--bottom:after, +.cw-hairline--left:after, +.cw-hairline--right:after, +.cw-hairline--surround:after, +.cw-hairline--top-bottom:after, +.cw-hairline--top:after, +.cw-hairline:after { + position: absolute; + box-sizing: border-box; + -webkit-transform-origin: center; + transform-origin: center; + content: ' '; + pointer-events: none; + top: -50%; + right: -50%; + bottom: -50%; + left: -50%; + border: 0 solid #ebedf0; + -webkit-transform: scale(0.5); + transform: scale(0.5); +} + +.cw-hairline--top:after { + border-top-width: 1px; +} + +.cw-hairline--left:after { + border-left-width: 1px; +} + +.cw-hairline--right:after { + border-right-width: 1px; +} + +.cw-hairline--bottom:after { + border-bottom-width: 1px; +} + +.cw-hairline--top-bottom:after { + border-width: 1px 0; +} + +.cw-hairline--surround:after { + border-width: 1px; +} diff --git a/employee-mp/src/components/common/utils.js b/employee-mp/src/components/common/utils.js new file mode 100644 index 0000000..24659d1 --- /dev/null +++ b/employee-mp/src/components/common/utils.js @@ -0,0 +1,101 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { isDef, isNumber, isPlainObject, isPromise } from './validator'; +import { canIUseGroupSetData, canIUseNextTick } from './version'; +export function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} +export function nextTick(cb) { + if (canIUseNextTick()) { + wx.nextTick(cb); + } else { + setTimeout(() => { + cb(); + }, 1000 / 30); + } +} +let systemInfo; +export function getSystemInfoSync() { + if (systemInfo == null) { + systemInfo = wx.getSystemInfoSync(); + } + return systemInfo; +} +export function addUnit(value) { + if (!isDef(value)) { + return undefined; + } + value = String(value); + return isNumber(value) ? `${value}px` : value; +} +export function requestAnimationFrame(cb) { + const systemInfo = getSystemInfoSync(); + if (systemInfo.platform === 'devtools') { + return setTimeout(() => { + cb(); + }, 1000 / 30); + } + return wx + .createSelectorQuery() + .selectViewport() + .boundingClientRect() + .exec(() => { + cb(); + }); +} +export function pickExclude(obj, keys) { + if (!isPlainObject(obj)) { + return {}; + } + return Object.keys(obj).reduce((prev, key) => { + if (!keys.includes(key)) { + prev[key] = obj[key]; + } + return prev; + }, {}); +} +export function getRect(context, selector) { + return new Promise(resolve => { + wx.createSelectorQuery() + .in(context) + .select(selector) + .boundingClientRect() + .exec((rect = []) => resolve(rect[0])); + }); +} +export function getAllRect(context, selector) { + return new Promise(resolve => { + wx.createSelectorQuery() + .in(context) + .selectAll(selector) + .boundingClientRect() + .exec((rect = []) => resolve(rect[0])); + }); +} +export function groupSetData(context, cb) { + if (canIUseGroupSetData()) { + context.groupSetData(cb); + } else { + cb(); + } +} +export function toPromise(promiseLike) { + if (isPromise(promiseLike)) { + return promiseLike; + } + return Promise.resolve(promiseLike); +} +export function getCurrentPage() { + const pages = getCurrentPages(); + return pages[pages.length - 1]; +} diff --git a/employee-mp/src/components/common/validator.js b/employee-mp/src/components/common/validator.js new file mode 100644 index 0000000..e804e84 --- /dev/null +++ b/employee-mp/src/components/common/validator.js @@ -0,0 +1,42 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export function isFunction(val) { + return typeof val === 'function'; +} +export function isPlainObject(val) { + return val !== null && typeof val === 'object' && !Array.isArray(val); +} +export function isPromise(val) { + return isPlainObject(val) && isFunction(val.then) && isFunction(val.catch); +} +export function isDef(value) { + return value !== undefined && value !== null; +} +export function isObj(x) { + const type = typeof x; + return x !== null && (type === 'object' || type === 'function'); +} +export function isNumber(value) { + return /^\d+(\.\d+)?$/.test(value); +} +export function isBoolean(value) { + return typeof value === 'boolean'; +} +const IMAGE_REGEXP = /\.(jpeg|jpg|gif|png|svg|webp|jfif|bmp|dpg)/i; +const VIDEO_REGEXP = /\.(mp4|mpg|mpeg|dat|asf|avi|rm|rmvb|mov|wmv|flv|mkv)/i; +export function isImageUrl(url) { + return IMAGE_REGEXP.test(url); +} +export function isVideoUrl(url) { + return VIDEO_REGEXP.test(url); +} diff --git a/employee-mp/src/components/common/version.js b/employee-mp/src/components/common/version.js new file mode 100644 index 0000000..eb022b3 --- /dev/null +++ b/employee-mp/src/components/common/version.js @@ -0,0 +1,57 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { getSystemInfoSync } from './utils'; +function compareVersion(v1, v2) { + v1 = v1.split('.'); + v2 = v2.split('.'); + const len = Math.max(v1.length, v2.length); + while (v1.length < len) { + v1.push('0'); + } + while (v2.length < len) { + v2.push('0'); + } + for (let i = 0; i < len; i++) { + const num1 = parseInt(v1[i], 10); + const num2 = parseInt(v2[i], 10); + if (num1 > num2) { + return 1; + } + if (num1 < num2) { + return -1; + } + } + return 0; +} +function gte(version) { + const system = getSystemInfoSync(); + return compareVersion(system.SDKVersion, version) >= 0; +} +export function canIUseModel() { + return gte('2.9.3'); +} +export function canIUseFormFieldButton() { + return gte('2.10.3'); +} +export function canIUseAnimate() { + return gte('2.9.0'); +} +export function canIUseGroupSetData() { + return gte('2.4.0'); +} +export function canIUseNextTick() { + return wx.canIUse('nextTick'); +} +export function canIUseCanvas2d() { + return gte('2.9.0'); +} diff --git a/employee-mp/src/components/copyright/index.js b/employee-mp/src/components/copyright/index.js new file mode 100644 index 0000000..ede7e0c --- /dev/null +++ b/employee-mp/src/components/copyright/index.js @@ -0,0 +1,25 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import * as config from '../../config'; + +CwComponent({ + data: { + version: config.VERSION + }, + props: { + fixed: Number, + dark: Boolean, + inTabPage: Boolean + } +}); diff --git a/employee-mp/src/components/copyright/index.json b/employee-mp/src/components/copyright/index.json new file mode 100644 index 0000000..85e5843 --- /dev/null +++ b/employee-mp/src/components/copyright/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon/index" + } +} diff --git a/employee-mp/src/components/copyright/index.wxml b/employee-mp/src/components/copyright/index.wxml new file mode 100644 index 0000000..bb9b2ce --- /dev/null +++ b/employee-mp/src/components/copyright/index.wxml @@ -0,0 +1,10 @@ + + + + + + e家宜业 v{{ version }} + 卓瓦科技版权所有 保留所有权利 + https://ejyy.chowa.cn + + diff --git a/employee-mp/src/components/copyright/index.wxss b/employee-mp/src/components/copyright/index.wxss new file mode 100644 index 0000000..d75c527 --- /dev/null +++ b/employee-mp/src/components/copyright/index.wxss @@ -0,0 +1,47 @@ +.cw-copyright { + padding: 34px 0; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + position: relative; + z-index: 5; + color: #d4d5d6; +} + +.cw-copyright.dark { + color: #999; +} + +.cw-copyright.fixed { + position: fixed; + left: 0; + right: 0; + bottom: constant(safe-area-inset-bottom); + bottom: env(safe-area-inset-bottom); +} + +.cw-copyright.in-tab-page { + position: absolute; +} + +.cw-copyright .chowa, +.cw-copyright .logo { + font-size: 42px; + flex: none; +} + +.cw-copyright .chowa { + margin-right: 8px; +} + +.cw-copyright .cw-company { + margin-left: 16px; + flex: none; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 12px; + line-height: 20px; +} diff --git a/employee-mp/src/components/count-down/index.js b/employee-mp/src/components/count-down/index.js new file mode 100644 index 0000000..e4c9baa --- /dev/null +++ b/employee-mp/src/components/count-down/index.js @@ -0,0 +1,111 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { isSameSecond, parseFormat, parseTimeData } from './utils'; +function simpleTick(fn) { + return setTimeout(fn, 30); +} +CwComponent({ + props: { + useSlot: Boolean, + millisecond: Boolean, + time: { + type: Number, + observer: 'reset' + }, + format: { + type: String, + value: 'HH:mm:ss' + }, + autoStart: { + type: Boolean, + value: true + } + }, + data: { + timeData: parseTimeData(0), + formattedTime: '0' + }, + destroyed() { + clearTimeout(this.tid); + this.tid = null; + }, + methods: { + // 开始 + start() { + if (this.counting) { + return; + } + this.counting = true; + this.endTime = Date.now() + this.remain; + this.tick(); + }, + // 暂停 + pause() { + this.counting = false; + clearTimeout(this.tid); + }, + // 重置 + reset() { + this.pause(); + this.remain = this.data.time; + this.setRemain(this.remain); + if (this.data.autoStart) { + this.start(); + } + }, + tick() { + if (this.data.millisecond) { + this.microTick(); + } else { + this.macroTick(); + } + }, + microTick() { + this.tid = simpleTick(() => { + this.setRemain(this.getRemain()); + if (this.remain !== 0) { + this.microTick(); + } + }); + }, + macroTick() { + this.tid = simpleTick(() => { + const remain = this.getRemain(); + if (!isSameSecond(remain, this.remain) || remain === 0) { + this.setRemain(remain); + } + if (this.remain !== 0) { + this.macroTick(); + } + }); + }, + getRemain() { + return Math.max(this.endTime - Date.now(), 0); + }, + setRemain(remain) { + this.remain = remain; + const timeData = parseTimeData(remain); + if (this.data.useSlot) { + this.$emit('change', timeData); + } + this.setData({ + formattedTime: parseFormat(this.data.format, timeData) + }); + if (remain === 0) { + this.pause(); + this.$emit('finish'); + } + } + } +}); diff --git a/employee-mp/src/components/count-down/index.json b/employee-mp/src/components/count-down/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/count-down/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/count-down/index.wxml b/employee-mp/src/components/count-down/index.wxml new file mode 100644 index 0000000..0098c33 --- /dev/null +++ b/employee-mp/src/components/count-down/index.wxml @@ -0,0 +1,4 @@ + + + {{ formattedTime }} + diff --git a/employee-mp/src/components/count-down/index.wxss b/employee-mp/src/components/count-down/index.wxss new file mode 100644 index 0000000..bea14f3 --- /dev/null +++ b/employee-mp/src/components/count-down/index.wxss @@ -0,0 +1,7 @@ +@import '../common/index.wxss'; + +.cw-count-down { + color: #323233; + font-size: 14px; + line-height: 20px; +} diff --git a/employee-mp/src/components/count-down/utils.js b/employee-mp/src/components/count-down/utils.js new file mode 100644 index 0000000..f0cc9df --- /dev/null +++ b/employee-mp/src/components/count-down/utils.js @@ -0,0 +1,65 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +function padZero(num, targetLength = 2) { + let str = num + ''; + while (str.length < targetLength) { + str = '0' + str; + } + return str; +} +const SECOND = 1000; +const MINUTE = 60 * SECOND; +const HOUR = 60 * MINUTE; +const DAY = 24 * HOUR; +export function parseTimeData(time) { + const days = Math.floor(time / DAY); + const hours = Math.floor((time % DAY) / HOUR); + const minutes = Math.floor((time % HOUR) / MINUTE); + const seconds = Math.floor((time % MINUTE) / SECOND); + const milliseconds = Math.floor(time % SECOND); + return { + days, + hours, + minutes, + seconds, + milliseconds + }; +} +export function parseFormat(format, timeData) { + const { days } = timeData; + let { hours, minutes, seconds, milliseconds } = timeData; + if (format.indexOf('DD') === -1) { + hours += days * 24; + } else { + format = format.replace('DD', padZero(days)); + } + if (format.indexOf('HH') === -1) { + minutes += hours * 60; + } else { + format = format.replace('HH', padZero(hours)); + } + if (format.indexOf('mm') === -1) { + seconds += minutes * 60; + } else { + format = format.replace('mm', padZero(minutes)); + } + if (format.indexOf('ss') === -1) { + milliseconds += seconds * 1000; + } else { + format = format.replace('ss', padZero(seconds)); + } + return format.replace('SSS', padZero(milliseconds, 3)); +} +export function isSameSecond(time1, time2) { + return Math.floor(time1 / 1000) === Math.floor(time2 / 1000); +} diff --git a/employee-mp/src/components/datetime-picker/index.js b/employee-mp/src/components/datetime-picker/index.js new file mode 100644 index 0000000..1c432f2 --- /dev/null +++ b/employee-mp/src/components/datetime-picker/index.js @@ -0,0 +1,317 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { isDef } from '../common/validator'; +import { pickerProps } from '../picker/shared'; +const currentYear = new Date().getFullYear(); +function isValidDate(date) { + return isDef(date) && !isNaN(new Date(date).getTime()); +} +function range(num, min, max) { + return Math.min(Math.max(num, min), max); +} +function padZero(val) { + return `00${val}`.slice(-2); +} +function times(n, iteratee) { + let index = -1; + const result = Array(n < 0 ? 0 : n); + while (++index < n) { + result[index] = iteratee(index); + } + return result; +} +function getTrueValue(formattedValue) { + if (formattedValue === undefined) { + formattedValue = '1'; + } + while (isNaN(parseInt(formattedValue, 10))) { + formattedValue = formattedValue.slice(1); + } + return parseInt(formattedValue, 10); +} +function getMonthEndDay(year, month) { + return 32 - new Date(year, month - 1, 32).getDate(); +} +const defaultFormatter = (type, value) => value; +CwComponent({ + classes: ['active-class', 'toolbar-class', 'column-class'], + props: Object.assign(Object.assign({}, pickerProps), { + value: { + type: null, + observer: 'updateValue' + }, + filter: null, + type: { + type: String, + value: 'datetime', + observer: 'updateValue' + }, + showToolbar: { + type: Boolean, + value: true + }, + formatter: { + type: null, + value: defaultFormatter + }, + minDate: { + type: Number, + value: new Date(currentYear - 10, 0, 1).getTime(), + observer: 'updateValue' + }, + maxDate: { + type: Number, + value: new Date(currentYear + 10, 11, 31).getTime(), + observer: 'updateValue' + }, + minHour: { + type: Number, + value: 0, + observer: 'updateValue' + }, + maxHour: { + type: Number, + value: 23, + observer: 'updateValue' + }, + minMinute: { + type: Number, + value: 0, + observer: 'updateValue' + }, + maxMinute: { + type: Number, + value: 59, + observer: 'updateValue' + } + }), + data: { + innerValue: Date.now(), + columns: [] + }, + methods: { + updateValue() { + const { data } = this; + const val = this.correctValue(data.value); + const isEqual = val === data.innerValue; + if (!isEqual) { + this.updateColumnValue(val).then(() => { + this.$emit('input', val); + }); + } else { + this.updateColumns(); + } + }, + getPicker() { + if (this.picker == null) { + this.picker = this.selectComponent('.cw-datetime-picker'); + const { picker } = this; + const { setColumnValues } = picker; + picker.setColumnValues = (...args) => setColumnValues.apply(picker, [...args, false]); + } + return this.picker; + }, + updateColumns() { + const { formatter = defaultFormatter } = this.data; + const results = this.getOriginColumns().map(column => ({ + values: column.values.map(value => formatter(column.type, value)) + })); + return this.set({ columns: results }); + }, + getOriginColumns() { + const { filter } = this.data; + const results = this.getRanges().map(({ type, range }) => { + let values = times(range[1] - range[0] + 1, index => { + let value = range[0] + index; + value = type === 'year' ? `${value}` : padZero(value); + return value; + }); + if (filter) { + values = filter(type, values); + } + return { type, values }; + }); + return results; + }, + getRanges() { + const { data } = this; + if (data.type === 'time') { + return [ + { + type: 'hour', + range: [data.minHour, data.maxHour] + }, + { + type: 'minute', + range: [data.minMinute, data.maxMinute] + } + ]; + } + const { maxYear, maxDate, maxMonth, maxHour, maxMinute } = this.getBoundary('max', data.innerValue); + const { minYear, minDate, minMonth, minHour, minMinute } = this.getBoundary('min', data.innerValue); + const result = [ + { + type: 'year', + range: [minYear, maxYear] + }, + { + type: 'month', + range: [minMonth, maxMonth] + }, + { + type: 'day', + range: [minDate, maxDate] + }, + { + type: 'hour', + range: [minHour, maxHour] + }, + { + type: 'minute', + range: [minMinute, maxMinute] + } + ]; + if (data.type === 'date') result.splice(3, 2); + if (data.type === 'year-month') result.splice(2, 3); + return result; + }, + correctValue(value) { + const { data } = this; + // validate value + const isDateType = data.type !== 'time'; + if (isDateType && !isValidDate(value)) { + value = data.minDate; + } else if (!isDateType && !value) { + const { minHour } = data; + value = `${padZero(minHour)}:00`; + } + // time type + if (!isDateType) { + let [hour, minute] = value.split(':'); + hour = padZero(range(hour, data.minHour, data.maxHour)); + minute = padZero(range(minute, data.minMinute, data.maxMinute)); + return `${hour}:${minute}`; + } + // date type + value = Math.max(value, data.minDate); + value = Math.min(value, data.maxDate); + return value; + }, + getBoundary(type, innerValue) { + const value = new Date(innerValue); + const boundary = new Date(this.data[`${type}Date`]); + const year = boundary.getFullYear(); + let month = 1; + let date = 1; + let hour = 0; + let minute = 0; + if (type === 'max') { + month = 12; + date = getMonthEndDay(value.getFullYear(), value.getMonth() + 1); + hour = 23; + minute = 59; + } + if (value.getFullYear() === year) { + month = boundary.getMonth() + 1; + if (value.getMonth() + 1 === month) { + date = boundary.getDate(); + if (value.getDate() === date) { + hour = boundary.getHours(); + if (value.getHours() === hour) { + minute = boundary.getMinutes(); + } + } + } + } + return { + [`${type}Year`]: year, + [`${type}Month`]: month, + [`${type}Date`]: date, + [`${type}Hour`]: hour, + [`${type}Minute`]: minute + }; + }, + onCancel() { + this.$emit('cancel'); + }, + onConfirm() { + this.$emit('confirm', this.data.innerValue); + }, + onChange() { + const { data } = this; + let value; + const picker = this.getPicker(); + const originColumns = this.getOriginColumns(); + if (data.type === 'time') { + const indexes = picker.getIndexes(); + value = `${+originColumns[0].values[indexes[0]]}:${+originColumns[1].values[indexes[1]]}`; + } else { + const indexes = picker.getIndexes(); + const values = indexes.map((value, index) => originColumns[index].values[value]); + const year = getTrueValue(values[0]); + const month = getTrueValue(values[1]); + const maxDate = getMonthEndDay(year, month); + let date = getTrueValue(values[2]); + if (data.type === 'year-month') { + date = 1; + } + date = date > maxDate ? maxDate : date; + let hour = 0; + let minute = 0; + if (data.type === 'datetime') { + hour = getTrueValue(values[3]); + minute = getTrueValue(values[4]); + } + value = new Date(year, month - 1, date, hour, minute); + } + value = this.correctValue(value); + this.updateColumnValue(value).then(() => { + this.$emit('input', value); + this.$emit('change', picker); + }); + }, + updateColumnValue(value) { + let values = []; + const { type } = this.data; + const formatter = this.data.formatter || defaultFormatter; + const picker = this.getPicker(); + if (type === 'time') { + const pair = value.split(':'); + values = [formatter('hour', pair[0]), formatter('minute', pair[1])]; + } else { + const date = new Date(value); + values = [formatter('year', `${date.getFullYear()}`), formatter('month', padZero(date.getMonth() + 1))]; + if (type === 'date') { + values.push(formatter('day', padZero(date.getDate()))); + } + if (type === 'datetime') { + values.push( + formatter('day', padZero(date.getDate())), + formatter('hour', padZero(date.getHours())), + formatter('minute', padZero(date.getMinutes())) + ); + } + } + return this.set({ innerValue: value }) + .then(() => this.updateColumns()) + .then(() => picker.setValues(values)); + } + }, + created() { + const innerValue = this.correctValue(this.data.value); + this.updateColumnValue(innerValue).then(() => { + this.$emit('input', innerValue); + }); + } +}); diff --git a/employee-mp/src/components/datetime-picker/index.json b/employee-mp/src/components/datetime-picker/index.json new file mode 100644 index 0000000..8e19f5d --- /dev/null +++ b/employee-mp/src/components/datetime-picker/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-picker": "../picker/index" + } +} diff --git a/employee-mp/src/components/datetime-picker/index.wxml b/employee-mp/src/components/datetime-picker/index.wxml new file mode 100644 index 0000000..658a5ac --- /dev/null +++ b/employee-mp/src/components/datetime-picker/index.wxml @@ -0,0 +1,16 @@ + diff --git a/employee-mp/src/components/datetime-picker/index.wxss b/employee-mp/src/components/datetime-picker/index.wxss new file mode 100644 index 0000000..ecfdfde --- /dev/null +++ b/employee-mp/src/components/datetime-picker/index.wxss @@ -0,0 +1 @@ +@import '../common/index.wxss'; diff --git a/employee-mp/src/components/definitions/index.js b/employee-mp/src/components/definitions/index.js new file mode 100644 index 0000000..f150f20 --- /dev/null +++ b/employee-mp/src/components/definitions/index.js @@ -0,0 +1,13 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export {}; diff --git a/employee-mp/src/components/dialog/dialog.js b/employee-mp/src/components/dialog/dialog.js new file mode 100644 index 0000000..f6ca05e --- /dev/null +++ b/employee-mp/src/components/dialog/dialog.js @@ -0,0 +1,93 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +let queue = []; +const defaultOptions = { + show: false, + title: '', + width: null, + theme: 'default', + message: '', + zIndex: 100, + overlay: true, + selector: '#cw-dialog', + className: '', + asyncClose: false, + beforeClose: null, + transition: 'scale', + customStyle: '', + messageAlign: '', + overlayStyle: '', + confirmButtonText: '确认', + cancelButtonText: '取消', + showConfirmButton: true, + showCancelButton: false, + closeOnClickOverlay: false, + confirmButtonOpenType: '' +}; +let currentOptions = Object.assign({}, defaultOptions); +function getContext() { + const pages = getCurrentPages(); + return pages[pages.length - 1]; +} +const Dialog = options => { + options = Object.assign(Object.assign({}, currentOptions), options); + return new Promise((resolve, reject) => { + const context = options.context || getContext(); + const dialog = context.selectComponent(options.selector); + delete options.context; + delete options.selector; + if (dialog) { + dialog.setData( + Object.assign( + { + callback: (action, instance) => { + action === 'confirm' ? resolve(instance) : reject(instance); + } + }, + options + ) + ); + wx.nextTick(() => { + dialog.setData({ show: true }); + }); + queue.push(dialog); + } else { + console.warn('未找到 cw-dialog 节点,请确认 selector 及 context 是否正确'); + } + }); +}; +Dialog.alert = options => Dialog(options); +Dialog.confirm = options => Dialog(Object.assign({ showCancelButton: true }, options)); +Dialog.close = () => { + queue.forEach(dialog => { + dialog.close(); + }); + queue = []; +}; +Dialog.stopLoading = () => { + queue.forEach(dialog => { + dialog.stopLoading(); + }); +}; +Dialog.currentOptions = currentOptions; +Dialog.defaultOptions = defaultOptions; +Dialog.setDefaultOptions = options => { + currentOptions = Object.assign(Object.assign({}, currentOptions), options); + Dialog.currentOptions = currentOptions; +}; +Dialog.resetDefaultOptions = () => { + currentOptions = Object.assign({}, defaultOptions); + Dialog.currentOptions = currentOptions; +}; +Dialog.resetDefaultOptions(); +export default Dialog; diff --git a/employee-mp/src/components/dialog/index.js b/employee-mp/src/components/dialog/index.js new file mode 100644 index 0000000..4a955f7 --- /dev/null +++ b/employee-mp/src/components/dialog/index.js @@ -0,0 +1,134 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { button } from '../mixins/button'; +import { openType } from '../mixins/open-type'; +import { GRAY, RED } from '../common/color'; +import { toPromise } from '../common/utils'; +CwComponent({ + mixins: [button, openType], + props: { + show: { + type: Boolean, + observer(show) { + !show && this.stopLoading(); + } + }, + title: String, + message: String, + theme: { + type: String, + value: 'default' + }, + useSlot: Boolean, + className: String, + customStyle: String, + asyncClose: Boolean, + messageAlign: String, + beforeClose: null, + overlayStyle: String, + useTitleSlot: Boolean, + showCancelButton: Boolean, + closeOnClickOverlay: Boolean, + confirmButtonOpenType: String, + width: null, + zIndex: { + type: Number, + value: 2000 + }, + confirmButtonText: { + type: String, + value: '确认' + }, + cancelButtonText: { + type: String, + value: '取消' + }, + confirmButtonColor: { + type: String, + value: RED + }, + cancelButtonColor: { + type: String, + value: GRAY + }, + showConfirmButton: { + type: Boolean, + value: true + }, + overlay: { + type: Boolean, + value: true + }, + transition: { + type: String, + value: 'scale' + } + }, + data: { + loading: { + confirm: false, + cancel: false + }, + callback: () => {} + }, + methods: { + onConfirm() { + this.handleAction('confirm'); + }, + onCancel() { + this.handleAction('cancel'); + }, + onClickOverlay() { + this.close('overlay'); + }, + close(action) { + this.setData({ show: false }); + wx.nextTick(() => { + this.$emit('close', action); + const { callback } = this.data; + if (callback) { + callback(action, this); + } + }); + }, + stopLoading() { + this.setData({ + loading: { + confirm: false, + cancel: false + } + }); + }, + handleAction(action) { + this.$emit(action, { dialog: this }); + const { asyncClose, beforeClose } = this.data; + if (!asyncClose && !beforeClose) { + this.close(action); + return; + } + this.setData({ + [`loading.${action}`]: true + }); + if (beforeClose) { + toPromise(beforeClose(action)).then(value => { + if (value) { + this.close(action); + } else { + this.stopLoading(); + } + }); + } + } + } +}); diff --git a/employee-mp/src/components/dialog/index.json b/employee-mp/src/components/dialog/index.json new file mode 100644 index 0000000..d1db410 --- /dev/null +++ b/employee-mp/src/components/dialog/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "cw-popup": "../popup/index", + "cw-button": "../button/index" + } +} diff --git a/employee-mp/src/components/dialog/index.wxml b/employee-mp/src/components/dialog/index.wxml new file mode 100644 index 0000000..7657c26 --- /dev/null +++ b/employee-mp/src/components/dialog/index.wxml @@ -0,0 +1,69 @@ + + + + + + {{ title }} + + + + + {{ message }} + + + + + {{ cancelButtonText }} + + + {{ confirmButtonText }} + + + diff --git a/employee-mp/src/components/dialog/index.wxss b/employee-mp/src/components/dialog/index.wxss new file mode 100644 index 0000000..cc0a5ea --- /dev/null +++ b/employee-mp/src/components/dialog/index.wxss @@ -0,0 +1,89 @@ +@import '../common/index.wxss'; + +.cw-dialog { + top: 45% !important; + overflow: hidden; + width: 320px; + font-size: 16px; + border-radius: 16px; + background-color: #fff; +} + +@media (max-width: 321px) { + .cw-dialog { + width: 90%; + } +} + +.cw-dialog__header { + text-align: center; + padding-top: 24px; + font-weight: 500; + line-height: 24px; +} + +.cw-dialog__header--isolated { + padding: 24px 0; +} + +.cw-dialog__message { + overflow-y: auto; + text-align: center; + -webkit-overflow-scrolling: touch; + font-size: 14px; + line-height: 20px; + max-height: 60vh; + padding: 24px; +} + +.cw-dialog__message-text { + word-wrap: break-word; +} + +.cw-dialog__message--hasTitle { + padding-top: 8px; + color: #646566; +} + +.cw-dialog__message--round-button { + padding-bottom: 16px; + color: #323233; +} + +.cw-dialog__message--left { + text-align: left; +} + +.cw-dialog__message--right { + text-align: right; +} + +.cw-dialog__footer { + display: -webkit-flex; + display: flex; +} + +.cw-dialog__footer--round-button { + position: relative !important; + padding: 8px 24px 16px !important; +} + +.cw-dialog__button { + -webkit-flex: 1; + flex: 1; +} + +.cw-dialog__cancel, +.cw-dialog__confirm { + border: 0 !important; +} + +.cw-dialog-bounce-enter { + transform: translate3d(-50%, -50%, 0) scale(0.7); + opacity: 0; +} + +.cw-dialog-bounce-leave-active { + transform: translate3d(-50%, -50%, 0) scale(0.9); + opacity: 0; +} diff --git a/employee-mp/src/components/divider/index.js b/employee-mp/src/components/divider/index.js new file mode 100644 index 0000000..8d4d113 --- /dev/null +++ b/employee-mp/src/components/divider/index.js @@ -0,0 +1,24 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +CwComponent({ + props: { + dashed: Boolean, + hairline: Boolean, + contentPosition: String, + fontSize: String, + borderColor: String, + textColor: String, + customStyle: String + } +}); diff --git a/employee-mp/src/components/divider/index.json b/employee-mp/src/components/divider/index.json new file mode 100644 index 0000000..59a1db6 --- /dev/null +++ b/employee-mp/src/components/divider/index.json @@ -0,0 +1,4 @@ +{ + "component": true, + "usingComponents": {} +} diff --git a/employee-mp/src/components/divider/index.wxml b/employee-mp/src/components/divider/index.wxml new file mode 100644 index 0000000..9d47f21 --- /dev/null +++ b/employee-mp/src/components/divider/index.wxml @@ -0,0 +1,9 @@ + + + + + + diff --git a/employee-mp/src/components/divider/index.wxs b/employee-mp/src/components/divider/index.wxs new file mode 100644 index 0000000..42f5210 --- /dev/null +++ b/employee-mp/src/components/divider/index.wxs @@ -0,0 +1,17 @@ +var style = require('../wxs/style.wxs'); +var addUnit = require('../wxs/add-unit.wxs'); + +function rootStyle(data) { + return style([ + { + 'border-color': data.borderColor, + color: data.textColor, + 'font-size': addUnit(data.fontSize) + }, + data.customStyle + ]); +} + +module.exports = { + rootStyle: rootStyle +}; diff --git a/employee-mp/src/components/divider/index.wxss b/employee-mp/src/components/divider/index.wxss new file mode 100644 index 0000000..93af82e --- /dev/null +++ b/employee-mp/src/components/divider/index.wxss @@ -0,0 +1,60 @@ +@import '../common/index.wxss'; + +.cw-divider { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + margin: 16px 0; + color: #969799; + font-size: 12px; + line-height: 24px; + border: 0 solid #ebedf0; +} + +.cw-divider:after, +.cw-divider:before { + display: block; + -webkit-flex: 1; + flex: 1; + box-sizing: border-box; + height: 1px; + border-color: inherit; + border-style: inherit; + border-width: 1px 0 0; +} + +.cw-divider:before { + content: ''; +} + +.cw-divider--hairline:after, +.cw-divider--hairline:before { + -webkit-transform: scaleY(0.5); + transform: scaleY(0.5); +} + +.cw-divider--dashed { + border-style: dashed; +} + +.cw-divider--center:before, +.cw-divider--left:before, +.cw-divider--right:before { + margin-right: 16px; +} + +.cw-divider--center:after, +.cw-divider--left:after, +.cw-divider--right:after { + content: ''; + margin-left: 16px; +} + +.cw-divider--left:before { + max-width: 10%; +} + +.cw-divider--right:after { + max-width: 10%; +} diff --git a/employee-mp/src/components/dropdown-item/index.js b/employee-mp/src/components/dropdown-item/index.js new file mode 100644 index 0000000..acf8f52 --- /dev/null +++ b/employee-mp/src/components/dropdown-item/index.js @@ -0,0 +1,115 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { useParent } from '../common/relation'; +import { CwComponent } from '../common/component'; +CwComponent({ + field: true, + relation: useParent('dropdown-menu', function() { + this.updateDataFromParent(); + }), + props: { + value: { + type: null, + observer: 'rerender' + }, + title: { + type: String, + observer: 'rerender' + }, + disabled: Boolean, + titleClass: { + type: String, + observer: 'rerender' + }, + options: { + type: Array, + value: [], + observer: 'rerender' + }, + popupStyle: String + }, + data: { + transition: true, + showPopup: false, + showWrapper: false, + displayTitle: '' + }, + methods: { + rerender() { + wx.nextTick(() => { + var _a; + (_a = this.parent) === null || _a === void 0 ? void 0 : _a.updateItemListData(); + }); + }, + updateDataFromParent() { + if (this.parent) { + const { overlay, duration, activeColor, closeOnClickOverlay, direction } = this.parent.data; + this.setData({ + overlay, + duration, + activeColor, + closeOnClickOverlay, + direction + }); + } + }, + onOpen() { + this.$emit('open'); + }, + onOpened() { + this.$emit('opened'); + }, + onClose() { + this.$emit('close'); + }, + onClosed() { + this.$emit('closed'); + this.setData({ showWrapper: false }); + }, + onOptionTap(event) { + const { option } = event.currentTarget.dataset; + const { value } = option; + const shouldEmitChange = this.data.value !== value; + this.setData({ showPopup: false, value }); + this.$emit('close'); + this.rerender(); + if (shouldEmitChange) { + this.$emit('change', value); + } + }, + toggle(show, options = {}) { + var _a; + const { showPopup } = this.data; + if (typeof show !== 'boolean') { + show = !showPopup; + } + if (show === showPopup) { + return; + } + this.setData({ + transition: !options.immediate, + showPopup: show + }); + if (show) { + (_a = this.parent) === null || _a === void 0 + ? void 0 + : _a.getChildWrapperStyle().then(wrapperStyle => { + this.setData({ wrapperStyle, showWrapper: true }); + this.rerender(); + }); + } else { + this.rerender(); + } + } + } +}); diff --git a/employee-mp/src/components/dropdown-item/index.json b/employee-mp/src/components/dropdown-item/index.json new file mode 100644 index 0000000..0b1bf7b --- /dev/null +++ b/employee-mp/src/components/dropdown-item/index.json @@ -0,0 +1,8 @@ +{ + "component": true, + "usingComponents": { + "cw-popup": "../popup/index", + "cw-cell": "../cell/index", + "cw-icon": "../icon/index" + } +} diff --git a/employee-mp/src/components/dropdown-item/index.wxml b/employee-mp/src/components/dropdown-item/index.wxml new file mode 100644 index 0000000..8b9ade0 --- /dev/null +++ b/employee-mp/src/components/dropdown-item/index.wxml @@ -0,0 +1,44 @@ + + + + + + + {{ item.text }} + + + + + + + diff --git a/employee-mp/src/components/dropdown-item/index.wxss b/employee-mp/src/components/dropdown-item/index.wxss new file mode 100644 index 0000000..be287dc --- /dev/null +++ b/employee-mp/src/components/dropdown-item/index.wxss @@ -0,0 +1,30 @@ +@import '../common/index.wxss'; + +.cw-dropdown-item { + position: fixed; + right: 0; + left: 0; + overflow: hidden; +} + +.cw-dropdown-item__option { + text-align: left; +} + +.cw-dropdown-item__option--active .cw-dropdown-item__icon, +.cw-dropdown-item__option--active .cw-dropdown-item__title { + color: #ee0a24; +} + +.cw-dropdown-item--up { + top: 0; +} + +.cw-dropdown-item--down { + bottom: 0; +} + +.cw-dropdown-item__icon { + display: block; + line-height: inherit; +} diff --git a/employee-mp/src/components/dropdown-item/shared.js b/employee-mp/src/components/dropdown-item/shared.js new file mode 100644 index 0000000..f150f20 --- /dev/null +++ b/employee-mp/src/components/dropdown-item/shared.js @@ -0,0 +1,13 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export {}; diff --git a/employee-mp/src/components/dropdown-menu/index.js b/employee-mp/src/components/dropdown-menu/index.js new file mode 100644 index 0000000..b85a3c8 --- /dev/null +++ b/employee-mp/src/components/dropdown-menu/index.js @@ -0,0 +1,120 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; +import { useChildren } from '../common/relation'; +import { addUnit, getRect, getSystemInfoSync } from '../common/utils'; +let ARRAY = []; +CwComponent({ + field: true, + relation: useChildren('dropdown-item', function() { + this.updateItemListData(); + }), + props: { + activeColor: { + type: String, + observer: 'updateChildrenData' + }, + overlay: { + type: Boolean, + value: true, + observer: 'updateChildrenData' + }, + zIndex: { + type: Number, + value: 10 + }, + duration: { + type: Number, + value: 200, + observer: 'updateChildrenData' + }, + direction: { + type: String, + value: 'down', + observer: 'updateChildrenData' + }, + closeOnClickOverlay: { + type: Boolean, + value: true, + observer: 'updateChildrenData' + }, + closeOnClickOutside: { + type: Boolean, + value: true + } + }, + data: { + itemListData: [] + }, + beforeCreate() { + const { windowHeight } = getSystemInfoSync(); + this.windowHeight = windowHeight; + ARRAY.push(this); + }, + destroyed() { + ARRAY = ARRAY.filter(item => item !== this); + }, + methods: { + updateItemListData() { + this.setData({ + itemListData: this.children.map(child => child.data) + }); + }, + updateChildrenData() { + this.children.forEach(child => { + child.updateDataFromParent(); + }); + }, + toggleItem(active) { + this.children.forEach((item, index) => { + const { showPopup } = item.data; + if (index === active) { + item.toggle(); + } else if (showPopup) { + item.toggle(false, { immediate: true }); + } + }); + }, + close() { + this.children.forEach(child => { + child.toggle(false, { immediate: true }); + }); + }, + getChildWrapperStyle() { + const { zIndex, direction } = this.data; + return getRect(this, '.cw-dropdown-menu').then(rect => { + const { top = 0, bottom = 0 } = rect; + const offset = direction === 'down' ? bottom : this.windowHeight - top; + let wrapperStyle = `z-index: ${zIndex};`; + if (direction === 'down') { + wrapperStyle += `top: ${addUnit(offset)};`; + } else { + wrapperStyle += `bottom: ${addUnit(offset)};`; + } + return wrapperStyle; + }); + }, + onTitleTap(event) { + const { index } = event.currentTarget.dataset; + const child = this.children[index]; + if (!child.data.disabled) { + ARRAY.forEach(menuItem => { + if (menuItem && menuItem.data.closeOnClickOutside && menuItem !== this) { + menuItem.close(); + } + }); + this.toggleItem(index); + } + } + } +}); diff --git a/employee-mp/src/components/dropdown-menu/index.json b/employee-mp/src/components/dropdown-menu/index.json new file mode 100644 index 0000000..10e7f9d --- /dev/null +++ b/employee-mp/src/components/dropdown-menu/index.json @@ -0,0 +1,3 @@ +{ + "component": true +} diff --git a/employee-mp/src/components/dropdown-menu/index.wxml b/employee-mp/src/components/dropdown-menu/index.wxml new file mode 100644 index 0000000..a3aaf5c --- /dev/null +++ b/employee-mp/src/components/dropdown-menu/index.wxml @@ -0,0 +1,23 @@ + + + + + + + + {{ computed.displayTitle(item) }} + + + + + + diff --git a/employee-mp/src/components/dropdown-menu/index.wxs b/employee-mp/src/components/dropdown-menu/index.wxs new file mode 100644 index 0000000..b283b75 --- /dev/null +++ b/employee-mp/src/components/dropdown-menu/index.wxs @@ -0,0 +1,15 @@ +function displayTitle(item) { + if (item.title) { + return item.title; + } + + var match = item.options.filter(function(option) { + return option.value === item.value; + }); + var displayTitle = match.length ? match[0].text : ''; + return displayTitle; +} + +module.exports = { + displayTitle: displayTitle +}; diff --git a/employee-mp/src/components/dropdown-menu/index.wxss b/employee-mp/src/components/dropdown-menu/index.wxss new file mode 100644 index 0000000..63754d5 --- /dev/null +++ b/employee-mp/src/components/dropdown-menu/index.wxss @@ -0,0 +1,69 @@ +@import '../common/index.wxss'; + +.cw-dropdown-menu { + display: -webkit-flex; + display: flex; + box-shadow: 0 2px 12px rgba(100, 101, 102, 0.12); + -webkit-user-select: none; + user-select: none; + height: 50px; + background-color: #fff; +} + +.cw-dropdown-menu__item { + display: -webkit-flex; + display: flex; + -webkit-flex: 1; + flex: 1; + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center; + min-width: 0; +} + +.cw-dropdown-menu__item:active { + opacity: 0.7; +} + +.cw-dropdown-menu__item--disabled:active { + opacity: 1; +} + +.cw-dropdown-menu__item--disabled .cw-dropdown-menu__title { + color: #969799; +} + +.cw-dropdown-menu__title { + position: relative; + box-sizing: border-box; + max-width: 100%; + padding: 0 8px; + color: #323233; + font-size: 14px; + line-height: 18px; +} + +.cw-dropdown-menu__title:after { + position: absolute; + top: 50%; + right: -4px; + margin-top: -5px; + border-color: transparent transparent currentcolor currentcolor; + border-style: solid; + border-width: 3px; + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + opacity: 0.8; + content: ''; +} + +.cw-dropdown-menu__title--active { + color: #ee0a24; +} + +.cw-dropdown-menu__title--down:after { + margin-top: -1px; + -webkit-transform: rotate(135deg); + transform: rotate(135deg); +} diff --git a/employee-mp/src/components/empty/index.js b/employee-mp/src/components/empty/index.js new file mode 100644 index 0000000..e130702 --- /dev/null +++ b/employee-mp/src/components/empty/index.js @@ -0,0 +1,34 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { CwComponent } from '../common/component'; + +CwComponent({ + props: { + description: { + type: String, + value: '暂无内容' + }, + icon: { + type: String, + value: 'empty' + }, + fixed: { + type: Boolean, + value: true + }, + withCopyright: { + type: Boolean, + value: false + } + } +}); diff --git a/employee-mp/src/components/empty/index.json b/employee-mp/src/components/empty/index.json new file mode 100644 index 0000000..503bd1a --- /dev/null +++ b/employee-mp/src/components/empty/index.json @@ -0,0 +1,6 @@ +{ + "component": true, + "usingComponents": { + "cw-icon": "../icon" + } +} diff --git a/employee-mp/src/components/empty/index.wxml b/employee-mp/src/components/empty/index.wxml new file mode 100644 index 0000000..84069eb --- /dev/null +++ b/employee-mp/src/components/empty/index.wxml @@ -0,0 +1,14 @@ + + + + + + + + + {{ description }} + + + + + diff --git a/employee-mp/src/components/empty/index.wxss b/employee-mp/src/components/empty/index.wxss new file mode 100644 index 0000000..01f3007 --- /dev/null +++ b/employee-mp/src/components/empty/index.wxss @@ -0,0 +1,39 @@ +@import '../common/index.wxss'; +.cw-empty { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + box-sizing: border-box; +} + +.cw-empty.fixed { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: constant(safe-area-inset-bottom); + bottom: env(safe-area-inset-bottom); +} + +.cw-empty.with-copyright { + padding-bottom: 122px; +} + +.cw-empty__icon { + font-size: 154px; + color: #d8d8d8; + line-height: 1; +} + +.cw-empty__description { + margin-top: 16px; + padding: 0 60px; + color: #989899; + font-size: 14px; + line-height: 20px; +} + +.cw-empty__bottom { + margin-top: 24px; +} diff --git a/employee-mp/src/components/field/index.js b/employee-mp/src/components/field/index.js new file mode 100644 index 0000000..cc0dc29 --- /dev/null +++ b/employee-mp/src/components/field/index.js @@ -0,0 +1,132 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +import { nextTick } from '../common/utils'; +import { CwComponent } from '../common/component'; +import { commonProps, inputProps, textareaProps } from './props'; +CwComponent({ + field: true, + classes: ['input-class', 'right-icon-class', 'label-class'], + props: Object.assign(Object.assign(Object.assign(Object.assign({}, commonProps), inputProps), textareaProps), { + size: String, + icon: String, + label: String, + error: Boolean, + center: Boolean, + isLink: Boolean, + leftIcon: String, + rightIcon: String, + autosize: null, + required: Boolean, + iconClass: String, + clickable: Boolean, + inputAlign: String, + customStyle: String, + errorMessage: String, + arrowDirection: String, + showWordLimit: Boolean, + errorMessageAlign: String, + readonly: { + type: Boolean, + observer: 'setShowClear' + }, + clearable: { + type: Boolean, + observer: 'setShowClear' + }, + border: { + type: Boolean, + value: true + }, + titleWidth: { + type: String, + value: '6.2em' + } + }), + data: { + focused: false, + innerValue: '', + showClear: false + }, + created() { + this.value = this.data.value; + this.setData({ innerValue: this.value }); + }, + methods: { + onInput(event) { + const { value = '' } = event.detail || {}; + this.value = value; + this.setShowClear(); + this.emitChange(); + }, + onFocus(event) { + this.focused = true; + this.setShowClear(); + this.$emit('focus', event.detail); + }, + onBlur(event) { + this.focused = false; + this.setShowClear(); + this.$emit('blur', event.detail); + }, + onClickIcon() { + this.$emit('click-icon'); + }, + onClickInput(event) { + this.$emit('click-input', event.detail); + }, + onClear() { + this.setData({ innerValue: '' }); + this.value = ''; + this.setShowClear(); + nextTick(() => { + this.emitChange(); + this.$emit('clear', ''); + }); + }, + onConfirm(event) { + const { value = '' } = event.detail || {}; + this.value = value; + this.setShowClear(); + this.$emit('confirm', value); + }, + setValue(value) { + this.value = value; + this.setShowClear(); + if (value === '') { + this.setData({ innerValue: '' }); + } + this.emitChange(); + }, + onLineChange(event) { + this.$emit('linechange', event.detail); + }, + onKeyboardHeightChange(event) { + this.$emit('keyboardheightchange', event.detail); + }, + emitChange() { + this.setData({ value: this.value }); + nextTick(() => { + this.$emit('input', this.value); + this.$emit('change', this.value); + }); + }, + setShowClear() { + const { clearable, readonly } = this.data; + const { focused, value } = this; + this.setData({ + showClear: !!clearable && !!focused && !!value && !readonly + }); + }, + noop() {} + } +}); diff --git a/employee-mp/src/components/field/index.json b/employee-mp/src/components/field/index.json new file mode 100644 index 0000000..d9ab7c8 --- /dev/null +++ b/employee-mp/src/components/field/index.json @@ -0,0 +1,7 @@ +{ + "component": true, + "usingComponents": { + "cw-cell": "../cell/index", + "cw-icon": "../icon/index" + } +} diff --git a/employee-mp/src/components/field/index.wxml b/employee-mp/src/components/field/index.wxml new file mode 100644 index 0000000..963f272 --- /dev/null +++ b/employee-mp/src/components/field/index.wxml @@ -0,0 +1,62 @@ + + + + + + + {{ label }} + + + + + + + + + + + + + + + + + + + + + + {{ value.length >= maxlength ? maxlength : value.length }} + + /{{ maxlength }} + + + {{ errorMessage }} + + diff --git a/employee-mp/src/components/field/index.wxs b/employee-mp/src/components/field/index.wxs new file mode 100644 index 0000000..44e4630 --- /dev/null +++ b/employee-mp/src/components/field/index.wxs @@ -0,0 +1,17 @@ +var style = require('../wxs/style.wxs'); +var addUnit = require('../wxs/add-unit.wxs'); + +function inputStyle(autosize) { + if (autosize && autosize.constructor === 'Object') { + return style({ + 'min-height': addUnit(autosize.minHeight), + 'max-height': addUnit(autosize.maxHeight) + }); + } + + return ''; +} + +module.exports = { + inputStyle: inputStyle +}; diff --git a/employee-mp/src/components/field/index.wxss b/employee-mp/src/components/field/index.wxss new file mode 100644 index 0000000..4468404 --- /dev/null +++ b/employee-mp/src/components/field/index.wxss @@ -0,0 +1,167 @@ +@import '../common/index.wxss'; + +.cw-field__label { + color: #323233; +} + +.cw-field__label--disabled { + color: #c8c9cc; +} + +.cw-field__body { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; +} + +.cw-field__body--textarea { + box-sizing: border-box; + padding: 3.6px 0; + line-height: 1.2em; + min-height: 24px; +} + +.cw-field__control:empty + .cw-field__control { + display: block; +} + +.cw-field__control { + position: relative; + display: none; + box-sizing: border-box; + width: 100%; + margin: 0; + padding: 0; + line-height: inherit; + text-align: left; + background-color: initial; + border: 0; + resize: none; + color: #323233; + height: 24px; + min-height: 24px; +} + +.cw-field__control:empty { + display: none; +} + +.cw-field__control--textarea { + height: 18px; + min-height: 18px; +} + +.cw-field__control--error { + color: #ee0a24; +} + +.cw-field__control--disabled { + background-color: initial; + opacity: 1; + color: #c8c9cc; +} + +.cw-field__control--center { + text-align: center; +} + +.cw-field__control--right { + text-align: right; +} + +.cw-field__control--custom { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + min-height: 24px; +} + +.cw-field__placeholder { + position: absolute; + top: 0; + right: 0; + left: 0; + pointer-events: none; + color: #c8c9cc; +} + +.cw-field__placeholder--error { + color: #ee0a24; +} + +.cw-field__icon-root { + display: -webkit-flex; + display: flex; + -webkit-align-items: center; + align-items: center; + min-height: 24px; +} + +.cw-field__clear-root, +.cw-field__icon-container { + line-height: inherit; + vertical-align: middle; + padding: 0 8px; + margin-right: -8px; +} + +.cw-field__button, +.cw-field__clear-root, +.cw-field__icon-container { + -webkit-flex-shrink: 0; + flex-shrink: 0; +} + +.cw-field__clear-root { + font-size: 16px; + color: #c8c9cc; +} + +.cw-field__icon-container { + font-size: 16px; + color: #969799; +} + +.cw-field__icon-container:empty { + display: none; +} + +.cw-field__button { + padding-left: 8px; +} + +.cw-field__button:empty { + display: none; +} + +.cw-field__error-message { + text-align: left; + font-size: 12px; + color: #ee0a24; +} + +.cw-field__error-message--center { + text-align: center; +} + +.cw-field__error-message--right { + text-align: right; +} + +.cw-field__word-limit { + text-align: right; + margin-top: 4px; + color: #646566; + font-size: 12px; + line-height: 16px; +} + +.cw-field__word-num { + display: inline; +} + +.cw-field__word-num--full { + color: #ee0a24; +} diff --git a/employee-mp/src/components/field/input.wxml b/employee-mp/src/components/field/input.wxml new file mode 100644 index 0000000..a18fe80 --- /dev/null +++ b/employee-mp/src/components/field/input.wxml @@ -0,0 +1,27 @@ + diff --git a/employee-mp/src/components/field/props.js b/employee-mp/src/components/field/props.js new file mode 100644 index 0000000..81d1aa9 --- /dev/null +++ b/employee-mp/src/components/field/props.js @@ -0,0 +1,75 @@ +/** + * +---------------------------------------------------------------------- + * | 「e家宜业」 —— 助力物业服务升级,用心服务万千业主 + * +---------------------------------------------------------------------- + * | Copyright (c) 2020~2021 https://www.chowa.com All rights reserved. + * +---------------------------------------------------------------------- + * | Licensed 未经许可不能去掉「e家宜业」和「卓瓦科技」相关版权 + * +---------------------------------------------------------------------- + * | Author: jixuecong@chowa.cn + * +---------------------------------------------------------------------- + */ + +export const commonProps = { + value: { + type: String, + observer(value) { + if (value !== this.value) { + this.setData({ innerValue: value }); + this.value = value; + } + } + }, + placeholder: String, + placeholderStyle: String, + placeholderClass: String, + disabled: Boolean, + maxlength: { + type: Number, + value: -1 + }, + cursorSpacing: { + type: Number, + value: 50 + }, + autoFocus: Boolean, + focus: Boolean, + cursor: { + type: Number, + value: -1 + }, + selectionStart: { + type: Number, + value: -1 + }, + selectionEnd: { + type: Number, + value: -1 + }, + adjustPosition: { + type: Boolean, + value: true + }, + holdKeyboard: Boolean +}; +export const inputProps = { + type: { + type: String, + value: 'text' + }, + password: Boolean, + confirmType: String, + confirmHold: Boolean +}; +export const textareaProps = { + autoHeight: Boolean, + fixed: Boolean, + showConfirmBar: { + type: Boolean, + value: true + }, + disableDefaultPadding: { + type: Boolean, + value: true + } +}; diff --git a/employee-mp/src/components/field/textarea.wxml b/employee-mp/src/components/field/textarea.wxml new file mode 100644 index 0000000..a493500 --- /dev/null +++ b/employee-mp/src/components/field/textarea.wxml @@ -0,0 +1,29 @@ +