v1.0.0
This commit is contained in:
commit
04256ba341
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -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
|
674
LICENSE
Normal file
674
LICENSE
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
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.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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:
|
||||
|
||||
<program> 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
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
126
README.MD
Normal file
126
README.MD
Normal file
@ -0,0 +1,126 @@
|
||||

|
||||
|
||||
<h1 align="center">🔥🔥🔥「e家宜业」开源物业管理系统</h1>
|
||||
<p align="center">
|
||||
<b>无加密,无阉割,喜欢的话就点右上角 "Star" 支持一下吧,每一个"Star",都是我们持续更新的动力!</b>
|
||||
</p>
|
||||
|
||||
## 项目介绍
|
||||
|
||||
「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端
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### 业主端
|
||||
|
||||
<p align="center" >
|
||||
<img src="readme/ower1.jpg" width="320"/>
|
||||
<img src="readme/ower2.jpg" width="320"/>
|
||||
<img src="readme/ower3.jpg" width="320"/>
|
||||
<img src="readme/ower4.jpg" width="320"/>
|
||||
<img src="readme/ower5.jpg" width="320"/>
|
||||
<img src="readme/ower6.jpg" width="320"/>
|
||||
<img src="readme/ower7.jpg" width="320"/>
|
||||
<img src="readme/ower8.jpg" width="320"/>
|
||||
</p>
|
||||
|
||||
### 员工端
|
||||
<p align="center" >
|
||||
<img src="readme/pc1.jpg" width="320"/>
|
||||
<img src="readme/pc2.jpg" width="320"/>
|
||||
<img src="readme/pc3.jpg" width="320"/>
|
||||
<img src="readme/pc4.jpg" width="320"/>
|
||||
<img src="readme/pc5.jpg" width="320"/>
|
||||
</p>
|
||||
|
||||
## 如何部署
|
||||
|
||||
### 服务器环境推荐要求
|
||||
* 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
|
||||
|
||||
### 微信公众号
|
||||

|
||||
|
||||
### 业主小程序
|
||||

|
||||
|
||||
### 物业员工小程序
|
||||

|
||||
|
||||
|
||||
## 开源版使用说明
|
||||
|
||||
1.允许用于个人学习、教学案例、公益事业;
|
||||
|
||||
2.如果商用必须保留版权信息(请尊重开源,开源不易),请自觉遵守,未经授权修改版权信息后自负,如果需要去版权请进群联系管理员或者微信扫描下方二维码;
|
||||
|
||||
3.禁止将本项目的代码和资源进行任何形式的出售,产生的一切任何后果责任由侵权者自负。
|
||||
|
||||
|
||||
## 参与开发
|
||||
|
||||
[欢迎反馈问题](https://github.com/chowa/ejyy/issues)
|
||||
[欢迎提交代码](https://github.com/chowa/ejyy/pulls)
|
||||
|
||||
## 定制和二次开发
|
||||
|
||||
>请加微信,请备注来意
|
||||
|
||||

|
||||
|
||||
## 支持
|
||||
|
||||
开源不易,欢迎给我打赏 ———— 以激励我持续更新和维护项目
|
||||
|
||||
<img src="readme/pay.jpg" width="320"/>
|
2
employee-mp/.prettierignore
Normal file
2
employee-mp/.prettierignore
Normal file
@ -0,0 +1,2 @@
|
||||
*.png
|
||||
*.jpg
|
34
employee-mp/README.MD
Normal file
34
employee-mp/README.MD
Normal file
@ -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';
|
||||
|
||||
```
|
9
employee-mp/package.json
Normal file
9
employee-mp/package.json
Normal file
@ -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/**/**/**/**/*"
|
||||
}
|
||||
}
|
32
employee-mp/prettier.config.js
Normal file
32
employee-mp/prettier.config.js
Normal file
@ -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'
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
74
employee-mp/project.config.json
Normal file
74
employee-mp/project.config.json
Normal file
@ -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": []
|
||||
}
|
||||
}
|
||||
}
|
54
employee-mp/project.private.config.json
Normal file
54
employee-mp/project.private.config.json
Normal file
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
163
employee-mp/src/app.js
Normal file
163
employee-mp/src/app.js
Normal file
@ -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();
|
||||
}
|
||||
});
|
58
employee-mp/src/app.json
Normal file
58
employee-mp/src/app.json
Normal file
@ -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"
|
||||
}
|
53
employee-mp/src/app.wxss
Normal file
53
employee-mp/src/app.wxss
Normal file
@ -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;
|
||||
}
|
BIN
employee-mp/src/assets/common/chowa.png
Normal file
BIN
employee-mp/src/assets/common/chowa.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
BIN
employee-mp/src/assets/common/logo.png
Normal file
BIN
employee-mp/src/assets/common/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 90 KiB |
BIN
employee-mp/src/assets/login/welcome.jpg
Normal file
BIN
employee-mp/src/assets/login/welcome.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 KiB |
BIN
employee-mp/src/assets/recommand.jpg
Normal file
BIN
employee-mp/src/assets/recommand.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
74
employee-mp/src/components/action-sheet/index.js
Normal file
74
employee-mp/src/components/action-sheet/index.js
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
8
employee-mp/src/components/action-sheet/index.json
Normal file
8
employee-mp/src/components/action-sheet/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-icon": "../icon/index",
|
||||
"cw-popup": "../popup/index",
|
||||
"cw-loading": "../loading/index"
|
||||
}
|
||||
}
|
65
employee-mp/src/components/action-sheet/index.wxml
Normal file
65
employee-mp/src/components/action-sheet/index.wxml
Normal file
@ -0,0 +1,65 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<cw-popup
|
||||
show="{{ show }}"
|
||||
position="bottom"
|
||||
round="{{ round }}"
|
||||
z-index="{{ zIndex }}"
|
||||
overlay="{{ overlay }}"
|
||||
custom-class="cw-action-sheet"
|
||||
safe-area-inset-bottom="{{ safeAreaInsetBottom }}"
|
||||
close-on-click-overlay="{{ closeOnClickOverlay }}"
|
||||
bind:close="onClickOverlay"
|
||||
>
|
||||
<view wx:if="{{ title }}" class="cw-action-sheet__header">
|
||||
{{ title }}
|
||||
<cw-icon name="cross" custom-class="cw-action-sheet__close" bind:click="onClose" />
|
||||
</view>
|
||||
<view wx:if="{{ description }}" class="cw-action-sheet__description cw-hairline--bottom">
|
||||
{{ description }}
|
||||
</view>
|
||||
<view wx:if="{{ actions && actions.length }}">
|
||||
<!-- button外包一层view,防止actions动态变化,导致渲染时button被打散 -->
|
||||
<button
|
||||
wx:for="{{ actions }}"
|
||||
wx:key="index"
|
||||
open-type="{{ item.openType }}"
|
||||
style="{{ item.color ? 'color: ' + item.color : '' }}"
|
||||
class="{{ utils.bem('action-sheet__item', { disabled: item.disabled || item.loading }) }} {{ item.className || '' }}"
|
||||
hover-class="cw-action-sheet__item--hover"
|
||||
data-index="{{ index }}"
|
||||
bind:tap="onSelect"
|
||||
bindgetuserinfo="bindGetUserInfo"
|
||||
bindcontact="bindContact"
|
||||
bindgetphonenumber="bindGetPhoneNumber"
|
||||
binderror="bindError"
|
||||
bindlaunchapp="bindLaunchApp"
|
||||
bindopensetting="bindOpenSetting"
|
||||
lang="{{ lang }}"
|
||||
session-from="{{ sessionFrom }}"
|
||||
send-message-title="{{ sendMessageTitle }}"
|
||||
send-message-path="{{ sendMessagePath }}"
|
||||
send-message-img="{{ sendMessageImg }}"
|
||||
show-message-card="{{ showMessageCard }}"
|
||||
app-parameter="{{ appParameter }}"
|
||||
>
|
||||
<block wx:if="{{ !item.loading }}">
|
||||
{{ item.name }}
|
||||
<view wx:if="{{ item.subname }}" class="cw-action-sheet__subname">{{ item.subname }}</view>
|
||||
</block>
|
||||
<cw-loading wx:else custom-class="cw-action-sheet__loading" size="22px" />
|
||||
</button>
|
||||
</view>
|
||||
<slot />
|
||||
<block wx:if="{{ cancelText }}">
|
||||
<view class="cw-action-sheet__gap" />
|
||||
<view
|
||||
class="cw-action-sheet__cancel"
|
||||
hover-class="cw-action-sheet__cancel--hover"
|
||||
hover-stay-time="70"
|
||||
bind:tap="onCancel"
|
||||
>
|
||||
{{ cancelText }}
|
||||
</view>
|
||||
</block>
|
||||
</cw-popup>
|
80
employee-mp/src/components/action-sheet/index.wxss
Normal file
80
employee-mp/src/components/action-sheet/index.wxss
Normal file
@ -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;
|
||||
}
|
70
employee-mp/src/components/button/index.js
Normal file
70
employee-mp/src/components/button/index.js
Normal file
@ -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() {}
|
||||
}
|
||||
});
|
7
employee-mp/src/components/button/index.json
Normal file
7
employee-mp/src/components/button/index.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-icon": "../icon/index",
|
||||
"cw-loading": "../loading/index"
|
||||
}
|
||||
}
|
53
employee-mp/src/components/button/index.wxml
Normal file
53
employee-mp/src/components/button/index.wxml
Normal file
@ -0,0 +1,53 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
<wxs src="./index.wxs" module="computed" />
|
||||
|
||||
<button
|
||||
id="{{ id }}"
|
||||
data-detail="{{ dataset }}"
|
||||
class="custom-class {{ utils.bem('button', [type, size, { block, round, plain, square, loading, disabled, hairline, unclickable: disabled || loading }]) }} {{ hairline ? 'cw-hairline--surround' : '' }}"
|
||||
hover-class="cw-button--active hover-class"
|
||||
lang="{{ lang }}"
|
||||
form-type="{{ formType }}"
|
||||
style="{{ computed.rootStyle({ plain, color, customStyle }) }}"
|
||||
open-type="{{ disabled ? '' : openType }}"
|
||||
business-id="{{ businessId }}"
|
||||
session-from="{{ sessionFrom }}"
|
||||
send-message-title="{{ sendMessageTitle }}"
|
||||
send-message-path="{{ sendMessagePath }}"
|
||||
send-message-img="{{ sendMessageImg }}"
|
||||
show-message-card="{{ showMessageCard }}"
|
||||
app-parameter="{{ appParameter }}"
|
||||
aria-label="{{ ariaLabel }}"
|
||||
bindtap="{{ !disabled ? 'onClick' : 'noop' }}"
|
||||
bindgetuserinfo="bindGetUserInfo"
|
||||
bindcontact="bindContact"
|
||||
bindgetphonenumber="bindGetPhoneNumber"
|
||||
binderror="bindError"
|
||||
bindlaunchapp="bindLaunchApp"
|
||||
bindopensetting="bindOpenSetting"
|
||||
>
|
||||
<block wx:if="{{ loading }}">
|
||||
<cw-loading
|
||||
custom-class="loading-class"
|
||||
size="{{ loadingSize }}"
|
||||
type="{{ loadingType }}"
|
||||
color="{{ computed.loadingColor({ type, color, plain }) }}"
|
||||
/>
|
||||
<view wx:if="{{ loadingText }}" class="cw-button__loading-text">
|
||||
{{ loadingText }}
|
||||
</view>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<cw-icon
|
||||
wx:if="{{ icon }}"
|
||||
size="1.2em"
|
||||
name="{{ icon }}"
|
||||
class-prefix="{{ classPrefix }}"
|
||||
class="cw-button__icon"
|
||||
custom-style="line-height: inherit;"
|
||||
/>
|
||||
<view class="cw-button__text">
|
||||
<slot />
|
||||
</view>
|
||||
</block>
|
||||
</button>
|
38
employee-mp/src/components/button/index.wxs
Normal file
38
employee-mp/src/components/button/index.wxs
Normal file
@ -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
|
||||
};
|
180
employee-mp/src/components/button/index.wxss
Normal file
180
employee-mp/src/components/button/index.wxss
Normal file
@ -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;
|
||||
}
|
48
employee-mp/src/components/calendar/calendar.wxml
Normal file
48
employee-mp/src/components/calendar/calendar.wxml
Normal file
@ -0,0 +1,48 @@
|
||||
<view class="cw-calendar">
|
||||
<header title="{{ title }}" showTitle="{{ showTitle }}" subtitle="{{ subtitle }}" showSubtitle="{{ showSubtitle }}">
|
||||
<slot name="title" slot="title"></slot>
|
||||
</header>
|
||||
|
||||
<scroll-view class="cw-calendar__body" scroll-y scroll-into-view="{{ scrollIntoView }}">
|
||||
<month
|
||||
wx:for="{{ computed.getMonths(minDate, maxDate) }}"
|
||||
wx:key="index"
|
||||
id="month{{ index }}"
|
||||
class="month"
|
||||
data-date="{{ item }}"
|
||||
date="{{ item }}"
|
||||
type="{{ type }}"
|
||||
color="{{ color }}"
|
||||
minDate="{{ minDate }}"
|
||||
maxDate="{{ maxDate }}"
|
||||
showMark="{{ showMark }}"
|
||||
formatter="{{ formatter }}"
|
||||
rowHeight="{{ rowHeight }}"
|
||||
currentDate="{{ currentDate }}"
|
||||
showSubtitle="{{ showSubtitle }}"
|
||||
allowSameDay="{{ allowSameDay }}"
|
||||
showMonthTitle="{{ index !== 0 || !showSubtitle }}"
|
||||
bind:click="onClickDay"
|
||||
/>
|
||||
</scroll-view>
|
||||
|
||||
<view class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}">
|
||||
<slot name="footer"></slot>
|
||||
</view>
|
||||
|
||||
<view class="{{ utils.bem('calendar__footer', { safeAreaInsetBottom }) }}">
|
||||
<cw-button
|
||||
wx:if="{{ showConfirm }}"
|
||||
round
|
||||
block
|
||||
type="danger"
|
||||
color="{{ color }}"
|
||||
custom-class="cw-calendar__confirm"
|
||||
disabled="{{ computed.getButtonDisabled(type, currentDate) }}"
|
||||
nativeType="text"
|
||||
bind:click="onConfirm"
|
||||
>
|
||||
{{ computed.getButtonDisabled(type, currentDate) ? confirmDisabledText : confirmText }}
|
||||
</cw-button>
|
||||
</view>
|
||||
</view>
|
@ -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: {}
|
||||
});
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<view class="cw-calendar__header">
|
||||
<block wx:if="{{ showTitle }}">
|
||||
<view class="cw-calendar__header-title"><slot name="title"></slot></view>
|
||||
<view class="cw-calendar__header-title">{{ title }}</view>
|
||||
</block>
|
||||
|
||||
<view wx:if="{{ showSubtitle }}" class="cw-calendar__header-subtitle">
|
||||
{{ subtitle }}
|
||||
</view>
|
||||
|
||||
<view class="cw-calendar__weekdays">
|
||||
<view wx:for="{{ weekdays }}" wx:key="index" class="cw-calendar__weekday">
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
@ -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;
|
||||
}
|
160
employee-mp/src/components/calendar/components/month/index.js
Normal file
160
employee-mp/src/components/calendar/components/month/index.js
Normal file
@ -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 '开始/结束';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<wxs src="./index.wxs" module="computed"></wxs>
|
||||
<wxs src="../../../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<view class="cw-calendar__month" style="{{ computed.getMonthStyle(visible, date, rowHeight) }}">
|
||||
<view wx:if="{{ showMonthTitle }}" class="cw-calendar__month-title">
|
||||
{{ computed.formatMonthTitle(date) }}
|
||||
</view>
|
||||
|
||||
<view wx:if="{{ visible }}" class="cw-calendar__days">
|
||||
<view wx:if="{{ showMark }}" class="cw-calendar__month-mark">
|
||||
{{ computed.getMark(date) }}
|
||||
</view>
|
||||
|
||||
<view
|
||||
wx:for="{{ days }}"
|
||||
wx:key="index"
|
||||
style="{{ computed.getDayStyle(item.type, index, date, rowHeight, color) }}"
|
||||
class="{{ utils.bem('calendar__day', [item.type]) }} {{ item.className }}"
|
||||
data-index="{{ index }}"
|
||||
bindtap="onClick"
|
||||
>
|
||||
<view
|
||||
wx:if="{{ item.type === 'selected' }}"
|
||||
class="cw-calendar__selected-day"
|
||||
style="background: {{ color }}"
|
||||
>
|
||||
<view wx:if="{{ item.topInfo }}" class="cw-calendar__top-info">{{ item.topInfo }}</view>
|
||||
{{ item.text }}
|
||||
<view wx:if="{{ item.bottomInfo }}" class="cw-calendar__bottom-info">
|
||||
{{ item.bottomInfo }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view wx:else>
|
||||
<view wx:if="{{ item.topInfo }}" class="cw-calendar__top-info">{{ item.topInfo }}</view>
|
||||
{{ item.text }}
|
||||
<view wx:if="{{ item.bottomInfo }}" class="cw-calendar__bottom-info">
|
||||
{{ item.bottomInfo }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
@ -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
|
||||
};
|
132
employee-mp/src/components/calendar/components/month/index.wxss
Normal file
132
employee-mp/src/components/calendar/components/month/index.wxss
Normal file
@ -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;
|
||||
}
|
289
employee-mp/src/components/calendar/index.js
Normal file
289
employee-mp/src/components/calendar/index.js
Normal file
@ -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));
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
10
employee-mp/src/components/calendar/index.json
Normal file
10
employee-mp/src/components/calendar/index.json
Normal file
@ -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"
|
||||
}
|
||||
}
|
25
employee-mp/src/components/calendar/index.wxml
Normal file
25
employee-mp/src/components/calendar/index.wxml
Normal file
@ -0,0 +1,25 @@
|
||||
<wxs src="./index.wxs" module="computed" />
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<import src="./calendar.wxml" />
|
||||
|
||||
<cw-popup
|
||||
wx:if="{{ poppable }}"
|
||||
custom-class="cw-calendar__popup--{{ position }}"
|
||||
close-icon-class="cw-calendar__close-icon"
|
||||
show="{{ show }}"
|
||||
round="{{ round }}"
|
||||
position="{{ position }}"
|
||||
closeable="{{ showTitle || showSubtitle }}"
|
||||
close-on-click-overlay="{{ closeOnClickOverlay }}"
|
||||
bind:enter="onOpen"
|
||||
bind:close="onClose"
|
||||
bind:after-enter="onOpened"
|
||||
bind:after-leave="onClosed"
|
||||
>
|
||||
<include src="calendar.wxml" />
|
||||
</cw-popup>
|
||||
|
||||
<include wx:else src="calendar.wxml" />
|
||||
|
||||
<cw-toast id="cw-toast" />
|
36
employee-mp/src/components/calendar/index.wxs
Normal file
36
employee-mp/src/components/calendar/index.wxs
Normal file
@ -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
|
||||
};
|
56
employee-mp/src/components/calendar/index.wxss
Normal file
56
employee-mp/src/components/calendar/index.wxss
Normal file
@ -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;
|
||||
}
|
90
employee-mp/src/components/calendar/utils.js
Normal file
90
employee-mp/src/components/calendar/utils.js
Normal file
@ -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;
|
||||
}
|
24
employee-mp/src/components/calendar/utils.wxs
Normal file
24
employee-mp/src/components/calendar/utils.wxs
Normal file
@ -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
|
||||
};
|
103
employee-mp/src/components/car-number/index.js
Normal file
103
employee-mp/src/components/car-number/index.js
Normal file
@ -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', '');
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
6
employee-mp/src/components/car-number/index.json
Normal file
6
employee-mp/src/components/car-number/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-icon": "../icon/index"
|
||||
}
|
||||
}
|
63
employee-mp/src/components/car-number/index.wxml
Normal file
63
employee-mp/src/components/car-number/index.wxml
Normal file
@ -0,0 +1,63 @@
|
||||
<view>
|
||||
<view class="cw-car-number-items">
|
||||
<view class="cw-car-number-items-box" bindtap="openKeyboard">
|
||||
<view class="cw-car-number-items-province cw-car-number-items-box-list">{{carNumber[0] || ""}}</view>
|
||||
<view class="cw-car-number-items-city cw-car-number-items-box-list">{{carNumber[1] || ""}}</view>
|
||||
</view>
|
||||
<!-- 常规 -->
|
||||
<view class="cw-car-number-item" bindtap="openKeyboard">{{carNumber[2] || ''}}</view>
|
||||
<view class="cw-car-number-item" bindtap="openKeyboard">{{carNumber[3] || ''}}</view>
|
||||
<view class="cw-car-number-item" bindtap="openKeyboard">{{carNumber[4] || ''}}</view>
|
||||
<view class="cw-car-number-item" bindtap="openKeyboard">{{carNumber[5] || ''}}</view>
|
||||
<view class="cw-car-number-item" bindtap="openKeyboard">{{carNumber[6] || ''}}</view>
|
||||
<!-- 新能源 -->
|
||||
<view class="cw-car-number-item" bindtap="openKeyboard" wx:if="{{isNewEnergy}}">
|
||||
{{carNumber[7] || ''}}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 虚拟键盘 -->
|
||||
<view class="cw-keyboard" hidden="{{!keyboardVisible}}">
|
||||
<view class="cw-keyboard-close">
|
||||
<view class="cw-keyboard-close-btn" bindtap="closeKeyboard">
|
||||
<cw-icon name="keyboard-hide" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 省份简写键盘 -->
|
||||
<view class="cw-keyboard-item" hidden="{{carNumber[0]}}">
|
||||
<view class="cw-keyboard-line" wx:for="{{provinces}}" wx:key="index">
|
||||
<view
|
||||
class="cw-keyboard-btn"
|
||||
wx:for="{{item}}"
|
||||
wx:key="index"
|
||||
data-val="{{itemlist}}"
|
||||
wx:for-item="itemlist"
|
||||
bindtap="bindChoose"
|
||||
>
|
||||
{{itemlist}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="cw-keyboard-del" bindtap="bindDelChoose">
|
||||
<cw-icon name="backspace" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 车牌号码选择键盘 -->
|
||||
<view class="cw-keyboard-item iscarnumber" hidden="{{!carNumber[0]}}">
|
||||
<view class="cw-keyboard-line" wx:for="{{numbers}}" wx:key="index">
|
||||
<view
|
||||
class="cw-keyboard-btn"
|
||||
wx:for="{{item}}"
|
||||
wx:key="index"
|
||||
data-val="{{itemlist}}"
|
||||
wx:for-item="itemlist"
|
||||
bindtap="bindChoose"
|
||||
>
|
||||
{{itemlist}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="cw-keyboard-del" bindtap="bindDelChoose">
|
||||
<cw-icon name="backspace" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
140
employee-mp/src/components/car-number/index.wxss
Normal file
140
employee-mp/src/components/car-number/index.wxss
Normal file
@ -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;
|
||||
}
|
54
employee-mp/src/components/card/index.js
Normal file
54
employee-mp/src/components/card/index.js
Normal file
@ -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');
|
||||
}
|
||||
}
|
||||
});
|
6
employee-mp/src/components/card/index.json
Normal file
6
employee-mp/src/components/card/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-tag": "../tag/index"
|
||||
}
|
||||
}
|
53
employee-mp/src/components/card/index.wxml
Normal file
53
employee-mp/src/components/card/index.wxml
Normal file
@ -0,0 +1,53 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<view class="custom-class cw-card">
|
||||
<view class="{{ utils.bem('card__header', { center: centered }) }}">
|
||||
<view class="cw-card__thumb" bind:tap="onClickThumb">
|
||||
<image
|
||||
wx:if="{{ thumb }}"
|
||||
src="{{ thumb }}"
|
||||
mode="{{ thumbMode }}"
|
||||
lazy-load="{{ lazyLoad }}"
|
||||
class="cw-card__img thumb-class"
|
||||
/>
|
||||
<slot wx:else name="thumb" />
|
||||
<cw-tag wx:if="{{ tag }}" mark type="danger" custom-class="cw-card__tag">
|
||||
{{ tag }}
|
||||
</cw-tag>
|
||||
<slot wx:else name="tag" />
|
||||
</view>
|
||||
|
||||
<view class="cw-card__content {{ utils.bem('card__content', { center: centered }) }}">
|
||||
<view>
|
||||
<view wx:if="{{ title }}" class="cw-card__title title-class">{{ title }}</view>
|
||||
<slot wx:else name="title" />
|
||||
|
||||
<view wx:if="{{ desc }}" class="cw-card__desc desc-class">{{ desc }}</view>
|
||||
<slot wx:else name="desc" />
|
||||
|
||||
<slot name="tags" />
|
||||
</view>
|
||||
|
||||
<view class="cw-card__bottom">
|
||||
<slot name="price-top" />
|
||||
<view wx:if="{{ price || price === 0 }}" class="cw-card__price price-class">
|
||||
<text>{{ currency }}</text>
|
||||
<text class="cw-card__price-integer">{{ integerStr }}</text>
|
||||
<text class="cw-card__price-decimal">{{ decimalStr }}</text>
|
||||
</view>
|
||||
<slot wx:else name="price" />
|
||||
<view wx:if="{{ originPrice || originPrice === 0 }}" class="cw-card__origin-price origin-price-class">
|
||||
{{ currency }} {{ originPrice }}
|
||||
</view>
|
||||
<slot wx:else name="origin-price" />
|
||||
<view wx:if="{{ num }}" class="cw-card__num num-class">x {{ num }}</view>
|
||||
<slot wx:else name="num" />
|
||||
<slot name="bottom" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="cw-card__footer">
|
||||
<slot name="footer" />
|
||||
</view>
|
||||
</view>
|
120
employee-mp/src/components/card/index.wxss
Normal file
120
employee-mp/src/components/card/index.wxss
Normal file
@ -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;
|
||||
}
|
22
employee-mp/src/components/cell-group/index.js
Normal file
22
employee-mp/src/components/cell-group/index.js
Normal file
@ -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
|
||||
}
|
||||
}
|
||||
});
|
3
employee-mp/src/components/cell-group/index.json
Normal file
3
employee-mp/src/components/cell-group/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
6
employee-mp/src/components/cell-group/index.wxml
Normal file
6
employee-mp/src/components/cell-group/index.wxml
Normal file
@ -0,0 +1,6 @@
|
||||
<view wx:if="{{ title }}" class="cw-cell-group__title">
|
||||
{{ title }}
|
||||
</view>
|
||||
<view class="custom-class cw-cell-group {{ border ? 'cw-hairline--top-bottom' : '' }}">
|
||||
<slot />
|
||||
</view>
|
8
employee-mp/src/components/cell-group/index.wxss
Normal file
8
employee-mp/src/components/cell-group/index.wxss
Normal file
@ -0,0 +1,8 @@
|
||||
@import '../common/index.wxss';
|
||||
|
||||
.cw-cell-group__title {
|
||||
padding: 16px 16px 8px;
|
||||
font-size: 14px;
|
||||
line-height: 16px;
|
||||
color: #969799;
|
||||
}
|
45
employee-mp/src/components/cell/index.js
Normal file
45
employee-mp/src/components/cell/index.js
Normal file
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
6
employee-mp/src/components/cell/index.json
Normal file
6
employee-mp/src/components/cell/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-icon": "../icon/index"
|
||||
}
|
||||
}
|
38
employee-mp/src/components/cell/index.wxml
Normal file
38
employee-mp/src/components/cell/index.wxml
Normal file
@ -0,0 +1,38 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
<wxs src="./index.wxs" module="computed" />
|
||||
|
||||
<view
|
||||
class="custom-class {{ utils.bem('cell', [size, { center, required, borderless: !border, clickable: isLink || clickable, detail: isDetail }]) }}"
|
||||
hover-class="cw-cell--hover hover-class"
|
||||
hover-stay-time="70"
|
||||
style="{{ customStyle }}"
|
||||
bind:tap="onClick"
|
||||
>
|
||||
<cw-icon wx:if="{{ icon }}" name="{{ icon }}" class="cw-cell__left-icon-wrap" custom-class="cw-cell__left-icon" />
|
||||
<slot wx:else name="icon" />
|
||||
|
||||
<view style="{{ computed.titleStyle({ titleWidth, titleStyle }) }}" class="cw-cell__title title-class">
|
||||
<block wx:if="{{ title }}">{{ title }}</block>
|
||||
<slot wx:else name="title" />
|
||||
|
||||
<view wx:if="{{ label || useLabelSlot }}" class="cw-cell__label label-class">
|
||||
<slot wx:if="{{ useLabelSlot }}" name="label" />
|
||||
<block wx:elif="{{ label }}">{{ label }}</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="cw-cell__value value-class {{title ? '' : 'only'}}">
|
||||
<block wx:if="{{ value || value === 0 }}">{{ value }}</block>
|
||||
<slot wx:else />
|
||||
</view>
|
||||
|
||||
<cw-icon
|
||||
wx:if="{{ isLink }}"
|
||||
name="{{ arrowDirection ? 'arrow' + '-' + arrowDirection : 'arrow' }}"
|
||||
class="cw-cell__right-icon-wrap right-icon-class"
|
||||
custom-class="cw-cell__right-icon"
|
||||
/>
|
||||
<slot wx:else name="right-icon" />
|
||||
|
||||
<slot name="extra" />
|
||||
</view>
|
16
employee-mp/src/components/cell/index.wxs
Normal file
16
employee-mp/src/components/cell/index.wxs
Normal file
@ -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
|
||||
};
|
141
employee-mp/src/components/cell/index.wxss
Normal file
141
employee-mp/src/components/cell/index.wxss
Normal file
@ -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;
|
||||
}
|
43
employee-mp/src/components/checkbox-group/index.js
Normal file
43
employee-mp/src/components/checkbox-group/index.js
Normal file
@ -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
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
3
employee-mp/src/components/checkbox-group/index.json
Normal file
3
employee-mp/src/components/checkbox-group/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
1
employee-mp/src/components/checkbox-group/index.wxml
Normal file
1
employee-mp/src/components/checkbox-group/index.wxml
Normal file
@ -0,0 +1 @@
|
||||
<slot />
|
1
employee-mp/src/components/checkbox-group/index.wxss
Normal file
1
employee-mp/src/components/checkbox-group/index.wxss
Normal file
@ -0,0 +1 @@
|
||||
@import '../common/index.wxss';
|
87
employee-mp/src/components/checkbox/index.js
Normal file
87
employee-mp/src/components/checkbox/index.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
6
employee-mp/src/components/checkbox/index.json
Normal file
6
employee-mp/src/components/checkbox/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-icon": "../icon/index"
|
||||
}
|
||||
}
|
31
employee-mp/src/components/checkbox/index.wxml
Normal file
31
employee-mp/src/components/checkbox/index.wxml
Normal file
@ -0,0 +1,31 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
<wxs src="./index.wxs" module="computed" />
|
||||
|
||||
<view class="cw-checkbox custom-class">
|
||||
<view
|
||||
wx:if="{{ labelPosition === 'left' }}"
|
||||
class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
|
||||
bindtap="onClickLabel"
|
||||
>
|
||||
<slot />
|
||||
</view>
|
||||
<view class="cw-checkbox__icon-wrap" bindtap="toggle">
|
||||
<slot wx:if="{{ useIconSlot }}" name="icon" />
|
||||
<cw-icon
|
||||
wx:else
|
||||
name="success"
|
||||
size="0.8em"
|
||||
class="{{ utils.bem('checkbox__icon', [shape, { disabled: disabled || parentDisabled, checked: value }]) }}"
|
||||
style="{{ computed.iconStyle(checkedColor, value, disabled, parentDisabled, iconSize) }}"
|
||||
custom-class="icon-class"
|
||||
custom-style="line-height: 1.25em;"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
wx:if="{{ labelPosition === 'right' }}"
|
||||
class="label-class {{ utils.bem('checkbox__label', [labelPosition, { disabled: disabled || parentDisabled }]) }}"
|
||||
bindtap="onClickLabel"
|
||||
>
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
19
employee-mp/src/components/checkbox/index.wxs
Normal file
19
employee-mp/src/components/checkbox/index.wxs
Normal file
@ -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
|
||||
};
|
77
employee-mp/src/components/checkbox/index.wxss
Normal file
77
employee-mp/src/components/checkbox/index.wxss
Normal file
@ -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;
|
||||
}
|
55
employee-mp/src/components/circle/canvas.js
Normal file
55
employee-mp/src/components/circle/canvas.js
Normal file
@ -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() {}
|
||||
});
|
||||
}
|
194
employee-mp/src/components/circle/index.js
Normal file
194
employee-mp/src/components/circle/index.js
Normal file
@ -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();
|
||||
}
|
||||
});
|
3
employee-mp/src/components/circle/index.json
Normal file
3
employee-mp/src/components/circle/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
15
employee-mp/src/components/circle/index.wxml
Normal file
15
employee-mp/src/components/circle/index.wxml
Normal file
@ -0,0 +1,15 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<view class="cw-circle">
|
||||
<canvas
|
||||
class="cw-circle__canvas"
|
||||
type="{{ type }}"
|
||||
style="width: {{ utils.addUnit(size) }};height:{{ utils.addUnit(size) }}"
|
||||
id="cw-circle"
|
||||
canvas-id="cw-circle"
|
||||
></canvas>
|
||||
<view wx:if="{{ !text }}" class="cw-circle__text">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<cover-view wx:else class="cw-circle__text">{{ text }}</cover-view>
|
||||
</view>
|
17
employee-mp/src/components/circle/index.wxss
Normal file
17
employee-mp/src/components/circle/index.wxss
Normal file
@ -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;
|
||||
}
|
21
employee-mp/src/components/col/index.js
Normal file
21
employee-mp/src/components/col/index.js
Normal file
@ -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
|
||||
}
|
||||
});
|
3
employee-mp/src/components/col/index.json
Normal file
3
employee-mp/src/components/col/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
9
employee-mp/src/components/col/index.wxml
Normal file
9
employee-mp/src/components/col/index.wxml
Normal file
@ -0,0 +1,9 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
<wxs src="./index.wxs" module="computed" />
|
||||
|
||||
<view
|
||||
class="custom-class {{ utils.bem('col', [span]) }} {{ offset ? 'cw-col--offset-' + offset : '' }}"
|
||||
style="{{ computed.rootStyle({ gutter }) }}"
|
||||
>
|
||||
<slot />
|
||||
</view>
|
17
employee-mp/src/components/col/index.wxs
Normal file
17
employee-mp/src/components/col/index.wxs
Normal file
@ -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
|
||||
};
|
198
employee-mp/src/components/col/index.wxss
Normal file
198
employee-mp/src/components/col/index.wxss
Normal file
@ -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%;
|
||||
}
|
90
employee-mp/src/components/collapse-item/animate.js
Normal file
90
employee-mp/src/components/collapse-item/animate.js
Normal file
@ -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);
|
||||
});
|
||||
}
|
69
employee-mp/src/components/collapse-item/index.js
Normal file
69
employee-mp/src/components/collapse-item/index.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
6
employee-mp/src/components/collapse-item/index.json
Normal file
6
employee-mp/src/components/collapse-item/index.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-cell": "../cell/index"
|
||||
}
|
||||
}
|
29
employee-mp/src/components/collapse-item/index.wxml
Normal file
29
employee-mp/src/components/collapse-item/index.wxml
Normal file
@ -0,0 +1,29 @@
|
||||
<wxs src="../wxs/utils.wxs" module="utils" />
|
||||
|
||||
<view class="cw-collapse-item custom-class {{ index !== 0 ? 'cw-hairline--top' : '' }}">
|
||||
<cw-cell
|
||||
title="{{ title }}"
|
||||
title-class="title-class"
|
||||
icon="{{ icon }}"
|
||||
value="{{ value }}"
|
||||
label="{{ label }}"
|
||||
is-link="{{ isLink }}"
|
||||
clickable="{{ clickable }}"
|
||||
border="{{ border && expanded }}"
|
||||
class="{{ utils.bem('collapse-item__title', { disabled, expanded }) }}"
|
||||
right-icon-class="cw-cell__right-icon"
|
||||
custom-class="cw-cell"
|
||||
hover-class="cw-cell--hover"
|
||||
bind:click="onClick"
|
||||
>
|
||||
<slot name="title" slot="title" />
|
||||
<slot name="icon" slot="icon" />
|
||||
<slot name="value" />
|
||||
<slot name="right-icon" slot="right-icon" />
|
||||
</cw-cell>
|
||||
<view class="{{ utils.bem('collapse-item__wrapper') }}" style="height: 0;" animation="{{ animation }}">
|
||||
<view class="cw-collapse-item__content content-class">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
35
employee-mp/src/components/collapse-item/index.wxss
Normal file
35
employee-mp/src/components/collapse-item/index.wxss
Normal file
@ -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;
|
||||
}
|
54
employee-mp/src/components/collapse/index.js
Normal file
54
employee-mp/src/components/collapse/index.js
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
});
|
3
employee-mp/src/components/collapse/index.json
Normal file
3
employee-mp/src/components/collapse/index.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"component": true
|
||||
}
|
3
employee-mp/src/components/collapse/index.wxml
Normal file
3
employee-mp/src/components/collapse/index.wxml
Normal file
@ -0,0 +1,3 @@
|
||||
<view class="custom-class cw-collapse {{ border ? 'cw-hairline--top-bottom' : '' }}">
|
||||
<slot />
|
||||
</view>
|
1
employee-mp/src/components/collapse/index.wxss
Normal file
1
employee-mp/src/components/collapse/index.wxss
Normal file
@ -0,0 +1 @@
|
||||
@import '../common/index.wxss';
|
61
employee-mp/src/components/colleague/index.js
Normal file
61
employee-mp/src/components/colleague/index.js
Normal file
@ -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 });
|
||||
}
|
||||
}
|
||||
});
|
8
employee-mp/src/components/colleague/index.json
Normal file
8
employee-mp/src/components/colleague/index.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"cw-cell": "../cell",
|
||||
"cw-cell-group": "../cell-group",
|
||||
"cw-popup": "../popup"
|
||||
}
|
||||
}
|
17
employee-mp/src/components/colleague/index.wxml
Normal file
17
employee-mp/src/components/colleague/index.wxml
Normal file
@ -0,0 +1,17 @@
|
||||
<cw-popup show="{{ show }}" closeable round position="bottom" custom-style="height: 80%" bind:close="onClose">
|
||||
<cw-cell-group wx:for="{{map}}" wx:key="index" title="{{item.name}}">
|
||||
<cw-cell
|
||||
wx:for="{{item.users}}"
|
||||
wx:for-index="key"
|
||||
wx:for-item="row"
|
||||
wx:key="key"
|
||||
title="{{row.real_name}}"
|
||||
border="{{key === item.users.length - 1 ? false : true}}"
|
||||
value="{{row.job}}"
|
||||
clickable
|
||||
data-id="{{row.id}}"
|
||||
data-name="{{row.real_name}}"
|
||||
bind:click="select"
|
||||
/>
|
||||
</cw-cell-group>
|
||||
</cw-popup>
|
0
employee-mp/src/components/colleague/index.wxss
Normal file
0
employee-mp/src/components/colleague/index.wxss
Normal file
19
employee-mp/src/components/common/color.js
Normal file
19
employee-mp/src/components/common/color.js
Normal file
@ -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';
|
57
employee-mp/src/components/common/component.js
Normal file
57
employee-mp/src/components/common/component.js
Normal file
@ -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 };
|
83
employee-mp/src/components/common/index.wxss
Normal file
83
employee-mp/src/components/common/index.wxss
Normal file
@ -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;
|
||||
}
|
74
employee-mp/src/components/common/relation.js
Normal file
74
employee-mp/src/components/common/relation.js
Normal file
@ -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) || []
|
||||
});
|
||||
}
|
||||
})
|
||||
};
|
||||
}
|
5
employee-mp/src/components/common/style/clearfix.wxss
Normal file
5
employee-mp/src/components/common/style/clearfix.wxss
Normal file
@ -0,0 +1,5 @@
|
||||
.cw-clearfix:after {
|
||||
display: table;
|
||||
clear: both;
|
||||
content: '';
|
||||
}
|
18
employee-mp/src/components/common/style/ellipsis.wxss
Normal file
18
employee-mp/src/components/common/style/ellipsis.wxss
Normal file
@ -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;
|
||||
}
|
55
employee-mp/src/components/common/style/hairline.wxss
Normal file
55
employee-mp/src/components/common/style/hairline.wxss
Normal file
@ -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;
|
||||
}
|
101
employee-mp/src/components/common/utils.js
Normal file
101
employee-mp/src/components/common/utils.js
Normal file
@ -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];
|
||||
}
|
42
employee-mp/src/components/common/validator.js
Normal file
42
employee-mp/src/components/common/validator.js
Normal file
@ -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);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user