init
This commit is contained in:
commit
459a88214b
|
@ -0,0 +1,7 @@
|
|||
APP_DEBUG = true
|
||||
|
||||
[APP]
|
||||
DEFAULT_TIMEZONE = Asia/Shanghai
|
||||
|
||||
[LANG]
|
||||
default_lang = zh-cn
|
|
@ -0,0 +1,8 @@
|
|||
/.idea
|
||||
/.vscode
|
||||
/.gitee
|
||||
*.log
|
||||
*.env
|
||||
*.lock
|
||||
*.ini
|
||||
/runtime/*
|
|
@ -0,0 +1,674 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://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 <http://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) <year> <name of author>
|
||||
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
|
||||
<http://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
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
ThinkPHP遵循Apache2开源协议发布,并提供免费使用。
|
||||
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
|
||||
All rights reserved。
|
||||
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
|
||||
|
||||
Apache Licence是著名的非盈利开源组织Apache采用的协议。
|
||||
该协议和BSD类似,鼓励代码共享和尊重原作者的著作权,
|
||||
允许代码修改,再作为开源或商业软件发布。需要满足
|
||||
的条件:
|
||||
1. 需要给代码的用户一份Apache Licence ;
|
||||
2. 如果你修改了代码,需要在被修改的文件中说明;
|
||||
3. 在延伸的代码中(修改和有源代码衍生的代码中)需要
|
||||
带有原来代码中的协议,商标,专利声明和其他原来作者规
|
||||
定需要包含的说明;
|
||||
4. 如果再发布的产品中包含一个Notice文件,则在Notice文
|
||||
件中需要带有本协议内容。你可以在Notice中增加自己的
|
||||
许可,但不可以表现为对Apache Licence构成更改。
|
||||
具体的协议参考:http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
勾股OA遵循GPL-2.0开源协议发布,并支持免费使用。
|
||||
版权所有Copyright © 2021 by gouguCMS (https://www.gougucms.com)
|
||||
All rights reserved。
|
|
@ -0,0 +1,191 @@
|
|||
## 📐 勾股OA4.0
|
||||
|
||||
![勾股OA](https://oa.gougucms.com/storage/image/slogo.jpg)
|
||||
|
||||
### ✅ 相关链接
|
||||
- 系统地址:https://www.gougucms.com/home/pages/detail/s/gouguoa.html
|
||||
- 文档地址:[https://blog.gougucms.com/home/book/detail/bid/3.html](https://blog.gougucms.com/home/book/detail/bid/3.html)
|
||||
- 项目会不定时进行更新,建议⭐star⭐和👁️watch👁️一份。
|
||||
|
||||
### ⭕ 同系列开源项目
|
||||
1. [开源项目系列:勾股OA —— OA协同办公系统](https://gitee.com/gougucms/office)
|
||||
2. [开源项目系列:勾股DEV —— 项目研发管理系统](https://gitee.com/gougucms/dev)
|
||||
3. [开源项目系列:勾股CMS —— CMS内容管理系统框架](https://gitee.com/gougucms/gougucms)
|
||||
4. [开源项目系列:勾股BLOG —— 个人&工作室博客系统](https://gitee.com/gougucms/blog)
|
||||
5. [开源项目系列:勾股Admin —— 基于Layui的Web UI解决方案](https://gitee.com/gouguopen/guoguadmin)
|
||||
|
||||
|
||||
### 📋 系统介绍
|
||||
**我们的愿景是:助力企业数智化。**
|
||||
|
||||
勾股OA是一款基于ThinkPHP6 + Layui + MySql打造的实用的开源的企业办公系统,开箱即用,使用勾股OA可以简单快速地建立企业级的办公自动化系统。
|
||||
办公自动化系统是员工及管理者使用频率最高的应用系统,可以极大提高公司的办公效率,我们立志为中小企业提供开源好用的办公自动化系统,帮助企业节省数字化、信息化办公的成本。
|
||||
|
||||
### ✳️ 演示地址
|
||||
|
||||
勾股OA演示地址:[https://oa.gougucms.com](https://oa.gougucms.com)
|
||||
|
||||
沟通咨询请加微信号:hdm588
|
||||
|
||||
PS:为了给后面的人提供良好的演示体验,体验以查看为主,如果确实需要填写数据,大家最好填些看似正常的数据,请不要乱填数据,比如:`1111`,`aaa`这些数据就不要乱填入了。
|
||||
|
||||
体验账号及密码:
|
||||
~~~
|
||||
BOSS角色:suhaizhen 123456
|
||||
总 经 理:yiyeshu 123456
|
||||
人事总监:fengcailing 123456
|
||||
财务总监:yucixin 1234566
|
||||
市场总监:qinjiaxian 1234566
|
||||
技术总监:yexiaochai 1234566
|
||||
销售组长:fujianfenshuo 123456
|
||||
销售组长:jianzixianji 123456
|
||||
销售组长:shuloulongsu 123456
|
||||
客服经理:hongchenxue 123456
|
||||
客服人员:guxinglei 123456
|
||||
~~~
|
||||
|
||||
### ✴️ 系统特点
|
||||
- 系统各功能模块,一目了然,操作简单;通用型的后台权限管理框架,员工的操作记录全覆盖跟踪,紧随潮流、极低门槛、开箱即用。
|
||||
- 系统集成了系统设置、人事管理、行政管理、消息管理、企业公告、知识库、审批流程设置、办公审批、日常办公、财务管理、客户管理、合同管理、项目管理、任务管理等基础模块。
|
||||
- 系统方便二次开发,易于功能扩展,代码维护,满足专注业务深度开发的需求。
|
||||
- 开发人员可以快速基于此系统进行二次开发,免去写一次系统架构的痛苦,帮助开发者高效降低开发的成本,通过二次开发之后可以用来做CRM,ERP,项目管理等企业办公系统。
|
||||
|
||||
**功能矩阵**
|
||||
|
||||
系统后台集成了主流的通用功能,如:登录验证、系统配置、操作日志管理、角色权限、职位职称、数据权限、功能菜单、模块管理、关键字管理、文件上传、数据备份/还原、基础数据、审批流程、员工管理、消息通知、企业公告、知识文章、办公审批、日常办公、财务管理、客户管理、合同管理、项目管理、任务管理等。更多的个性化功能可以基于当前系统便捷做二次开发。
|
||||
|
||||
![输入图片说明](https://oa.gougucms.com/storage/image/gouguoa2.0.png)
|
||||
|
||||
|
||||
### 📚 安装教程
|
||||
|
||||
**一、服务器。**
|
||||
|
||||
服务器最低配置:
|
||||
~~~
|
||||
1核CPU (建议2核+)
|
||||
2G内存 (建议4G+)
|
||||
1M带宽 (建议3M+)
|
||||
~~~
|
||||
服务器运行环境要求:
|
||||
~~~
|
||||
PHP >= 7.4
|
||||
Mysql >= 5.6.0 (需支持innodb引擎)
|
||||
Apache 或 Nginx
|
||||
PDO PHP Extension
|
||||
MBstring PHP Extension
|
||||
CURL PHP Extension
|
||||
FileInfo PHP Extension
|
||||
Composer (用于管理第三方扩展包)
|
||||
~~~
|
||||
|
||||
**二、系统安装**
|
||||
|
||||
**命令行安装(推荐)**
|
||||
|
||||
推荐使用命令行安装,因为采用命令行安装的方式可以和勾股OA随时保持更新同步。使用命令行安装请提前准备好`Git`、`Composer`。
|
||||
|
||||
**勾股OA的安装步骤,以下加粗的内容需要特别留意:**
|
||||
|
||||
第一步:克隆(下载)勾股OA到你本地 **(如果不用git的可以在代码仓库上角打包下载代码,然后解压上传到服务器)**
|
||||
|
||||
git clone https://gitee.com/gougucms/office.git
|
||||
|
||||
第二步:进入目录
|
||||
cd gouguoa(文件所在根目录)
|
||||
|
||||
第三步:下载PHP依赖包
|
||||
|
||||
composer install
|
||||
|
||||
第四步:添加虚拟主机并绑定到项目的`public`目录 ,实际部署中,确保绑定域名访问到的是`public`目录。**(这一步很重要,很多人出错)**
|
||||
|
||||
第五步:伪静态配置 **(这一步也很重要,很多人出错)**,使用的是ThinkPHP的伪静态规则,**具体看下面的伪静态配置内容**。
|
||||
|
||||
**Nginx**
|
||||
修改nginx.conf 配置文件 加入下面的语句。
|
||||
~~~
|
||||
location / {
|
||||
if (!-e $request_filename){
|
||||
rewrite ^(.*)$ /index.php?s=$1 last; break;
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
**Apache**
|
||||
把下面的内容保存为.htaccess文件放到应用入 public 文件的同级目录下。
|
||||
~~~
|
||||
<IfModule mod_rewrite.c>
|
||||
Options +FollowSymlinks -Multiviews
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
|
||||
</IfModule>
|
||||
~~~
|
||||
|
||||
第六步:访问 http://www.你的域名.com/install/index 进行安装**(访问主域名,系统会自动跳转到安装连接的)**
|
||||
|
||||
⚠️⚠️ **注意:安装过程中,系统会自动创建数据库,请确保填写的数据库用户的权限可创建数据库,如果权限不足,请先手动创建空的数据库,然后填写刚创建的数据库名称和用户名也可完成安装。**
|
||||
|
||||
🔺🔺 **提醒:安装过程中,如果进度条卡住,一般都是数据库写入权限或者安装环境配置问题,请注意检查。遇到问题请到QQ群反馈:24641076(群一满),46924914(群二名额不多)**
|
||||
|
||||
✅✅ **PS:如需要重新安装,请删除目录里面 config/install.lock 的文件,即可重新安装。**
|
||||
|
||||
|
||||
### ❓ 常见问题
|
||||
|
||||
1. 安装失败,可能存在php配置文件禁止了`putenv`和`proc_open`函数。解决方法,查找`php.ini`文件位置,打开`php.ini`,搜索`disable_functions`项,看是否禁用了`putenv`和`proc_open`函数。如果在禁用列表里,移除`putenv`、`proc_open`然后退出,重启`php`即可。
|
||||
|
||||
2. 如果安装后打开页面提示 `404`错误,请检查服务器伪静态配置,如果是宝塔面板,网站伪静态请配置使用thinkphp规则。
|
||||
|
||||
3. 如果提示当前权限不足,无法写入配置文件`config/database.php`,请检查`config`目录是否可写,还有可能是当前安装程序无法访问父目录,请检查PHP的`open_basedir`配置。
|
||||
|
||||
4. 如果`composer install`失败,请尝试在命令行进行切换配置到国内源,命令如下:
|
||||
|
||||
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/
|
||||
|
||||
5. 访问 http://www.你的域名.com/install/index 前,请注意查看伪静态请配置是否设置了`thinkphp`伪静态规则。
|
||||
|
||||
6. 出现访问报错一般是服务器环境配置问题
|
||||
|
||||
比如:伪静态配置,网站的访问入口是否绑定`public`目录,放配置文件的目录是否有可写权限,放缓存的目录是否有可写权限,数据库连接确认无误等。
|
||||
|
||||
开启`debug`的方式请查看链接:https://blog.gougucms.com/home/book/detail/bid/3/id/77.html
|
||||
|
||||
开启`debug`后,看具体的报错信息,然后沿着这些思路去一个个排查基本解决90%的问题。
|
||||
|
||||
7. 如果是`composer`的安装,`composer install`报错,这不是勾股系列系统的问题,可以百度得到具体解决方案的。
|
||||
|
||||
8. 安装过程中,如果 **进度条卡住(99%)**,一般都是数据库写入权限或者安装环境配置`config`目录无法写入问题,请注意检查权限。
|
||||
|
||||
9. 如果安装成功后,无法显示图形验证码的,请看是否已安装(开启)了PHP的`GD`库。
|
||||
|
||||
10. 如果安装成功后,无法上传文件的,请看是否已安装(开启)了PHP的`fileinfo`扩展。
|
||||
|
||||
11. 遇到解决不了的问题请到QQ群反馈:24641076(群一满),46924914(群二名额不多) 。
|
||||
|
||||
12. **最后,如果实在安装不成功,确实需要提供安装服务的,请搜索微信号:hdm588,或者QQ号:327725426,添加好友,注意备注[安装勾股系统]。开源不易,该服务需友情赞赏💰99元。**
|
||||
|
||||
### 🖼️ 截图预览
|
||||
|
||||
|页面截图 | 部分截图|
|
||||
| :--------: | :--------:|
|
||||
| ![功能导图](https://oa.gougucms.com/storage/image/oa4.png "功能导图")|![功能导图](https://oa.gougucms.com/storage/image/oa1.png "功能导图")|
|
||||
|![功能导图](https://oa.gougucms.com/storage/image/oa2.png "功能导图")|![功能导图](https://oa.gougucms.com/storage/image/oa3.png "功能导图")|
|
||||
|
||||
### ⭐ 开源助力
|
||||
|
||||
- 勾股OA遵循GPL-3.0开源协议发布。
|
||||
- 开源的系统少不了大家的参与,如果大家在体验的过程中发现有问题或者BUG,请到Issue里面反馈,谢谢!
|
||||
- 如果觉得勾股OA不错,不要吝啬您的赞许和鼓励,请给我们⭐ STAR ⭐吧!
|
||||
|
||||
### 👍 支持我们
|
||||
|
||||
- If the project is very helpful to you, you can buy the author a cup of coffee☕.
|
||||
- 如果这个项目对您有帮助,可以请作者喝杯咖啡哟☕
|
||||
|
||||
|支付宝 | 微信|
|
||||
| :--------: | :--------:|
|
||||
| <img src="https://www.gougucms.com/static/home/images/zfb.png" width="300" align=center />|<img src="https://www.gougucms.com/static/home/images/wx.png" width="300" align=center />|
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
/**
|
||||
======================
|
||||
*模块数据获取公共文件
|
||||
======================
|
||||
*/
|
||||
use think\facade\Db;
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\adm\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\adm\validate\CarCateCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Car extends BaseController
|
||||
{
|
||||
//车辆类型
|
||||
public function car_cate()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('CarCate')->order('create_time asc')->select();
|
||||
return to_assign(0, '', $cate);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//车辆类型添加
|
||||
public function car_cate_add()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(CarCateCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('CarCate')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(CarCateCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('CarCate')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//车辆类型设置
|
||||
public function car_cate_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$res = Db::name('CarCate')->strict(false)->field('id,status')->update($param);
|
||||
if ($res) {
|
||||
if($param['status'] == 0){
|
||||
add_log('disable', $param['id'], $param);
|
||||
}
|
||||
else if($param['status'] == 1){
|
||||
add_log('recovery', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(0, '操作失败');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\adm\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\adm\validate\MeetingCateCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Meeting extends BaseController
|
||||
{
|
||||
//会议室
|
||||
public function meeting_cate()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('MeetingCate')->order('create_time asc')->select();
|
||||
return to_assign(0, '', $cate);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//会议室添加
|
||||
public function meeting_cate_add()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(MeetingCateCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('MeetingCate')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(MeetingCateCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('MeetingCate')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//会议室设置
|
||||
public function meeting_cate_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$res = Db::name('MeetingCate')->strict(false)->field('id,status')->update($param);
|
||||
if ($res) {
|
||||
if($param['status'] == 0){
|
||||
add_log('disable', $param['id'], $param);
|
||||
}
|
||||
else if($param['status'] == 1){
|
||||
add_log('recovery', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(0, '操作失败');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\adm\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\adm\validate\SealCateCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Seal extends BaseController
|
||||
{
|
||||
//印章类别
|
||||
public function seal_cate()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('SealCate')->order('create_time asc')->select();
|
||||
return to_assign(0, '', $cate);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//印章类别添加
|
||||
public function seal_cate_add()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(SealCateCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('SealCate')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(SealCateCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('SealCate')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//印章类别设置
|
||||
public function seal_cate_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$res = Db::name('SealCate')->strict(false)->field('id,status')->update($param);
|
||||
if ($res) {
|
||||
if($param['status'] == 0){
|
||||
add_log('disable', $param['id'], $param);
|
||||
}
|
||||
else if($param['status'] == 1){
|
||||
add_log('recovery', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(0, '操作失败');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
// 这是系统自动生成的event定义文件
|
||||
return [
|
||||
|
||||
];
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
//开启session中间件
|
||||
//'think\middleware\SessionInit',
|
||||
//验证勾股OA是否完成安装
|
||||
\app\home\middleware\Install::class,
|
||||
];
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\adm\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class CarCateCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:car_cate',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\adm\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class MeetingCateCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:meeting_cate',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\adm\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class SealCateCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:seal_cate',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm addNew" type="button">+ 添加车辆类型</button>
|
||||
</div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool, form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test'
|
||||
,toolbar: '#toolbarDemo'
|
||||
,defaultToolbar: false
|
||||
,title:'车辆类型列表'
|
||||
,url: "/adm/car/car_cate"
|
||||
,page: false
|
||||
,cellMinWidth: 80
|
||||
,cols: [[
|
||||
{field:'id',width:80, title: 'ID号', align:'center'}
|
||||
,{field:'title',title: '车辆名称'}
|
||||
,{field:'name',title: '车牌号码'}
|
||||
,{field:'status', title: '状态',width:80,align:'center',templet: function(d){
|
||||
var html1='<span class="green">正常</span>';
|
||||
var html2='<span class="yellow">禁用</span>';
|
||||
if(d.status==1){
|
||||
return html1;
|
||||
}
|
||||
else{
|
||||
return html2;
|
||||
}
|
||||
}}
|
||||
,{width:100,title: '操作', align:'center',templet: function(d){
|
||||
var html='';
|
||||
var btn='<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</a>';
|
||||
var btn1='<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="disable">禁用</a>';
|
||||
var btn2='<a class="layui-btn layui-btn-xs" lay-event="open">启用</a>';
|
||||
if(d.status==1){
|
||||
html = '<div class="layui-btn-group">'+btn+btn1+'</div>';
|
||||
}
|
||||
else{
|
||||
html = '<div class="layui-btn-group">'+btn+btn2+'</div>';
|
||||
}
|
||||
return html;
|
||||
}}
|
||||
]]
|
||||
});
|
||||
|
||||
table.on('tool(test)',function (obj) {
|
||||
if(obj.event === 'edit'){
|
||||
addExpense(obj.data.id,obj.data.title,obj.data.name);
|
||||
}
|
||||
if(obj.event === 'disable'){
|
||||
layer.confirm('确定要禁用该车辆吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/car/car_cate_check", { id: obj.data.id,status: 0}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
if(obj.event === 'open'){
|
||||
layer.confirm('确定要启用该车辆吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/car/car_cate_check", { id: obj.data.id,status: 1}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click','.addNew',function(){
|
||||
addExpense(0,'','');
|
||||
});
|
||||
|
||||
function addExpense(id,title,name){
|
||||
var biaoti = '新增车辆';
|
||||
if(id>0){
|
||||
biaoti = '编辑车辆';
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1
|
||||
,title: biaoti
|
||||
,area: '368px;'
|
||||
,id: 'LAY_module' //设定一个id,防止重复弹出
|
||||
,btn: ['确定', '取消']
|
||||
,btnAlign: 'c'
|
||||
,content: '<div style="padding-top:15px;">\
|
||||
<div class="layui-form-item">\
|
||||
<label class="layui-form-label">车辆名称</label>\
|
||||
<div class="layui-input-inline">\
|
||||
<input type="hidden" name="id" value="'+id+'">\
|
||||
<input type="text" name="title" autocomplete="off" value="'+title+'" placeholder="请输入车辆名称" class="layui-input">\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="layui-form-item">\
|
||||
<label class="layui-form-label">车牌号码</label>\
|
||||
<div class="layui-input-inline">\
|
||||
<input type="text" name="name" autocomplete="off" value="'+name+'" placeholder="请输入车牌号码" class="layui-input">\
|
||||
</div>\
|
||||
</div>\
|
||||
</div>'
|
||||
,yes: function(index){
|
||||
let id = $('#LAY_module').find('[name="id"]').val();
|
||||
let title = $('#LAY_module').find('[name="title"]').val();
|
||||
let name = $('#LAY_module').find('[name="name"]').val();
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
layer.close(index);
|
||||
}
|
||||
}
|
||||
tool.post("/adm/car/car_cate_add", {
|
||||
id: id,
|
||||
title: title,
|
||||
name: name
|
||||
}, callback);
|
||||
}
|
||||
,btn2: function(){
|
||||
layer.closeAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,121 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm addNew" type="button">+ 添加会议室</button>
|
||||
</div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool, form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test'
|
||||
,toolbar: '#toolbarDemo'
|
||||
,defaultToolbar: false
|
||||
,title:'会议室列表'
|
||||
,url: "/adm/meeting/meeting_cate"
|
||||
,page: false
|
||||
,cellMinWidth: 80
|
||||
,cols: [[
|
||||
{field:'id',width:80, title: 'ID号', align:'center'}
|
||||
,{field:'title',title: '类别名称'}
|
||||
,{field:'status', title: '状态',width:80,align:'center',templet: function(d){
|
||||
var html1='<span class="green">正常</span>';
|
||||
var html2='<span class="yellow">禁用</span>';
|
||||
if(d.status==1){
|
||||
return html1;
|
||||
}
|
||||
else{
|
||||
return html2;
|
||||
}
|
||||
}}
|
||||
,{width:100,title: '操作', align:'center',templet: function(d){
|
||||
var html='';
|
||||
var btn='<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</a>';
|
||||
var btn1='<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="disable">禁用</a>';
|
||||
var btn2='<a class="layui-btn layui-btn-xs" lay-event="open">启用</a>';
|
||||
if(d.status==1){
|
||||
html = '<div class="layui-btn-group">'+btn+btn1+'</div>';
|
||||
}
|
||||
else{
|
||||
html = '<div class="layui-btn-group">'+btn+btn2+'</div>';
|
||||
}
|
||||
return html;
|
||||
}}
|
||||
]]
|
||||
});
|
||||
|
||||
table.on('tool(test)',function (obj) {
|
||||
if(obj.event === 'edit'){
|
||||
addExpense(obj.data.id,obj.data.title);
|
||||
}
|
||||
if(obj.event === 'disable'){
|
||||
layer.confirm('确定要禁用该会议室吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/meeting/meeting_cate_check", { id: obj.data.id,status: 0,title: obj.data.title}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
if(obj.event === 'open'){
|
||||
layer.confirm('确定要启用该会议室吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/meeting/meeting_cate_check", { id: obj.data.id,status: 1,title: obj.data.title}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click','.addNew',function(){
|
||||
addExpense(0,'');
|
||||
});
|
||||
|
||||
function addExpense(id,val){
|
||||
var title = '新增会议室';
|
||||
if(id>0){
|
||||
title = '编辑会议室';
|
||||
}
|
||||
layer.prompt({
|
||||
title: title,
|
||||
value: val,
|
||||
yes: function(index, layero) {
|
||||
// 获取文本框输入的值
|
||||
var value = layero.find(".layui-layer-input").val();
|
||||
if (value) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/meeting/meeting_cate_add", {id: id,title: value}, callback);
|
||||
layer.close(index);
|
||||
} else {
|
||||
layer.msg('请填写会议室名称');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,121 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm addNew" type="button">+ 添加印章类型</button>
|
||||
</div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool, form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test'
|
||||
,toolbar: '#toolbarDemo'
|
||||
,defaultToolbar: false
|
||||
,title:'印章类型列表'
|
||||
,url: "/adm/seal/seal_cate"
|
||||
,page: false
|
||||
,cellMinWidth: 80
|
||||
,cols: [[
|
||||
{field:'id',width:80, title: 'ID号', align:'center'}
|
||||
,{field:'title',title: '类别名称'}
|
||||
,{field:'status', title: '状态',width:80,align:'center',templet: function(d){
|
||||
var html1='<span class="green">正常</span>';
|
||||
var html2='<span class="yellow">禁用</span>';
|
||||
if(d.status==1){
|
||||
return html1;
|
||||
}
|
||||
else{
|
||||
return html2;
|
||||
}
|
||||
}}
|
||||
,{width:100,title: '操作', align:'center',templet: function(d){
|
||||
var html='';
|
||||
var btn='<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="edit">编辑</a>';
|
||||
var btn1='<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="disable">禁用</a>';
|
||||
var btn2='<a class="layui-btn layui-btn-xs" lay-event="open">启用</a>';
|
||||
if(d.status==1){
|
||||
html = '<div class="layui-btn-group">'+btn+btn1+'</div>';
|
||||
}
|
||||
else{
|
||||
html = '<div class="layui-btn-group">'+btn+btn2+'</div>';
|
||||
}
|
||||
return html;
|
||||
}}
|
||||
]]
|
||||
});
|
||||
|
||||
table.on('tool(test)',function (obj) {
|
||||
if(obj.event === 'edit'){
|
||||
addExpense(obj.data.id,obj.data.title);
|
||||
}
|
||||
if(obj.event === 'disable'){
|
||||
layer.confirm('确定要禁用该类别吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/seal/seal_cate_check", { id: obj.data.id,status: 0,title: obj.data.title}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
if(obj.event === 'open'){
|
||||
layer.confirm('确定要启用该类别吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/seal/seal_cate_check", { id: obj.data.id,status: 1,title: obj.data.title}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click','.addNew',function(){
|
||||
addExpense(0,'');
|
||||
});
|
||||
|
||||
function addExpense(id,val){
|
||||
var title = '新增类别';
|
||||
if(id>0){
|
||||
title = '编辑类别';
|
||||
}
|
||||
layer.prompt({
|
||||
title: title,
|
||||
value: val,
|
||||
yes: function(index, layero) {
|
||||
// 获取文本框输入的值
|
||||
var value = layero.find(".layui-layer-input").val();
|
||||
if (value) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/adm/seal/seal_cate_add", {id: id,title: value}, callback);
|
||||
layer.close(index);
|
||||
} else {
|
||||
layer.msg('请填写类别标题');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,161 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\api;
|
||||
|
||||
use think\App;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\facade\Request;
|
||||
use think\facade\Session;
|
||||
use think\facade\View;
|
||||
use think\facade\Db;
|
||||
use think\Response;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class BaseController
|
||||
{
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* 是否批量验证
|
||||
* @var bool
|
||||
*/
|
||||
protected $batchValidate = false;
|
||||
|
||||
/**
|
||||
* 控制器中间件
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [];
|
||||
|
||||
/**
|
||||
* 分页数量
|
||||
* @var string
|
||||
*/
|
||||
protected $pageSize = '';
|
||||
|
||||
/**
|
||||
* jwt配置
|
||||
* @var string
|
||||
*/
|
||||
protected $jwt_conf = [
|
||||
'secrect' => 'gouguoa',
|
||||
'iss' => 'www.gougucms.com', //签发者 可选
|
||||
'aud' => 'gouguoa', //接收该JWT的一方,可选
|
||||
'exptime' => 7200, //过期时间,这里设置2个小时
|
||||
];
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
$this->module = strtolower(app('http')->getName());
|
||||
$this->controller = strtolower($this->request->controller());
|
||||
$this->action = strtolower($this->request->action());
|
||||
$this->uid = 0;
|
||||
$this->did = 0;
|
||||
$this->jwt_conf = get_system_config('token');
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{
|
||||
// 检测权限
|
||||
$this->checkLogin();
|
||||
//每页显示数据量
|
||||
$this->pageSize = Request::param('page_size', \think\facade\Config::get('app.page_size'));
|
||||
}
|
||||
|
||||
/**
|
||||
*验证用户登录
|
||||
*/
|
||||
protected function checkLogin()
|
||||
{
|
||||
$session_admin = get_config('app.session_admin');
|
||||
if (!Session::has($session_admin)) {
|
||||
$this->apiError('请先登录');
|
||||
}
|
||||
else{
|
||||
$this->uid = Session::get($session_admin);
|
||||
$login_admin = Db::name('Admin')->where(['id' => $this->uid])->find();
|
||||
$this->did = $login_admin['did'];
|
||||
View::assign('login_admin', $login_admin);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Api处理成功结果返回方法
|
||||
* @param $message
|
||||
* @param null $redirect
|
||||
* @param null $extra
|
||||
* @return mixed
|
||||
* @throws ReturnException
|
||||
*/
|
||||
protected function apiSuccess($msg = 'success', $data = [])
|
||||
{
|
||||
return $this->apiReturn($data, 0, $msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Api处理结果失败返回方法
|
||||
* @param $error_code
|
||||
* @param $message
|
||||
* @param null $redirect
|
||||
* @param null $extra
|
||||
* @return mixed
|
||||
* @throws ReturnException
|
||||
*/
|
||||
protected function apiError($msg = 'fail', $data = [], $code = 1)
|
||||
{
|
||||
return $this->apiReturn($data, $code, $msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回封装后的API数据到客户端
|
||||
* @param mixed $data 要返回的数据
|
||||
* @param integer $code 返回的code
|
||||
* @param mixed $msg 提示信息
|
||||
* @param string $type 返回数据格式
|
||||
* @param array $header 发送的Header信息
|
||||
* @return Response
|
||||
*/
|
||||
protected function apiReturn($data, int $code = 0, $msg = '', string $type = '', array $header = []): Response
|
||||
{
|
||||
$result = [
|
||||
'code' => $code,
|
||||
'msg' => $msg,
|
||||
'time' => time(),
|
||||
'data' => $data,
|
||||
];
|
||||
|
||||
$type = $type ?: 'json';
|
||||
$response = Response::create($result, $type)->header($header);
|
||||
|
||||
throw new HttpResponseException($response);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
//读取文章分类列表
|
||||
function get_article_cate()
|
||||
{
|
||||
$cate = \think\facade\Db::name('ArticleCate')->order('create_time asc')->select()->toArray();
|
||||
return $cate;
|
||||
}
|
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/Apache-2.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use app\api\middleware\Auth;
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use think\facade\Db;
|
||||
use think\facade\Request;
|
||||
|
||||
class Demo extends BaseController
|
||||
{
|
||||
/**
|
||||
* 控制器中间件 [登录、注册 不需要鉴权]
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
Auth::class => ['except' => ['index','login'] ]
|
||||
];
|
||||
|
||||
/**
|
||||
* @param $user_id
|
||||
* @return string
|
||||
*/
|
||||
public function getToken($user_id){
|
||||
$time = time(); //当前时间
|
||||
$conf = $this->jwt_conf;
|
||||
$token = [
|
||||
'iss' => $conf['iss'], //签发者 可选
|
||||
'aud' => $conf['aud'], //接收该JWT的一方,可选
|
||||
'iat' => $time, //签发时间
|
||||
'nbf' => $time-1 , //(Not Before):某个时间点后才能访问,比如设置time+30,表示当前时间30秒后才能使用
|
||||
'exp' => $time+$conf['exptime'], //过期时间,这里设置2个小时
|
||||
'data' => [
|
||||
//自定义信息,不要定义敏感信息
|
||||
'userid' =>$user_id,
|
||||
]
|
||||
];
|
||||
return JWT::encode($token, $conf['secrect'], 'HS256'); //输出Token 默认'HS256'
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $token
|
||||
*/
|
||||
public static function checkToken($token){
|
||||
try {
|
||||
JWT::$leeway = 60;//当前时间减去60,把时间留点余地
|
||||
$decoded = JWT::decode($token, self::$config['secrect'], ['HS256']); //HS256方式,这里要和签发的时候对应
|
||||
return (array)$decoded;
|
||||
} catch(\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
|
||||
return json(['code'=>403,'msg'=>'签名错误']);
|
||||
}catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
|
||||
return json(['code'=>401,'msg'=>'token失效']);
|
||||
}catch(\Firebase\JWT\ExpiredException $e) { // token过期
|
||||
return json(['code'=>401,'msg'=>'token已过期']);
|
||||
}catch(Exception $e) { //其他错误
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
}catch(\UnexpectedValueException $e) { //其他错误
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
} catch(\DomainException $e) { //其他错误
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {post} /demo/login 会员登录
|
||||
* @apiDescription 系统登录接口,返回 token 用于操作需验证身份的接口
|
||||
|
||||
* @apiParam (请求参数:) {string} username 登录用户名
|
||||
* @apiParam (请求参数:) {string} password 登录密码
|
||||
|
||||
* @apiParam (响应字段:) {string} token Token
|
||||
|
||||
* @apiSuccessExample {json} 成功示例
|
||||
* {"code":0,"msg":"登录成功","time":1627374739,"data":{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJhcGkuZ291Z3VjbXMuY29tIiwiYXVkIjoiZ291Z3VjbXMiLCJpYXQiOjE2MjczNzQ3MzksImV4cCI6MTYyNzM3ODMzOSwidWlkIjoxfQ.gjYMtCIwKKY7AalFTlwB2ZVWULxiQpsGvrz5I5t2qTs"}}
|
||||
* @apiErrorExample {json} 失败示例
|
||||
* {"code":1,"msg":"帐号或密码错误","time":1627374820,"data":[]}
|
||||
*/
|
||||
|
||||
public function login()
|
||||
{
|
||||
$param = get_params();
|
||||
if (empty($param['username']) || empty($param['password'])) {
|
||||
$this->apiError('参数错误');
|
||||
}
|
||||
// 校验用户名密码
|
||||
$user = Db::name('Admin')->where(['username' => $param['username']])->find();
|
||||
if (empty($user)) {
|
||||
$this->apiError('帐号或密码错误');
|
||||
}
|
||||
$param['pwd'] = set_password($param['password'], $user['salt']);
|
||||
if ($param['pwd'] !== $user['pwd']) {
|
||||
$this->apiError('帐号或密码错误');
|
||||
}
|
||||
if ($user['status'] == -1) {
|
||||
$this->apiError('该用户禁止登录,请于平台联系');
|
||||
}
|
||||
$data = [
|
||||
'last_login_time' => time(),
|
||||
'last_login_ip' => request()->ip(),
|
||||
'login_num' => $user['login_num'] + 1,
|
||||
];
|
||||
$res = Db::name('Admin')->where(['id' => $user['id']])->update($data);
|
||||
if ($res) {
|
||||
$token = self::getToken($user['id']);
|
||||
$this->apiSuccess('登录成功', ['token' => $token]);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @api {post} /index/demo 测试页面
|
||||
* @apiDescription 返回文章列表信息
|
||||
|
||||
* @apiParam (请求参数:) {string} token Token
|
||||
|
||||
* @apiSuccessExample {json} 响应数据样例
|
||||
* {"code":1,"msg":"","time":1563517637,"data":{"id":13,"email":"test110@qq.com","password":"e10adc3949ba59abbe56e057f20f883e","sex":1,"last_login_time":1563517503,"last_login_ip":"127.0.0.1","qq":"123455","mobile":"","mobile_validated":0,"email_validated":0,"type_id":1,"status":1,"create_ip":"127.0.0.1","update_time":1563507130,"create_time":1563503991,"type_name":"注册会员"}}
|
||||
*/
|
||||
public function test(Request $request)
|
||||
{
|
||||
$uid = JWT_UID;
|
||||
$userInfo = Db::name('Admin')->where(['id' => $uid])->find();
|
||||
$this->apiSuccess('请求成功', ['user' => $userInfo]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,367 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use think\facade\Db;
|
||||
use app\user\model\Admin;
|
||||
use app\customer\model\Customer;
|
||||
use avatars\MDAvatars;
|
||||
use Overtrue\Pinyin\Pinyin;
|
||||
use PhpOffice\PhpSpreadsheet\IOFactory;
|
||||
use PhpOffice\PhpSpreadsheet\Shared\Date as Shared;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
|
||||
|
||||
|
||||
class Import extends BaseController
|
||||
{
|
||||
//生成头像
|
||||
public function to_avatars($char)
|
||||
{
|
||||
$defaultData = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'S', 'Y', 'Z',
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖', '拾',
|
||||
'一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
|
||||
if (isset($char)) {
|
||||
$Char = $char;
|
||||
} else {
|
||||
$Char = $defaultData[mt_rand(0, count($defaultData) - 1)];
|
||||
}
|
||||
$OutputSize = min(512, empty($_GET['size']) ? 36 : intval($_GET['size']));
|
||||
|
||||
$Avatar = new MDAvatars($Char, 256, 1);
|
||||
$avatar_name = '/avatars/avatar_256_' . set_salt(10) . time() . '.png';
|
||||
$path = get_config('filesystem.disks.public.url') . $avatar_name;
|
||||
$res = $Avatar->Save('.' . $path, 256);
|
||||
$Avatar->Free();
|
||||
return $path;
|
||||
}
|
||||
|
||||
//登录名校验
|
||||
public function check_name($name,$arr)
|
||||
{
|
||||
if(in_array($name,$arr)){
|
||||
$name = $this->check_name($name.'1',$arr);
|
||||
}
|
||||
return $name;
|
||||
}
|
||||
|
||||
//导入员工
|
||||
public function import_admin(){
|
||||
// 获取表单上传文件
|
||||
$file[]= request()->file('file');
|
||||
if($this->uid>1){
|
||||
return to_assign(1,'该操作只能是超级管理员有权限操作');
|
||||
}
|
||||
try {
|
||||
// 验证文件大小,名称等是否正确
|
||||
validate(['file' => 'filesize:51200|fileExt:xls,xlsx'])->check($file);
|
||||
// 日期前綴
|
||||
$dataPath = date('Ym');
|
||||
$md5 = $file[0]->hash('md5');
|
||||
$savename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file[0], function () use ($md5) {
|
||||
return $md5;
|
||||
});
|
||||
$fileExtendName = substr(strrchr($savename, '.'), 1);
|
||||
// 有Xls和Xlsx格式两种
|
||||
if ($fileExtendName == 'xlsx') {
|
||||
$objReader = IOFactory::createReader('Xlsx');
|
||||
} else {
|
||||
$objReader = IOFactory::createReader('Xls');
|
||||
}
|
||||
$objReader->setReadDataOnly(TRUE);
|
||||
$path = get_config('filesystem.disks.public.url');
|
||||
// 读取文件,tp6默认上传的文件,在runtime的相应目录下,可根据实际情况自己更改
|
||||
$objPHPExcel = $objReader->load('.'.$path . '/' .$savename);
|
||||
$sheet = $objPHPExcel->getSheet(0); //excel中的第一张sheet
|
||||
$highestRow = $sheet->getHighestRow(); // 取得总行数
|
||||
$highestColumn = $sheet->getHighestColumn(); // 取得总列数
|
||||
Coordinate::columnIndexFromString($highestColumn);
|
||||
$lines = $highestRow - 1;
|
||||
if ($lines <= 0) {
|
||||
return to_assign(1, '数据不能为空');
|
||||
exit();
|
||||
}
|
||||
$sex_array=['未知','男','女'];
|
||||
$type_array=['未知','正式','试用','实习'];
|
||||
$mobile_array = Db::name('Admin')->where([['status','>=',0]])->column('mobile');
|
||||
$email_array = Db::name('Admin')->where([['status','>=',0]])->column('email');
|
||||
$username_array = Db::name('Admin')->where([['status','>=',0]])->column('username');
|
||||
$department_array = Db::name('Department')->where(['status' => 1])->column('title', 'id');
|
||||
$position_array = Db::name('Position')->where(['status' => 1])->column('title', 'id');
|
||||
//循环读取excel表格,整合成数组。如果是不指定key的二维,就用$data[i][j]表示。
|
||||
$pinyin = new Pinyin();
|
||||
for ($j = 3; $j <= $highestRow; $j++) {
|
||||
$salt = set_salt(20);
|
||||
$reg_pwd = '123456';
|
||||
$name = $objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue();
|
||||
if(empty($name)){
|
||||
continue;
|
||||
}
|
||||
$char = mb_substr($name, 0, 1, 'utf-8');
|
||||
$sex = arraySearch($sex_array,$objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue());
|
||||
$department = arraySearch($department_array,$objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue());
|
||||
$position = arraySearch($position_array,$objPHPExcel->getActiveSheet()->getCell("f" . $j)->getValue());
|
||||
$type = arraySearch($type_array,$objPHPExcel->getActiveSheet()->getCell("G" . $j)->getValue());
|
||||
$pinyinname = $pinyin->name($name,PINYIN_UMLAUT_V);
|
||||
$username = implode('', $pinyinname);
|
||||
$mobile = $objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue();
|
||||
$email = $objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue();
|
||||
$file_check['mobile'] = $mobile;
|
||||
$file_check['email'] = $email;
|
||||
$validate_mobile = \think\facade\Validate::rule([
|
||||
'mobile' => 'require|mobile',
|
||||
]);
|
||||
$validate_email = \think\facade\Validate::rule([
|
||||
'email' => 'email',
|
||||
]);
|
||||
if (!$validate_mobile->check($file_check)) {
|
||||
return to_assign(1, '第'.($j - 2).'行的手机号码的格式错误');
|
||||
}
|
||||
else{
|
||||
if(in_array($mobile,$mobile_array)){
|
||||
return to_assign(1, '第'.($j - 2).'行的手机号码已存在或者重复');
|
||||
}
|
||||
else{
|
||||
array_push($mobile_array,$mobile);
|
||||
}
|
||||
}
|
||||
if(!empty($email)){
|
||||
if (!$validate_email->check($file_check)) {
|
||||
return to_assign(1, '第'.($j - 2).'行的电子邮箱的格式错误');
|
||||
}
|
||||
else{
|
||||
if(in_array($email,$email_array)){
|
||||
return to_assign(1, '第'.($j - 2).'行的电子邮箱已存在或者重复');
|
||||
}
|
||||
else{
|
||||
array_push($email_array,$email);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
$email='';
|
||||
}
|
||||
if(empty($department)){
|
||||
return to_assign(1, '第'.($j - 2).'行的所在部门错误');
|
||||
}
|
||||
if(empty($position)){
|
||||
return to_assign(1, '第'.($j - 2).'行的所属职位错误');
|
||||
}
|
||||
$data[$j - 3] = [
|
||||
'name' => $name,
|
||||
'nickname' => $name,
|
||||
'mobile' => $mobile,
|
||||
'email' => $email,
|
||||
'sex' => $sex,
|
||||
'did' => $department,
|
||||
'position_id' => $position,
|
||||
'type' => $type,
|
||||
'entry_time' => Shared::excelToTimestamp($objPHPExcel->getActiveSheet()->getCell("H" . $j)->getValue(),'Asia/Shanghai'),
|
||||
'username' => $this->check_name($username,$username_array),
|
||||
'salt' => $salt,
|
||||
'pwd' => set_password($reg_pwd, $salt),
|
||||
'reg_pwd' => $reg_pwd,
|
||||
'thumb' => $this->to_avatars($char)
|
||||
];
|
||||
}
|
||||
//dd($data);exit;
|
||||
// 批量添加数据
|
||||
if ((new Admin())->saveAll($data)) {
|
||||
return to_assign(0, '导入成功');
|
||||
}
|
||||
else{
|
||||
return to_assign(1, '导入失败,请检查excel文件再试');
|
||||
}
|
||||
} catch (\think\exception\ValidateException $e) {
|
||||
return to_assign(1, $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
//导入客户
|
||||
public function import_customer(){
|
||||
// 获取表单上传文件
|
||||
$file[]= request()->file('file');
|
||||
|
||||
$param = get_params();
|
||||
$type = 'sea';
|
||||
if(isset($param['type'])){
|
||||
$type = $param['type'];
|
||||
}
|
||||
try {
|
||||
// 验证文件大小,名称等是否正确
|
||||
validate(['file' => 'filesize:51200|fileExt:xls,xlsx'])->check($file);
|
||||
// 日期前綴
|
||||
$dataPath = date('Ym');
|
||||
$md5 = $file[0]->hash('md5');
|
||||
$savename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file[0], function () use ($md5) {
|
||||
return $md5;
|
||||
});
|
||||
$fileExtendName = substr(strrchr($savename, '.'), 1);
|
||||
// 有Xls和Xlsx格式两种
|
||||
if ($fileExtendName == 'xlsx') {
|
||||
$objReader = IOFactory::createReader('Xlsx');
|
||||
} else {
|
||||
$objReader = IOFactory::createReader('Xls');
|
||||
}
|
||||
$objReader->setReadDataOnly(TRUE);
|
||||
$path = get_config('filesystem.disks.public.url');
|
||||
// 读取文件,tp6默认上传的文件,在runtime的相应目录下,可根据实际情况自己更改
|
||||
$objPHPExcel = $objReader->load('.'.$path . '/' .$savename);
|
||||
//$objPHPExcel = $objReader->load('./storage/202209/d11544d20b3ca1c1a5f8ce799c3b2433.xlsx');
|
||||
$sheet = $objPHPExcel->getSheet(0); //excel中的第一张sheet
|
||||
$highestRow = $sheet->getHighestRow(); // 取得总行数
|
||||
$highestColumn = $sheet->getHighestColumn(); // 取得总列数
|
||||
Coordinate::columnIndexFromString($highestColumn);
|
||||
$lines = $highestRow - 1;
|
||||
if ($lines <= 0) {
|
||||
return to_assign(1, '数据不能为空');
|
||||
exit();
|
||||
}
|
||||
$name_array = [];
|
||||
$source_array = Db::name('CustomerSource')->where(['status' => 1])->column('title', 'id');
|
||||
$grade_array = Db::name('CustomerGrade')->where(['status' => 1])->column('title', 'id');
|
||||
$industry_array = Db::name('Industry')->where(['status' => 1])->column('title', 'id');
|
||||
|
||||
//循环读取excel表格,整合成数组。如果是不指定key的二维,就用$data[i][j]表示。
|
||||
for ($j = 3; $j <= $highestRow; $j++) {
|
||||
$file_check = [];
|
||||
$name = $objPHPExcel->getActiveSheet()->getCell("A" . $j)->getValue();
|
||||
if(empty($name)){
|
||||
continue;
|
||||
}
|
||||
$count_name = Db::name('Customer')->where('name',$name)->count();
|
||||
if($count_name>0){
|
||||
return to_assign(1, '第'.($j - 2).'行的客户名称已经存在');
|
||||
}
|
||||
if(in_array($name,$name_array)){
|
||||
return to_assign(1, '上传的文件存在相同的客户名称,请删除再操作');
|
||||
}
|
||||
array_push($name_array,$name);
|
||||
$source_id = arraySearch($source_array,$objPHPExcel->getActiveSheet()->getCell("B" . $j)->getValue());
|
||||
$grade_id = arraySearch($grade_array,$objPHPExcel->getActiveSheet()->getCell("C" . $j)->getValue());
|
||||
$industry_id = arraySearch($industry_array,$objPHPExcel->getActiveSheet()->getCell("D" . $j)->getValue());
|
||||
|
||||
$c_name = $objPHPExcel->getActiveSheet()->getCell("E" . $j)->getValue();
|
||||
$c_mobile = $objPHPExcel->getActiveSheet()->getCell("F" . $j)->getValue();
|
||||
$file_check['c_mobile'] = $c_mobile;
|
||||
$tax_num = $objPHPExcel->getActiveSheet()->getCell("G" . $j)->getValue();
|
||||
$bank = $objPHPExcel->getActiveSheet()->getCell("H" . $j)->getValue();
|
||||
$bank_sn = $objPHPExcel->getActiveSheet()->getCell("I" . $j)->getValue();
|
||||
$file_check['bank_sn'] = $bank_sn;
|
||||
$bank_no = $objPHPExcel->getActiveSheet()->getCell("K" . $j)->getValue();
|
||||
$cperson_mobile = $objPHPExcel->getActiveSheet()->getCell("K" . $j)->getValue();
|
||||
$address = $objPHPExcel->getActiveSheet()->getCell("L" . $j)->getValue();
|
||||
$content = $objPHPExcel->getActiveSheet()->getCell("M" . $j)->getValue();
|
||||
$market = $objPHPExcel->getActiveSheet()->getCell("N" . $j)->getValue();
|
||||
if(empty($c_name)){
|
||||
return to_assign(1, '第'.($j - 2).'行的客户联系人姓名没完善');
|
||||
}
|
||||
if(empty($c_mobile)){
|
||||
return to_assign(1, '第'.($j - 2).'行的客户联系人手机号码没完善');
|
||||
}
|
||||
$validate_mobile = \think\facade\Validate::rule([
|
||||
'c_mobile' => 'mobile',
|
||||
]);
|
||||
if (!$validate_mobile->check($file_check)) {
|
||||
return to_assign(1, '第'.($j - 2).'行的客户联系人手机号码格式错误');
|
||||
}
|
||||
if(empty($source_id)){
|
||||
return to_assign(1, '第'.($j - 2).'行的客户来源错误');
|
||||
}
|
||||
if(empty($grade_id)){
|
||||
return to_assign(1, '第'.($j - 2).'行的客户等级错误');
|
||||
}
|
||||
if(empty($industry_id)){
|
||||
return to_assign(1, '第'.($j - 2).'行的所属行业错误');
|
||||
}
|
||||
if(empty($tax_num)){
|
||||
$tax_num='';
|
||||
}
|
||||
if(empty($bank)){
|
||||
$bank='';
|
||||
}
|
||||
$validate_bank = \think\facade\Validate::rule([
|
||||
'bank_sn' => 'number',
|
||||
]);
|
||||
if(!empty($bank_sn)){
|
||||
if (!$validate_bank->check($file_check)) {
|
||||
return to_assign(1, '第'.($j - 2).'行的银行卡账号格式错误');
|
||||
}
|
||||
}
|
||||
else{
|
||||
$bank_sn='';
|
||||
}
|
||||
if(empty($bank_no)){
|
||||
$bank_no='';
|
||||
}
|
||||
if(empty($cperson_mobile)){
|
||||
$cperson_mobile='';
|
||||
}
|
||||
if(empty($address)){
|
||||
$address='';
|
||||
}
|
||||
if(empty($content)){
|
||||
$content='';
|
||||
}
|
||||
if(empty($market)){
|
||||
$market='';
|
||||
}
|
||||
$belong_uid = 0;
|
||||
$belong_did = 0;
|
||||
if($type != 'sea'){
|
||||
$belong_uid = $this->uid;
|
||||
$belong_did = $this->did;
|
||||
}
|
||||
$data[$j - 3] = [
|
||||
'name' => $name,
|
||||
'source_id' => $source_id,
|
||||
'grade_id' => $grade_id,
|
||||
'industry_id' => $industry_id,
|
||||
'tax_num' => $tax_num,
|
||||
'bank' => $bank,
|
||||
'bank_sn' => $bank_sn,
|
||||
'bank_no' => $bank_no,
|
||||
'cperson_mobile' => $cperson_mobile,
|
||||
'address' => $address,
|
||||
'content' => $content,
|
||||
'market' => $market,
|
||||
'admin_id' => $this->uid,
|
||||
'belong_uid' => $belong_uid,
|
||||
'belong_did' => $belong_did,
|
||||
'c_mobile' => $c_mobile,
|
||||
'c_name' => $c_name,
|
||||
'create_time' => time()
|
||||
];
|
||||
}
|
||||
//dd($data);exit;
|
||||
// 批量添加数据
|
||||
$count=0;
|
||||
foreach ($data as $a => $aa) {
|
||||
$cid = Customer::strict(false)->field(true)->insertGetId($aa);
|
||||
if($cid>0){
|
||||
$contact = [
|
||||
'name' => $aa['c_name'],
|
||||
'mobile' => $aa['c_mobile'],
|
||||
'sex' => 1,
|
||||
'cid' => $cid,
|
||||
'is_default' => 1,
|
||||
'create_time' => time(),
|
||||
'admin_id' => $this->uid
|
||||
];
|
||||
Db::name('CustomerContact')->strict(false)->field(true)->insert($contact);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return to_assign(0, '共成功导入了'.$count.'条客户数据');
|
||||
} catch (\think\exception\ValidateException $e) {
|
||||
return to_assign(1, $e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,684 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use think\facade\Db;
|
||||
|
||||
class Index extends BaseController
|
||||
{
|
||||
//上传文件
|
||||
public function upload()
|
||||
{
|
||||
$param = get_params();
|
||||
//var_dump($param);exit;
|
||||
$sourse = 'file';
|
||||
if(isset($param['sourse'])){
|
||||
$sourse = $param['sourse'];
|
||||
}
|
||||
if($sourse == 'file' || $sourse == 'tinymce'){
|
||||
if(request()->file('file')){
|
||||
$file = request()->file('file');
|
||||
}
|
||||
else{
|
||||
return to_assign(1, '没有选择上传文件');
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (request()->file('editormd-image-file')) {
|
||||
$file = request()->file('editormd-image-file');
|
||||
} else {
|
||||
return to_assign(1, '没有选择上传文件');
|
||||
}
|
||||
}
|
||||
// 获取上传文件的hash散列值
|
||||
$sha1 = $file->hash('sha1');
|
||||
$md5 = $file->hash('md5');
|
||||
$rule = [
|
||||
'image' => 'jpg,png,jpeg,gif',
|
||||
'doc' => 'txt,doc,docx,ppt,pptx,xls,xlsx,pdf',
|
||||
'file' => 'zip,gz,7z,rar,tar',
|
||||
'video' => 'mpg,mp4,mpeg,avi,wmv,mov,flv,m4v',
|
||||
];
|
||||
$fileExt = $rule['image'] . ',' . $rule['doc'] . ',' . $rule['file'] . ',' . $rule['video'];
|
||||
//1M=1024*1024=1048576字节
|
||||
$fileSize = 100 * 1024 * 1024;
|
||||
if (isset($param['type']) && $param['type']) {
|
||||
$fileExt = $rule[$param['type']];
|
||||
}
|
||||
if (isset($param['size']) && $param['size']) {
|
||||
$fileSize = $param['size'];
|
||||
}
|
||||
$validate = \think\facade\Validate::rule([
|
||||
'image' => 'require|fileSize:' . $fileSize . '|fileExt:' . $fileExt,
|
||||
]);
|
||||
$file_check['image'] = $file;
|
||||
if (!$validate->check($file_check)) {
|
||||
return to_assign(1, $validate->getError());
|
||||
}
|
||||
// 日期前綴
|
||||
$dataPath = date('Ym');
|
||||
$use = 'thumb';
|
||||
$filename = \think\facade\Filesystem::disk('public')->putFile($dataPath, $file, function () use ($md5) {
|
||||
return $md5;
|
||||
});
|
||||
if ($filename) {
|
||||
//写入到附件表
|
||||
$data = [];
|
||||
$path = get_config('filesystem.disks.public.url');
|
||||
$data['filepath'] = $path . '/' . $filename;
|
||||
$data['name'] = $file->getOriginalName();
|
||||
$data['mimetype'] = $file->getOriginalMime();
|
||||
$data['fileext'] = $file->extension();
|
||||
$data['filesize'] = $file->getSize();
|
||||
$data['filename'] = $filename;
|
||||
$data['sha1'] = $sha1;
|
||||
$data['md5'] = $md5;
|
||||
$data['module'] = \think\facade\App::initialize()->http->getName();
|
||||
$data['action'] = app('request')->action();
|
||||
$data['uploadip'] = app('request')->ip();
|
||||
$data['create_time'] = time();
|
||||
$data['user_id'] = $this->uid;
|
||||
if ($data['module'] = 'admin') {
|
||||
//通过后台上传的文件直接审核通过
|
||||
$data['status'] = 1;
|
||||
$data['admin_id'] = $data['user_id'];
|
||||
$data['audit_time'] = time();
|
||||
}
|
||||
$data['use'] = request()->has('use') ? request()->param('use') : $use; //附件用处
|
||||
$res['id'] = Db::name('file')->insertGetId($data);
|
||||
$res['filepath'] = $data['filepath'];
|
||||
$res['name'] = $data['name'];
|
||||
$res['filename'] = $data['filename'];
|
||||
$res['filesize'] = $data['filesize'];
|
||||
$res['fileext'] = $data['fileext'];
|
||||
add_log('upload', $data['user_id'], $data,'文件');
|
||||
if($sourse == 'editormd'){
|
||||
//editormd编辑器上传返回
|
||||
return json(['success'=>1,'message'=>'上传成功','url'=>$data['filepath']]);
|
||||
}
|
||||
else if($sourse == 'tinymce'){
|
||||
//tinymce编辑器上传返回
|
||||
return json(['success'=>1,'message'=>'上传成功','location'=>$data['filepath']]);
|
||||
}
|
||||
else{
|
||||
//普通上传返回
|
||||
return to_assign(0, '上传成功', $res);
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, '上传失败,请重试');
|
||||
}
|
||||
}
|
||||
|
||||
//清空缓存
|
||||
public function cache_clear()
|
||||
{
|
||||
\think\facade\Cache::clear();
|
||||
return to_assign(0, '系统缓存已清空');
|
||||
}
|
||||
|
||||
// 测试邮件发送
|
||||
public function email_test()
|
||||
{
|
||||
$sender = get_params('email');
|
||||
//检查是否邮箱格式
|
||||
if (!is_email($sender)) {
|
||||
return to_assign(1, '测试邮箱码格式有误');
|
||||
}
|
||||
$email_config = \think\facade\Db::name('config')->where('name', 'email')->find();
|
||||
$config = unserialize($email_config['content']);
|
||||
$content = $config['template'];
|
||||
//所有项目必须填写
|
||||
if (empty($config['smtp']) || empty($config['smtp_port']) || empty($config['smtp_user']) || empty($config['smtp_pwd'])) {
|
||||
return to_assign(1, '请完善邮件配置信息');
|
||||
}
|
||||
|
||||
$send = send_email($sender, '测试邮件', $content);
|
||||
if ($send) {
|
||||
return to_assign(0, '邮件发送成功');
|
||||
} else {
|
||||
return to_assign(1, '邮件发送失败');
|
||||
}
|
||||
}
|
||||
|
||||
//获取部门
|
||||
public function get_department()
|
||||
{
|
||||
$department = get_department();
|
||||
return to_assign(0, '', $department);
|
||||
}
|
||||
|
||||
//获取部门树形节点列表
|
||||
public function get_department_tree()
|
||||
{
|
||||
$department = get_department();
|
||||
$list = get_tree($department, 0, 2);
|
||||
$data['trees'] = $list;
|
||||
return json($data);
|
||||
}
|
||||
|
||||
//获取部门树形节点列表2
|
||||
public function get_department_select()
|
||||
{
|
||||
$keyword = get_params('keyword');
|
||||
$selected = [];
|
||||
if(!empty($keyword)){
|
||||
$selected = explode(",",$keyword);
|
||||
}
|
||||
$department = get_department();
|
||||
$list = get_select_tree($department, 0,0,$selected);
|
||||
return to_assign(0, '',$list);
|
||||
}
|
||||
|
||||
//获取子部门所有员工
|
||||
public function get_employee($did = 0)
|
||||
{
|
||||
$did = get_params('did');
|
||||
if($did == 1){
|
||||
$department = $did;
|
||||
}
|
||||
else{
|
||||
$department = get_department_son($did);
|
||||
}
|
||||
$employee = Db::name('admin')
|
||||
->field('a.id,a.did,a.position_id,a.mobile,a.name,a.nickname,a.sex,a.status,a.thumb,a.username,d.title as department')
|
||||
->alias('a')
|
||||
->join('Department d', 'a.did = d.id')
|
||||
->where(['a.status' => 1])
|
||||
->where('a.id', ">", 1)
|
||||
->where('a.did', "in", $department)
|
||||
->select();
|
||||
return to_assign(0, '', $employee);
|
||||
}
|
||||
|
||||
//获取所有员工
|
||||
public function get_personnel()
|
||||
{
|
||||
$param = get_params();
|
||||
$where[] = ['a.status', '=', 1];
|
||||
$where[] = ['a.id', '>', 1];
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.name', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if(!empty($param['ids'])){
|
||||
$where[] = ['a.id', 'notin', $param['ids']];
|
||||
}
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$list = Db::name('admin')
|
||||
->field('a.id,a.did,a.position_id,a.mobile,a.name,a.nickname,a.sex,a.status,a.thumb,a.username,d.title as department')
|
||||
->alias('a')
|
||||
->join('Department d', 'a.did = d.id')
|
||||
->where($where)
|
||||
->order('a.id desc')
|
||||
->paginate($rows, false, ['query' => $param]);
|
||||
return table_assign(0, '', $list);
|
||||
}
|
||||
|
||||
//获取部门所有员工
|
||||
public function get_employee_select()
|
||||
{
|
||||
$keyword = get_params('keyword');
|
||||
$selected = [];
|
||||
if(!empty($keyword)){
|
||||
$selected = explode(",",$keyword);
|
||||
}
|
||||
$employee = Db::name('admin')
|
||||
->field('id as value,name')
|
||||
->where(['status' => 1])
|
||||
->select()->toArray();
|
||||
|
||||
foreach($employee as $k => &$v){
|
||||
$v['selected'] = '';
|
||||
if(in_array($v['value'],$selected)){
|
||||
$v['selected'] = 'selected';
|
||||
}
|
||||
}
|
||||
return to_assign(0, '', $employee);
|
||||
}
|
||||
|
||||
//获取角色列表
|
||||
public function get_position()
|
||||
{
|
||||
$position = Db::name('Position')->field('id,title as name')->where([['status', '=', 1], ['id', '>', 1]])->select();
|
||||
return to_assign(0, '', $position);
|
||||
}
|
||||
|
||||
//获取审核类型
|
||||
public function get_flow_cate($type=0)
|
||||
{
|
||||
$flows = Db::name('FlowType')->where(['type'=>$type,'status'=>1])->select()->toArray();
|
||||
return to_assign(0, '', $flows);
|
||||
}
|
||||
//获取审核步骤人员
|
||||
public function get_flow_users($id=0)
|
||||
{
|
||||
$flow = Db::name('Flow')->where(['id' => $id])->find();
|
||||
$flowData = unserialize($flow['flow_list']);
|
||||
if(!empty($flowData)){
|
||||
foreach ($flowData as $key => &$val) {
|
||||
$val['user_id_info'] = Db::name('Admin')->field('id,name,thumb')->where('id','in',$val['flow_uids'])->select()->toArray();
|
||||
}
|
||||
}
|
||||
$data['copy_uids'] = $flow['copy_uids'];
|
||||
$data['copy_unames'] ='';
|
||||
if($flow['copy_uids']!=''){
|
||||
$copy_unames = Db::name('Admin')->where('id', 'in', $flow['copy_uids'])->column('name');
|
||||
$data['copy_unames'] = implode(',', $copy_unames);
|
||||
}
|
||||
$data['flow_data'] = $flowData;
|
||||
return to_assign(0, '', $data);
|
||||
}
|
||||
|
||||
//获取审核流程节点
|
||||
public function get_flow_nodes($id=0,$type=1)
|
||||
{
|
||||
$flows = Db::name('FlowStep')->where(['action_id'=>$id,'type'=>$type,'delete_time'=>0])->order('sort asc')->select()->toArray();
|
||||
foreach ($flows as $key => &$val) {
|
||||
$user_id_info = Db::name('Admin')->field('id,name,thumb')->where('id','in',$val['flow_uids'])->select()->toArray();
|
||||
foreach ($user_id_info as $k => &$v) {
|
||||
$v['check_time'] = 0;
|
||||
$v['content'] = '';
|
||||
$v['status'] = 0;
|
||||
$check_array = Db::name('FlowRecord')->where(['check_user_id' => $v['id'],'step_id' => $val['id']])->order('check_time desc')->select()->toArray();
|
||||
if(!empty($check_array)){
|
||||
$checked = $check_array[0];
|
||||
$v['check_time'] = date('Y-m-d H:i', $checked['check_time']);
|
||||
$v['content'] = $checked['content'];
|
||||
$v['status'] = $checked['status'];
|
||||
}
|
||||
}
|
||||
|
||||
$check_list = Db::name('FlowRecord')
|
||||
->field('f.*,a.name,a.thumb')
|
||||
->alias('f')
|
||||
->join('Admin a', 'a.id = f.check_user_id', 'left')
|
||||
->where(['f.step_id' => $val['id']])->select()->toArray();
|
||||
foreach ($check_list as $kk => &$vv) {
|
||||
$vv['check_time_str'] = date('Y-m-d H:i', $vv['check_time']);
|
||||
}
|
||||
|
||||
$val['user_id_info'] = $user_id_info;
|
||||
$val['check_list'] = $check_list;
|
||||
}
|
||||
return to_assign(0, '', $flows);
|
||||
}
|
||||
|
||||
//获取审核流程节点
|
||||
public function get_flow_record($id=0,$type=1)
|
||||
{
|
||||
$check_list = Db::name('FlowRecord')
|
||||
->field('f.*,a.name,a.thumb')
|
||||
->alias('f')
|
||||
->join('Admin a', 'a.id = f.check_user_id', 'left')
|
||||
->where(['f.action_id'=>$id,'f.type'=>$type])
|
||||
->order('check_time asc')
|
||||
->select()->toArray();
|
||||
foreach ($check_list as $kk => &$vv) {
|
||||
$vv['check_time_str'] = date('Y-m-d H:i', $vv['check_time']);
|
||||
}
|
||||
return to_assign(0, '', $check_list);
|
||||
}
|
||||
|
||||
//流程审核
|
||||
public function flow_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$id = $param['id'];
|
||||
$type = $param['type'];
|
||||
$detail = [];
|
||||
$subject = '一个审批';
|
||||
if($type==1){
|
||||
//日常审核
|
||||
$detail = Db::name('Approve')->where(['id' => $id])->find();
|
||||
$subject = '一个日常审批';
|
||||
$msg_title_type = $detail['type'];
|
||||
}
|
||||
else if($type==2){
|
||||
//报销审核
|
||||
$detail = Db::name('Expense')->where(['id' => $id])->find();
|
||||
$subject = '一个报销审批';
|
||||
$msg_title_type = 22;
|
||||
}
|
||||
else if($type==3){
|
||||
//发票审核
|
||||
$detail = Db::name('Invoice')->where(['id' => $id])->find();
|
||||
$subject = '一个发票审批';
|
||||
$msg_title_type = 23;
|
||||
}
|
||||
else if($type==4){
|
||||
//合同审核
|
||||
$detail = Db::name('Contract')->where(['id' => $id])->find();
|
||||
$subject = '一个合同审批';
|
||||
$msg_title_type = 24;
|
||||
}
|
||||
if (empty($detail)){
|
||||
return to_assign(1,'审批数据错误');
|
||||
}
|
||||
//当前审核节点详情
|
||||
$step = Db::name('FlowStep')->where(['action_id'=>$id,'type'=>$type,'sort'=>$detail['check_step_sort'],'delete_time'=>0])->find();
|
||||
|
||||
//审核通过
|
||||
if($param['check'] == 1){
|
||||
$check_admin_ids = explode(",", strval($detail['check_admin_ids']));
|
||||
if (!in_array($this->uid, $check_admin_ids)){
|
||||
return to_assign(1,'您没权限审核该审批');
|
||||
}
|
||||
|
||||
//多人会签审批
|
||||
if($step['flow_type'] == 4){
|
||||
//查询当前会签记录数
|
||||
$check_count = Db::name('FlowRecord')->where(['action_id'=>$id,'type'=>$type,'step_id'=>$step['id']])->count();
|
||||
//当前会签记应有记录数
|
||||
$flow_count = explode(',', $step['flow_uids']);
|
||||
if(($check_count+1) >=count($flow_count)){
|
||||
$next_step = Db::name('FlowStep')->where(['action_id'=>$id,'type'=>$type,'sort'=>($detail['check_step_sort']+1),'delete_time'=>0])->find();
|
||||
if($next_step){
|
||||
//存在下一步审核
|
||||
if($next_step['flow_type'] == 1){
|
||||
$param['check_admin_ids'] = get_department_leader($detail['admin_id']);
|
||||
}
|
||||
else if($next_step['flow_type'] == 2){
|
||||
$param['check_admin_ids'] = get_department_leader($detail['admin_id'],1);
|
||||
}
|
||||
else{
|
||||
$param['check_admin_ids'] = $next_step['flow_uids'];
|
||||
}
|
||||
$param['check_step_sort'] = $detail['check_step_sort']+1;
|
||||
$param['check_status'] = 1;
|
||||
}
|
||||
else{
|
||||
//不存在下一步审核,审核结束
|
||||
$param['check_status'] = 2;
|
||||
$param['check_admin_ids'] ='';
|
||||
}
|
||||
}
|
||||
else{
|
||||
$param['check_status'] = 1;
|
||||
$param['check_admin_ids'] = $step['flow_uids'];
|
||||
}
|
||||
}
|
||||
else if($step['flow_type'] == 0){
|
||||
//自由人审批
|
||||
if($param['check_node'] == 2){
|
||||
$next_step = $detail['check_step_sort']+1;
|
||||
$flow_step = array(
|
||||
'action_id' => $id,
|
||||
'sort' => $next_step,
|
||||
'type' => $type,
|
||||
'flow_uids' => $param['check_admin_ids'],
|
||||
'create_time' => time()
|
||||
);
|
||||
$fid = Db::name('FlowStep')->strict(false)->field(true)->insertGetId($flow_step);
|
||||
//下一步审核步骤
|
||||
$param['check_admin_ids'] = $param['check_admin_ids'];
|
||||
$param['check_step_sort'] = $next_step;
|
||||
$param['check_status'] = 1;
|
||||
}
|
||||
else{
|
||||
//不存在下一步审核,审核结束
|
||||
$param['check_status'] = 2;
|
||||
$param['check_admin_ids'] ='';
|
||||
}
|
||||
}
|
||||
else{
|
||||
$next_step = Db::name('FlowStep')->where(['action_id'=>$id,'type'=>$type,'sort'=>($detail['check_step_sort']+1),'delete_time'=>0])->find();
|
||||
if($next_step){
|
||||
//存在下一步审核
|
||||
if($next_step['flow_type'] == 1){
|
||||
$param['check_admin_ids'] = get_department_leader($detail['admin_id']);
|
||||
}
|
||||
else if($next_step['flow_type'] == 2){
|
||||
$param['check_admin_ids'] = get_department_leader($detail['admin_id'],1);
|
||||
}
|
||||
else{
|
||||
$param['check_admin_ids'] = $next_step['flow_uids'];
|
||||
}
|
||||
$param['check_step_sort'] = $detail['check_step_sort']+1;
|
||||
$param['check_status'] = 1;
|
||||
}
|
||||
else{
|
||||
//不存在下一步审核,审核结束
|
||||
$param['check_status'] = 2;
|
||||
$param['check_admin_ids'] ='';
|
||||
}
|
||||
}
|
||||
if($param['check_status'] == 1 && empty($param['check_admin_ids'])){
|
||||
return to_assign(1,'找不到下一步的审批人,该审批流程设置有问题,请联系HR或者管理员');
|
||||
}
|
||||
//审核通过数据操作
|
||||
$param['last_admin_id'] = $this->uid;
|
||||
$param['flow_admin_ids'] = $detail['flow_admin_ids'].$this->uid.',';
|
||||
|
||||
if($type==1){
|
||||
//日常审核
|
||||
$res = Db::name('Approve')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==2){
|
||||
//报销审核
|
||||
$res = Db::name('Expense')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==3){
|
||||
//发票审核
|
||||
$res = Db::name('Invoice')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==4){
|
||||
//合同审核
|
||||
$res = Db::name('Contract')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
|
||||
if($res!==false){
|
||||
$checkData=array(
|
||||
'action_id' => $id,
|
||||
'step_id' => $step['id'],
|
||||
'check_user_id' => $this->uid,
|
||||
'type' => $type,
|
||||
'check_time' => time(),
|
||||
'status' => $param['check'],
|
||||
'content' => $param['content'],
|
||||
'create_time' => time()
|
||||
);
|
||||
$aid = Db::name('FlowRecord')->strict(false)->field(true)->insertGetId($checkData);
|
||||
add_log('check', $param['id'], $param,$subject);
|
||||
//发送消息通知
|
||||
$msg=[
|
||||
'create_time'=>date('Y-m-d H:i:s',$detail['create_time']),
|
||||
'action_id'=>$id,
|
||||
'title' => Db::name('FlowType')->where('id',$msg_title_type)->value('title'),
|
||||
'from_uid'=>$detail['admin_id']
|
||||
];
|
||||
if($param['check_status'] == 1){
|
||||
$users = $param['check_admin_ids'];
|
||||
sendMessage($users,($type*10+11),$msg);
|
||||
}
|
||||
if($param['check_status'] == 2){
|
||||
$users = $detail['admin_id'];
|
||||
sendMessage($users,($type*10+12),$msg);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(1,'操作失败');
|
||||
}
|
||||
}
|
||||
else if($param['check'] == 2){
|
||||
$check_admin_ids = explode(",", strval($detail['check_admin_ids']));
|
||||
if (!in_array($this->uid, $check_admin_ids)){
|
||||
return to_assign(1,'您没权限审核该审批');
|
||||
}
|
||||
//拒绝审核,数据操作
|
||||
$param['check_status'] = 3;
|
||||
$param['last_admin_id'] = $this->uid;
|
||||
$param['flow_admin_ids'] = $detail['flow_admin_ids'].$this->uid.',';
|
||||
$param['check_admin_ids'] ='';
|
||||
if($step['flow_type'] == 5){
|
||||
//获取上一步的审核信息
|
||||
$prev_step = Db::name('FlowStep')->where(['action_id'=>$id,'type'=>$type,'sort'=>($detail['check_step_sort']-1),'delete_time'=>0])->find();
|
||||
if($prev_step){
|
||||
//存在上一步审核
|
||||
$param['check_step_sort'] = $prev_step['sort'];
|
||||
$param['check_admin_ids'] = $prev_step['flow_uids'];
|
||||
$param['check_status'] = 1;
|
||||
}
|
||||
else{
|
||||
//不存在上一步审核,审核初始化步骤
|
||||
$param['check_step_sort'] = 0;
|
||||
$param['check_admin_ids'] = '';
|
||||
$param['check_status'] = 0;
|
||||
}
|
||||
}
|
||||
if($type==1){
|
||||
//日常审核
|
||||
$res = Db::name('Approve')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==2){
|
||||
//报销审核
|
||||
$res = Db::name('Expense')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==3){
|
||||
//发票审核
|
||||
$res = Db::name('Invoice')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==4){
|
||||
//合同审核
|
||||
$res = Db::name('Contract')->strict(false)->field('check_step_sort,check_status,last_admin_id,flow_admin_ids,check_admin_ids')->update($param);
|
||||
}
|
||||
if($res!==false){
|
||||
$checkData=array(
|
||||
'action_id' => $id,
|
||||
'step_id' => $step['id'],
|
||||
'check_user_id' => $this->uid,
|
||||
'type' => $type,
|
||||
'check_time' => time(),
|
||||
'status' => $param['check'],
|
||||
'content' => $param['content'],
|
||||
'create_time' => time()
|
||||
);
|
||||
$aid = Db::name('FlowRecord')->strict(false)->field(true)->insertGetId($checkData);
|
||||
add_log('refue', $param['id'], $param,$subject);
|
||||
//发送消息通知
|
||||
$msg=[
|
||||
'create_time'=>date('Y-m-d H:i:s',$detail['create_time']),
|
||||
'action_id'=>$detail['id'],
|
||||
'title' => Db::name('FlowType')->where('id',$msg_title_type)->value('title'),
|
||||
'from_uid'=>$detail['admin_id']
|
||||
];
|
||||
$users = $detail['admin_id'];
|
||||
sendMessage($users,($type*10+13),$msg);
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(1,'操作失败');
|
||||
}
|
||||
}
|
||||
else if($param['check'] == 3){
|
||||
if($detail['admin_id'] != $this->uid){
|
||||
return to_assign(1,'你没权限操作');
|
||||
}
|
||||
//撤销审核,数据操作
|
||||
$param['check_status'] = 4;
|
||||
$param['check_admin_ids'] ='';
|
||||
$param['check_step_sort'] =0;
|
||||
if($type==1){
|
||||
//日常审核
|
||||
$res = Db::name('Approve')->strict(false)->field('check_step_sort,check_status,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==2){
|
||||
//报销审核
|
||||
$res = Db::name('Expense')->strict(false)->field('check_step_sort,check_status,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==3){
|
||||
//发票审核
|
||||
$res = Db::name('Invoice')->strict(false)->field('check_step_sort,check_status,check_admin_ids')->update($param);
|
||||
}
|
||||
else if($type==4){
|
||||
//合同审核
|
||||
$res = Db::name('Contract')->strict(false)->field('check_step_sort,check_status,check_admin_ids')->update($param);
|
||||
}
|
||||
if($res!==false){
|
||||
$checkData=array(
|
||||
'action_id' => $id,
|
||||
'step_id' => 0,
|
||||
'check_user_id' => $this->uid,
|
||||
'type' => $type,
|
||||
'check_time' => time(),
|
||||
'status' => $param['check'],
|
||||
'content' => $param['content'],
|
||||
'create_time' => time()
|
||||
);
|
||||
$aid = Db::name('FlowRecord')->strict(false)->field(true)->insertGetId($checkData);
|
||||
add_log('back', $param['id'], $param,$subject);
|
||||
return to_assign();
|
||||
}else{
|
||||
return to_assign(1,'操作失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//获取关键字
|
||||
public function get_keyword_cate()
|
||||
{
|
||||
$keyword = Db::name('Keywords')->where(['status' => 1])->order('id desc')->select()->toArray();
|
||||
return to_assign(0, '', $keyword);
|
||||
}
|
||||
|
||||
//读取报销类型
|
||||
function get_expense_cate()
|
||||
{
|
||||
$cate = get_expense_cate();
|
||||
return to_assign(0, '', $cate);
|
||||
}
|
||||
|
||||
//读取费用类型
|
||||
function get_cost_cate()
|
||||
{
|
||||
$cate = get_cost_cate();
|
||||
return to_assign(0, '', $cate);
|
||||
}
|
||||
|
||||
//读取印章类型
|
||||
function get_seal_cate()
|
||||
{
|
||||
$cate = get_seal_cate();
|
||||
return to_assign(0, '', $cate);
|
||||
}
|
||||
|
||||
//读取车辆类型
|
||||
function get_car_cate()
|
||||
{
|
||||
$cate = get_car_cate();
|
||||
return to_assign(0, '', $cate);
|
||||
}
|
||||
|
||||
//读取企业主体
|
||||
function get_subject()
|
||||
{
|
||||
$subject = get_subject();
|
||||
return to_assign(0, '', $subject);
|
||||
}
|
||||
|
||||
//读取行业类型
|
||||
function get_industry()
|
||||
{
|
||||
$industry = get_industry();
|
||||
return to_assign(0, '', $industry);
|
||||
}
|
||||
|
||||
//读取服务类型
|
||||
function get_services()
|
||||
{
|
||||
$services = get_services();
|
||||
return to_assign(0, '', $services);
|
||||
}
|
||||
|
||||
//获取工作类型列表
|
||||
public function get_work_cate()
|
||||
{
|
||||
$cate = get_work_cate();
|
||||
return to_assign(0, '', $cate);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
// 这是系统自动生成的event定义文件
|
||||
return [
|
||||
|
||||
];
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
//开启session中间件
|
||||
//'think\middleware\SessionInit',
|
||||
//验证勾股cms是否完成安装
|
||||
\app\home\middleware\Install::class,
|
||||
];
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\api\middleware;
|
||||
|
||||
use Firebase\JWT\JWT;
|
||||
use Firebase\JWT\Key;
|
||||
use think\facade\Request;
|
||||
use think\Response;
|
||||
|
||||
class Auth
|
||||
{
|
||||
public function handle($request, \Closure $next)
|
||||
{
|
||||
$token = Request::header('Token');
|
||||
if ($token) {
|
||||
if (count(explode('.', $token)) != 3) {
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
}
|
||||
$config = get_system_config('token');
|
||||
//var_dump($config);exit;
|
||||
try {
|
||||
JWT::$leeway = 60;//当前时间减去60,把时间留点余地
|
||||
$decoded = JWT::decode($token, new Key($config['secrect'], 'HS256')); //HS256方式,这里要和签发的时候对应
|
||||
//return (array)$decoded;
|
||||
$decoded_array = json_decode(json_encode($decoded),TRUE);
|
||||
$jwt_data = $decoded_array['data'];
|
||||
//$request->uid = $jwt_data['userid'];
|
||||
define('JWT_UID', $jwt_data['userid']);
|
||||
$response = $next($request);
|
||||
return $response;
|
||||
//return $next($request);
|
||||
} catch(\Firebase\JWT\SignatureInvalidException $e) { //签名不正确
|
||||
return json(['code'=>403,'msg'=>'签名错误']);
|
||||
}catch(\Firebase\JWT\BeforeValidException $e) { // 签名在某个时间点之后才能用
|
||||
return json(['code'=>401,'msg'=>'token失效']);
|
||||
}catch(\Firebase\JWT\ExpiredException $e) { // token过期
|
||||
return json(['code'=>401,'msg'=>'token已过期']);
|
||||
}catch(Exception $e) { //其他错误
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
}catch(\UnexpectedValueException $e) { //其他错误
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
} catch(\DomainException $e) { //其他错误
|
||||
return json(['code'=>404,'msg'=>'非法请求']);
|
||||
}
|
||||
} else {
|
||||
return json(['code'=>404,'msg'=>'token不能为空']);
|
||||
}
|
||||
return $next($request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
/**
|
||||
======================
|
||||
*模块数据获取公共文件
|
||||
======================
|
||||
*/
|
||||
use think\facade\Db;
|
||||
|
||||
//读取知识分类子分类ids
|
||||
function admin_article_cate_son($id = 0, $is_self = 1)
|
||||
{
|
||||
$article = Db::name('ArticleCate')->order('id desc')->select()->toArray();
|
||||
$article_list = get_data_node($article, $id);
|
||||
$article_array = array_column($article_list, 'id');
|
||||
if ($is_self == 1) {
|
||||
//包括自己在内
|
||||
$article_array[] = $id;
|
||||
}
|
||||
return $article_array;
|
||||
}
|
||||
//读取知识分类列表
|
||||
function article_cate()
|
||||
{
|
||||
$cate = Db::name('ArticleCate')->order('id desc')->select()->toArray();
|
||||
return $cate;
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
勾股OA模块安装鉴定文件,请勿删除!!!!!此次模块标识为:article
|
|
@ -0,0 +1,100 @@
|
|||
-- ----------------------------
|
||||
-- Table structure for oa_article_cate
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_article_cate`;
|
||||
CREATE TABLE `oa_article_cate` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`pid` int(11) NOT NULL DEFAULT 0 COMMENT '父类ID',
|
||||
`sort` int(5) NOT NULL DEFAULT 0 COMMENT '排序',
|
||||
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '分类标题',
|
||||
`desc` varchar(1000) NULL DEFAULT '' COMMENT '描述',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '知识文章分类表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_article_cate
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_article_cate` VALUES (1, 0, 0, '办公技巧', '', 1637984651, 0);
|
||||
INSERT INTO `oa_article_cate` VALUES (2, 0, 0, '行业技能', '', 1637984739, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_article
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_article`;
|
||||
CREATE TABLE `oa_article` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '知识文章标题',
|
||||
`cate_id` int(11) NOT NULL DEFAULT 0 COMMENT '关联分类id',
|
||||
`keywords` varchar(255) NULL DEFAULT '' COMMENT '关键字',
|
||||
`desc` varchar(1000) NULL DEFAULT '' COMMENT '摘要',
|
||||
`thumb` int(11) NOT NULL DEFAULT 0 COMMENT '缩略图id',
|
||||
`uid` int(11) NOT NULL DEFAULT 0 COMMENT '作者',
|
||||
`did` int(11) NOT NULL DEFAULT 0 COMMENT '部门',
|
||||
`origin_url` varchar(255) NOT NULL DEFAULT '' COMMENT '来源地址',
|
||||
`file_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '相关附件',
|
||||
`is_share` tinyint(1) NOT NULL DEFAULT 1 COMMENT '分享,0私有,1所有人,2部门,3人员',
|
||||
`share_dids` varchar(500) NOT NULL DEFAULT '' COMMENT '分享部门',
|
||||
`share_uids` varchar(500) NOT NULL DEFAULT '' COMMENT '分享用户',
|
||||
`content` text NOT NULL COMMENT '文章内容',
|
||||
`read` int(11) NOT NULL DEFAULT 0 COMMENT '阅读量',
|
||||
`type` tinyint(2) NOT NULL DEFAULT 0 COMMENT '属性:1精华 2热门 3推荐',
|
||||
`status` int(1) NOT NULL DEFAULT 1 COMMENT '状态:1正常-1下架',
|
||||
`sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0,
|
||||
`update_time` int(11) NOT NULL DEFAULT 0,
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '知识文章表';
|
||||
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_article
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_article` VALUES (1, '勾股OA——简单实用的开源免费的企业办公系统框架', 2, '', '勾股办公是一款简单实用的开源免费的企业办公系统框架。系统集成了系统设置、人事管理模块、消息管理模块、日常办公、财务管理等基础模块。系统简约,易于功...', 0, 1, 1, '','',1,'','', '<p>勾股办公是一款简单实用的开源免费的企业办公系统框架。系统集成了系统设置、人事管理模块、消息管理模块、日常办公、财务管理等基础模块。系统简约,易于功能扩展,方便二次开发,让开发者更专注于业务深度需求的开发,帮助开发者简单高效降低二次开发成本,通过二次开发之后可以用来做CRM,ERP,业务管理等系统。</p><p>项目体验地址:https://www.gougucms.com/home/pages/detail/s/gouguoa.html</p><p>项目开源地址:https://gitee.com/gouguopen/office</p>', 1, 2, 1, 1, 1637985280, 1650817107, 0);
|
||||
INSERT INTO `oa_article` VALUES (2, '勾股Admin——优秀的前端Web UI解决方案', 2, '', '勾股Admin是一款开基于Layui的最新版扩展的Web UI解决方案。封装了Layui的自身调用方法和一些常用的工具函数,整合部分第三方开源的组件。', 0, 1, 1, '','',1,'','', '<p>勾股Admin是一款开基于Layui的最新版扩展的Web UI解决方案。封装了Layui的自身调用方法和一些常用的工具函数,整合部分第三方开源的组件。更多是为服务端程序员量身定做,为使用者提供相对完善的前端UI开发方案,相信她是一个很好的前端轮子。</p>
|
||||
<p>项目体验地址:http://admin.gougucms.com</p><p>项目开源地址:https://gitee.com/gouguopen/guoguadmin</p>', 0, 0, 1, 1, 1650817189, 0, 0);
|
||||
INSERT INTO `oa_article` VALUES (3, '勾股CMS——轻量级、高性能极速后台开发框架', 2, '', '勾股CMS是一套轻量级、高性能极速后台开发框架。通用型的后台权限管理框架,极低门槛、操作简单、开箱即用。系统易于功能扩展,代码维护,方便二次开发,让...', 0, 1, 1, '', '',1,'','','<p>勾股CMS是一套轻量级、高性能极速后台开发框架。通用型的后台权限管理框架,极低门槛、操作简单、开箱即用。系统易于功能扩展,代码维护,方便二次开发,让开发者更专注于业务深度需求的开发,帮助开发者简单高效降低二次开发成本。</p><p>项目体验地址:http://www.gougucms.com</p><p>项目开源地址:https://gitee.com/gouguopen/gougucms</p>', 0, 0, 1, 1, 1650817085, 0, 0);
|
||||
INSERT INTO `oa_article` VALUES (4, '勾股BLOG——简约,易用开源的个人博客系统', 2, '', '勾股BLOG是一款实用的开源免费的个人博客系统。集成了系统管理、基础数据、博客文章、博客动态、语雀知识库、用户管理、访问统计等功能。具有简约,易用,内存占用低等特点,可以用来做个人博客,工作室官网,自...', 0, 1, 1, '', '',1,'','','<p>勾股BLOG是一款实用的开源免费的个人博客系统。集成了系统管理、基础数据、博客文章、博客动态、语雀知识库、用户管理、访问统计等功能。具有简约,易用,内存占用低等特点,可以用来做个人博客,工作室官网,自媒体官网等网站,二次开发之后也可以作为资讯、展品展示等网站。</p><p>项目体验地址:http://blog.gougucms.com</p><p>项目开源地址:https://gitee.com/gouguopen/blog</p>', 0, 0, 1, 1, 1650817152, 0, 0);
|
||||
INSERT INTO `oa_article` VALUES (5, '勾股DEV——研发管理与团队协作的工具', 2, '', '勾股DEV是一款专为IT行业研发团队打造的智能化项目管理与团队协作的工具,可以在线管理团队的工作、项目和任务,覆盖从需求提出到研发完成上线整个过程的项目协作。', 0, 1, 1, '', '',1,'','','<p>勾股DEV是一款专为IT行业研发团队打造的智能化项目管理与团队协作的工具软件,可以在线管理团队的工作、项目和任务,覆盖从需求提出到研发完成上线整个过程的项目协作。</p><p>项目体验地址:https://www.gougucms.com/home/pages/detail/s/gougudev.html</p><p>项目开源地址:https://gitee.com/gouguopen/dev</p>', 0, 0, 1, 1, 1650817189, 0, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_article_keywords
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_article_keywords`;
|
||||
CREATE TABLE `oa_article_keywords` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`aid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '知识文章ID',
|
||||
`keywords_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联关键字id',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
INDEX `aid`(`aid`) USING BTREE,
|
||||
INDEX `inid`(`keywords_id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '知识文章关联表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_article_keywords
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_article_keywords` VALUES (1, 1, 1, 1, 1638093082);
|
||||
INSERT INTO `oa_article_keywords` VALUES (2, 2, 2, 1, 1638093082);
|
||||
INSERT INTO `oa_article_keywords` VALUES (3, 3, 3, 3, 1638093082);
|
||||
INSERT INTO `oa_article_keywords` VALUES (4, 4, 4, 4, 1638093082);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_article_comment
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_article_comment`;
|
||||
CREATE TABLE `oa_article_comment` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`article_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联知识文章id',
|
||||
`pid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '回复内容id',
|
||||
`padmin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '回复内容用户id',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`content` text NULL COMMENT '评论内容',
|
||||
`create_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '添加时间',
|
||||
`update_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '修改时间',
|
||||
`delete_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1000 COMMENT = '知识评论表' ROW_FORMAT = Compact;
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\article\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use app\article\model\ArticleComment;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Api extends BaseController
|
||||
{
|
||||
//获取评论列表
|
||||
public function article_comment()
|
||||
{
|
||||
$param = get_params();
|
||||
$list = new ArticleComment();
|
||||
$content = $list->get_list($param);
|
||||
return to_assign(0, '', $content);
|
||||
}
|
||||
|
||||
//添加修改评论内容
|
||||
public function add_comment()
|
||||
{
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
$param['update_time'] = time();
|
||||
unset($param['pid']);
|
||||
unset($param['padmin_id']);
|
||||
$res = ArticleComment::where(['admin_id' => $this->uid,'id'=>$param['id']])->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param,'评论');
|
||||
return to_assign();
|
||||
}
|
||||
} else {
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$cid = ArticleComment::strict(false)->field(true)->insertGetId($param);
|
||||
if ($cid) {
|
||||
add_log('add', $cid, $param,'评论');
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//删除评论内容
|
||||
public function delete_comment()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$id = get_params("id");
|
||||
$res = ArticleComment::where('id',$id)->strict(false)->field(true)->update(['delete_time'=>time()]);
|
||||
if ($res) {
|
||||
add_log('delete', $id,[],'评论');
|
||||
return to_assign(0, "删除成功");
|
||||
} else {
|
||||
return to_assign(1, "删除失败");
|
||||
}
|
||||
}else{
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\article\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\article\validate\ArticleCateCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Cate extends BaseController
|
||||
{
|
||||
//文章类别
|
||||
public function cate()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('ArticleCate')->order('create_time asc')->select();
|
||||
$list = generateTree($cate);
|
||||
return to_assign(0, '', $list);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//文章分类添加&编辑
|
||||
public function cate_add()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(ArticleCateCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$note_array = admin_article_cate_son($param['id']);
|
||||
if (in_array($param['pid'], $note_array)) {
|
||||
return to_assign(1, '父级分类不能是该分类本身或其子分类');
|
||||
} else {
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('ArticleCate')->strict(false)->field(true)->update($param);
|
||||
if($res){
|
||||
add_log('edit', $param['id'], $param);
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
validate(ArticleCateCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('ArticleCate')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
} else {
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
$pid = isset($param['pid']) ? $param['pid'] : 0;
|
||||
$cate = Db::name('ArticleCate')->order('id desc')->select()->toArray();
|
||||
$cates = set_recursion($cate);
|
||||
if ($id > 0) {
|
||||
$detail = Db::name('ArticleCate')->where(['id' => $id])->find();
|
||||
View::assign('detail', $detail);
|
||||
}
|
||||
View::assign('id', $id);
|
||||
View::assign('pid', $pid);
|
||||
View::assign('cates', $cates);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//删除文章分类
|
||||
public function cate_delete()
|
||||
{
|
||||
$id = get_params("id");
|
||||
$cate_count = Db::name('ArticleCate')->where(["pid" => $id])->count();
|
||||
if ($cate_count > 0) {
|
||||
return to_assign(1, "该分类下还有子分类,无法删除");
|
||||
}
|
||||
$content_count = Db::name('Article')->where(["cate_id" => $id])->count();
|
||||
if ($content_count > 0) {
|
||||
return to_assign(1, "该分类下还有文章,无法删除");
|
||||
}
|
||||
if (Db::name('ArticleCate')->delete($id) !== false) {
|
||||
add_log('delete', $id);
|
||||
return to_assign(0, "删除分类成功");
|
||||
} else {
|
||||
return to_assign(1, "删除失败");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\article\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\article\model\Article as ArticleList;
|
||||
use app\article\validate\ArticleCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Index extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$uid = $this->uid;
|
||||
$did = $this->did;
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.title|a.keywords|a.desc|a.content|c.title', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['cate_id'])) {
|
||||
$where[] = ['a.cate_id', '=', $param['cate_id']];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
|
||||
$whereOr[] = ['a.is_share', '=', 1];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$did}',a.share_dids)")];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.share_uids)")];
|
||||
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = ArticleList::where($where)
|
||||
->where(function ($query) use($whereOr) {
|
||||
$query->whereOr($whereOr);
|
||||
})
|
||||
->field('a.*,a.id as id,c.title as cate_title,a.title as title,d.title as department,u.name as user')
|
||||
->alias('a')
|
||||
->join('article_cate c', 'a.cate_id = c.id')
|
||||
->join('admin u', 'a.uid = u.id','LEFT')
|
||||
->join('department d', 'a.did = d.id','LEFT')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param]);
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
public function list()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.title|a.keywords|a.desc|a.content|c.title', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['cate_id'])) {
|
||||
$where[] = ['a.cate_id', '=', $param['cate_id']];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
$where[] = ['a.uid', '=', $this->uid];
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = ArticleList::where($where)
|
||||
->field('a.*,a.id as id,c.title as cate_title,a.title as title')
|
||||
->alias('a')
|
||||
->join('article_cate c', 'a.cate_id = c.id')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param]);
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//文章添加&&编辑
|
||||
public function add()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
$DbRes = false;
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(ArticleCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
Db::startTrans();
|
||||
try {
|
||||
$res = ArticleList::strict(false)->field(true)->update($param);
|
||||
$aid = $param['id'];
|
||||
if ($res) {
|
||||
//关联关键字
|
||||
if (isset($param['keyword_names']) && $param['keyword_names']) {
|
||||
Db::name('ArticleKeywords')->where(['aid' => $aid])->delete();
|
||||
$keywordArray = explode(',', $param['keyword_names']);
|
||||
$res_keyword = (new ArticleList())->insertKeyword($keywordArray, $aid);
|
||||
} else {
|
||||
$res_keyword = true;
|
||||
}
|
||||
if ($res_keyword !== false) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
Db::commit();
|
||||
$DbRes = true;
|
||||
}
|
||||
} else {
|
||||
Db::rollback();
|
||||
}
|
||||
} catch (\Exception $e) { ##这里参数不能删除($e:错误信息)
|
||||
Db::rollback();
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
validate(ArticleCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$param['uid'] = $this->uid;
|
||||
$param['did'] = $this->did;
|
||||
Db::startTrans();
|
||||
try {
|
||||
if (empty($param['desc'])) {
|
||||
$param['desc'] = get_desc_content($param['content'], 100);
|
||||
}
|
||||
$aid = ArticleList::strict(false)->field(true)->insertGetId($param);
|
||||
if ($aid) {
|
||||
//关联关键字
|
||||
if (isset($param['keyword_names']) && $param['keyword_names']) {
|
||||
$keywordArray = explode(',', $param['keyword_names']);
|
||||
$res_keyword = (new ArticleList())->insertKeyword($keywordArray, $aid);
|
||||
} else {
|
||||
$res_keyword = true;
|
||||
}
|
||||
if ($res_keyword !== false) {
|
||||
add_log('add', $aid, $param);
|
||||
Db::commit();
|
||||
$DbRes = true;
|
||||
}
|
||||
} else {
|
||||
Db::rollback();
|
||||
}
|
||||
} catch (\Exception $e) { ##这里参数不能删除($e:错误信息)
|
||||
Db::rollback();
|
||||
}
|
||||
}
|
||||
if ($DbRes) {
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
View::assign('id', $id);
|
||||
if ($id > 0) {
|
||||
$article = (new ArticleList())->detail($id);
|
||||
if($article['file_ids'] !=''){
|
||||
$fileArray = Db::name('File')->where('id','in',$article['file_ids'])->select();
|
||||
$article['fileArray'] = $fileArray;
|
||||
}
|
||||
$article['share_depaments'] = '';
|
||||
if($article['share_dids'] !=''){
|
||||
$depamentArray = Db::name('Department')->where('id','in',$article['share_dids'])->column('title');
|
||||
$article['share_depaments'] = implode(',',$depamentArray);
|
||||
}
|
||||
$article['share_names'] = '';
|
||||
if($article['share_uids'] !=''){
|
||||
$uidArray = Db::name('Admin')->where('id','in',$article['share_uids'])->column('name');
|
||||
$article['share_names'] = implode(',',$uidArray);
|
||||
}
|
||||
View::assign('article', $article);
|
||||
return view('edit');
|
||||
}
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//查看文章
|
||||
public function view()
|
||||
{
|
||||
$id = get_params("id");
|
||||
$uid=$this->uid;
|
||||
$did=$this->did;
|
||||
$detail = (new ArticleList())->detail($id);
|
||||
$share_uids = [];
|
||||
if(!empty($detail['share_uids'])){
|
||||
$share_uids = explode(',', $detail['share_uids']);
|
||||
}
|
||||
$share_dids = [];
|
||||
if(!empty($detail['share_dids'])){
|
||||
$share_dids = explode(',', $detail['share_dids']);
|
||||
}
|
||||
if($detail['uid'] !=$uid && !in_array($uid,$share_uids) && !in_array($did,$share_dids) && $detail['is_share'] !=1){
|
||||
throw new \think\exception\HttpException(405, '无权限访问');
|
||||
}
|
||||
$detail['cate_title'] = Db::name('ArticleCate')->where(['id' => $detail['cate_id']])->value('title');
|
||||
if($detail['file_ids'] !=''){
|
||||
$fileArray = Db::name('File')->where('id','in',$detail['file_ids'])->select();
|
||||
$detail['fileArray'] = $fileArray;
|
||||
}
|
||||
|
||||
$comment = Db::name('ArticleComment')
|
||||
->field('a.*,u.name,u.thumb')
|
||||
->alias('a')
|
||||
->join('Admin u', 'u.id = a.admin_id')
|
||||
->order('a.create_time desc')
|
||||
->where(['a.article_id'=>$detail['id'],'a.delete_time' => 0])
|
||||
->select()->toArray();
|
||||
foreach ($comment as $k => &$v) {
|
||||
$v['times'] = time_trans($v['create_time']);
|
||||
$v['create_time'] = date('Y-m-d H:i:s',$v['create_time']);
|
||||
if($v['update_time']>0){
|
||||
$v['update_time'] = ',最后编辑时间:'.time_trans($v['update_time']);
|
||||
}
|
||||
else{
|
||||
$v['update_time'] = '';
|
||||
}
|
||||
}
|
||||
$detail['comment'] = $comment;
|
||||
// read 字段加 1
|
||||
Db::name('article')->where('id', $id)->inc('read')->update();
|
||||
View::assign('detail', $detail);
|
||||
return view();
|
||||
}
|
||||
//删除文章
|
||||
public function delete()
|
||||
{
|
||||
$id = get_params("id");
|
||||
$data['id'] = $id;
|
||||
$data['delete_time'] = time();
|
||||
if (Db::name('Article')->update($data) !== false) {
|
||||
add_log('delete', $id);
|
||||
return to_assign(0, "删除成功");
|
||||
} else {
|
||||
return to_assign(1, "删除失败");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
// 这是系统自动生成的event定义文件
|
||||
return [
|
||||
|
||||
];
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
//开启session中间件
|
||||
//'think\middleware\SessionInit',
|
||||
//验证勾股OA是否完成安装
|
||||
\app\home\middleware\Install::class,
|
||||
];
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\article\model;
|
||||
|
||||
use app\home\model\Keywords;
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class Article extends Model
|
||||
{
|
||||
// 获取文章详情
|
||||
public function detail($id)
|
||||
{
|
||||
$article = Db::name('Article')->where(['id' => $id])->find();
|
||||
if (!empty($article)) {
|
||||
$keywrod_array = Db::name('ArticleKeywords')
|
||||
->field('i.aid,i.keywords_id,k.title')
|
||||
->alias('i')
|
||||
->join('Keywords k', 'k.id = i.keywords_id', 'LEFT')
|
||||
->order('i.create_time asc')
|
||||
->where(array('i.aid' => $id, 'k.status' => 1))
|
||||
->select()->toArray();
|
||||
|
||||
$article['keyword_ids'] = implode(",", array_column($keywrod_array, 'keywords_id'));
|
||||
$article['keyword_names'] = implode(',', array_column($keywrod_array, 'title'));
|
||||
$article['user'] = Db::name('Admin')->where(['id' => $article['uid']])->value('name');
|
||||
$article['department'] = Db::name('Department')->where(['id' => $article['did']])->value('title');
|
||||
}
|
||||
return $article;
|
||||
}
|
||||
|
||||
//插入关键字
|
||||
public function insertKeyword($keywordArray = [],$aid = 0)
|
||||
{
|
||||
$insert = [];
|
||||
$time = time();
|
||||
foreach ($keywordArray as $key => $value) {
|
||||
if (!$value) {
|
||||
continue;
|
||||
}
|
||||
$keywords_id = (new Keywords())->increase($value);
|
||||
$insert[] = ['aid' => $aid,
|
||||
'keywords_id' => $keywords_id,
|
||||
'create_time' => $time,
|
||||
];
|
||||
}
|
||||
$res = Db::name('ArticleKeywords')->strict(false)->field(true)->insertAll($insert);
|
||||
return $res;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
namespace app\Article\model;
|
||||
|
||||
use think\Model;
|
||||
|
||||
class ArticleComment extends Model
|
||||
{
|
||||
public function get_list($param = [])
|
||||
{
|
||||
$where = array();
|
||||
$where['a.article_id'] = $param['tid'];
|
||||
$where['a.delete_time'] = 0;
|
||||
$content = \think\facade\Db::name('ArticleComment')
|
||||
->field('a.*,u.name,u.thumb,pu.name as pname')
|
||||
->alias('a')
|
||||
->join('Admin u', 'u.id = a.admin_id')
|
||||
->leftjoin('Admin pu', 'pu.id = a.padmin_id')
|
||||
->order('a.create_time desc')
|
||||
->where($where)
|
||||
->select()->toArray();
|
||||
foreach ($content as $k => &$v) {
|
||||
$v['times'] = time_trans($v['create_time']);
|
||||
$v['create_time'] = date('Y-m-d H:i:s',$v['create_time']);
|
||||
if($v['update_time']>0){
|
||||
$v['update_time'] = ',最后编辑时间:'.time_trans($v['update_time']);
|
||||
}
|
||||
else{
|
||||
$v['update_time'] = '';
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\article\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class ArticleCateCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:article_cate',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\article\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class ArticleCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:article',
|
||||
'content' => 'require',
|
||||
'id' => 'require',
|
||||
'cate_id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '标题不能为空',
|
||||
'title.unique' => '同样的文章标题已经存在',
|
||||
'cate_id.require' => '所属分类为必选',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title', 'cate_id', 'content'],
|
||||
'edit' => ['title', 'cate_id', 'content', 'id'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<div class="gg-form-bar border-t border-x" style="padding-bottom:12px;">
|
||||
<button class="layui-btn layui-btn-sm add-menu">+ 添加分类</button>
|
||||
</div>
|
||||
<div>
|
||||
<table class="layui-hide" id="treeTable" lay-filter="treeTable"></table>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/html" id="switchStatus">
|
||||
<input type="checkbox" name="status" value="{{d.id}}" lay-skin="switch" lay-text="是|否" lay-filter="status" {{ d.status == 1 ? 'checked' : '' }}>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var treeTable = layui.treeTable, tool = layui.tool;
|
||||
|
||||
layui.pageTable = treeTable.render({
|
||||
elem: '#treeTable'
|
||||
,url: "/article/cate/cate"
|
||||
,tree: { // treeTable 特定属性集
|
||||
customName: {name:'title'},
|
||||
data: {},
|
||||
view: {showIcon:false},
|
||||
async: {},
|
||||
callback: {}
|
||||
}
|
||||
,cols: [[
|
||||
{field:'id',width:80, title: 'ID号', align:'center'}
|
||||
,{field: 'sort', title: '排序',align:'center', width:80}
|
||||
,{field:'title', width:240, title: '分类名称'}
|
||||
,{field:'pid', title: '父级ID', width:80, align:'center'}
|
||||
,{field:'desc', title: '描述', }
|
||||
,{width:160,title: '操作', align:'center',templet: function(d){
|
||||
var html = '<span class="layui-btn-group"><button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="add">添加子分类</button><button class="layui-btn layui-btn-xs" lay-event="edit">编辑</button><button class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</button></span>';
|
||||
return html;
|
||||
}
|
||||
}
|
||||
]]
|
||||
,page:false
|
||||
//,skin:'line'
|
||||
});
|
||||
|
||||
//表头工具栏事件
|
||||
$('.add-menu').on('click', function(){
|
||||
tool.side("/article/cate/cate_add");
|
||||
return;
|
||||
});
|
||||
|
||||
//操作按钮
|
||||
treeTable.on('tool(treeTable)', function (obj) {
|
||||
if (obj.event === 'add') {
|
||||
tool.side('/article/cate/cate_add?pid='+obj.data.id);
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'edit') {
|
||||
tool.side('/article/cate/cate_add?id='+obj.data.id);
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'del') {
|
||||
layer.confirm('确定要删除吗?', { icon: 3, title: '提示' }, function (index) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
obj.del();
|
||||
}
|
||||
}
|
||||
tool.delete("/article/cate/cate_delete", { id: obj.data.id }, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,88 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">知识分类</h3>
|
||||
{eq name="$id" value="0"}
|
||||
<table class="layui-table">
|
||||
<tr>
|
||||
<td class="layui-td-gray">父级分类<font>*</font></td>
|
||||
<td>
|
||||
<select name="pid" lay-verify="required" lay-reqText="请选择父级分类">
|
||||
<option value="0">作为顶级分类</option>
|
||||
{volist name="$cates" id="v"}
|
||||
<option value="{$v.id}" {eq name="$pid" value="$v.id"}selected=""{/eq}>{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">分类名称<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="title" lay-verify="required" autocomplete="off" placeholder="请输入分类名称" lay-reqText="请输入分类名称" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">排序</td>
|
||||
<td>
|
||||
<input type="text" name="sort" placeholder="请输入排序,数字" value="0" autocomplete="off" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">描述</td>
|
||||
<td colspan="5"><textarea name="desc" placeholder="请输入描述,可空" class="layui-textarea"></textarea></td>
|
||||
</tr>
|
||||
</table>
|
||||
{else/}
|
||||
<table class="layui-table">
|
||||
<tr>
|
||||
<td class="layui-td-gray">父级分类<font>*</font></td>
|
||||
<td>
|
||||
<select name="pid" lay-verify="required" lay-reqText="请选择父级分类">
|
||||
<option value="0">作为顶级分类</option>
|
||||
{volist name="$cates" id="v"}
|
||||
<option value="{$v.id}" {eq name="$detail.pid" value="$v.id"}selected=""{/eq}>{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">分类名称<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="title" value="{$detail.title}" lay-verify="required" autocomplete="off" placeholder="请输入分类名称" lay-reqText="请输入分类名称" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">排序</td>
|
||||
<td>
|
||||
<input type="text" name="sort" value="{$detail.sort}" placeholder="请输入排序,数字" value="0" autocomplete="off" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">描述</td>
|
||||
<td colspan="5"><textarea name="desc" placeholder="请输入描述,可空" class="layui-textarea">{$detail.desc}</textarea></td>
|
||||
</tr>
|
||||
</table>
|
||||
{/eq}
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="id" value="{$id}">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool;
|
||||
//监听提交
|
||||
form.on('submit(webform)', function(data){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose(1000);
|
||||
}
|
||||
}
|
||||
tool.post("/article/cate/cate_add", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,212 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">新增知识文章</h3>
|
||||
<table class="layui-table">
|
||||
<tr>
|
||||
<td class="layui-td-gray">文章标题<font>*</font></td>
|
||||
<td colspan="3"><input type="text" name="title" lay-verify="required" lay-reqText="请输入文章标题" autocomplete="off" placeholder="请输入文章标题"
|
||||
class="layui-input"></td>
|
||||
<td class="layui-td-gray">文章分类<font>*</font></td>
|
||||
<td>
|
||||
<select name="cate_id" lay-verify="required" lay-reqText="请选择分类">
|
||||
<option value="">请选择分类</option>
|
||||
{volist name=":set_recursion(article_cate())" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">关键字<font>*</font></td>
|
||||
<td colspan="3">
|
||||
<input type="text" id="keyword_name" name="keyword_names" autocomplete="off" lay-verify="required" lay-reqText="请选择关键字" placeholder="请选择关键字"
|
||||
class="layui-input" readonly>
|
||||
<input type="hidden" id="keyword_id" name="keyword_ids" autocomplete="off">
|
||||
</td>
|
||||
<td class="layui-td-gray">属性</td>
|
||||
<td>
|
||||
<select name="type">
|
||||
<option value="">请选择属性</option>
|
||||
<option value="1">精华</option>
|
||||
<option value="2">热门</option>
|
||||
<option value="3">推荐</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">共享设置</td>
|
||||
<td>
|
||||
<input type="radio" name="is_share" lay-filter="type" value="0" title="私有">
|
||||
<input type="radio" name="is_share" lay-filter="type" value="1" title="所有人" checked>
|
||||
<input type="radio" name="is_share" lay-filter="type" value="2" title="部门">
|
||||
<input type="radio" name="is_share" lay-filter="type" value="3" title="部分人员">
|
||||
</td>
|
||||
<td class="layui-td-gray" style="width:50px">状态</td>
|
||||
<td>
|
||||
<input type="radio" name="status" value="1" title="正常" checked>
|
||||
<input type="radio" name="status" value="0" title="下架">
|
||||
</td>
|
||||
<td class="layui-td-gray">排序</td>
|
||||
<td>
|
||||
<input type="text" name="sort" value="0" placeholder="请输入排序,数字" autocomplete="off" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="depament" style="display:none">
|
||||
<td class="layui-td-gray">共享部门<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<input type="text" name="share_depaments" value="" placeholder="请选择共享部门" readonly class="layui-input picker-depaments">
|
||||
<input type="hidden" name="share_dids" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="person" style="display:none">
|
||||
<td class="layui-td-gray">共享人员<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<input type="text" name="share_names" value="" placeholder="请选择共享人员" readonly class="layui-input picker-more">
|
||||
<input type="hidden" name="share_uids" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">
|
||||
<div class="layui-input-inline">关联附件</div>
|
||||
<div class="layui-input-inline">
|
||||
<button type="button" class="layui-btn layui-btn-xs" id="uploadBtn"><i class="layui-icon"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="5" style="line-height:inherit">
|
||||
<div class="layui-row" id="fileBox">
|
||||
<input type="hidden" data-type="file" name="file_ids" value="">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top;">文章摘要</td>
|
||||
<td colspan="3">
|
||||
<textarea name="desc" placeholder="请输入摘要,不能超过200个字" class="layui-textarea"></textarea>
|
||||
</td>
|
||||
<td class="layui-td-gray" style="vertical-align:top;">缩略图</td>
|
||||
<td>
|
||||
<div class="layui-upload">
|
||||
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" id="test1">缩略图(尺寸:640x360)</button>
|
||||
<div class="layui-upload-list" id="demo1" style="width: 120px; height:66px; overflow: hidden;">
|
||||
<img src="" style="max-width: 100%; height:66px;" />
|
||||
<input type="hidden" name="thumb" value="">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top;">文章内容<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<textarea name="content" placeholder="请输入内容" class="layui-textarea" id="container" style="border:0;padding:0"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="pt-3">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','employeepicker','oaTool','tagpicker','tinymce'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,oaTool = layui.oaTool, tagspicker = layui.tagpicker, upload = layui.upload;
|
||||
|
||||
//选择共享类型
|
||||
form.on('radio(type)', function (data) {
|
||||
if(data.value==2){
|
||||
$('#person').hide();
|
||||
$('#depament').show();
|
||||
}
|
||||
else if(data.value==3){
|
||||
$('#person').show();
|
||||
$('#depament').hide();
|
||||
}
|
||||
else{
|
||||
$('#person').hide();
|
||||
$('#depament').hide();
|
||||
}
|
||||
});
|
||||
|
||||
//编辑器初始化
|
||||
var editor = layui.tinymce;
|
||||
var edit = editor.render({
|
||||
selector: "#container",
|
||||
menubar:false,
|
||||
images_upload_url: '/api/index/upload/sourse/tinymce',//图片上传接口
|
||||
height: 500
|
||||
});
|
||||
|
||||
//相关附件上传
|
||||
oaTool.addFile();
|
||||
|
||||
//tag选择
|
||||
var tags = new tagspicker({
|
||||
'url': "/api/index/get_keyword_cate",
|
||||
'target': 'keyword_name',
|
||||
'tag_ids': 'keyword_id',
|
||||
'tag_tags': 'keyword_name',
|
||||
'height': 500,
|
||||
'isDiy': 1
|
||||
});
|
||||
|
||||
//封面上传
|
||||
var uploadInst = upload.render({
|
||||
elem: '#test1'
|
||||
, url: "/api/index/upload"
|
||||
, done: function (res) {
|
||||
layer.msg(res.msg);
|
||||
if (res.code == 0) {
|
||||
//上传成功
|
||||
$('#demo1 input').attr('value', res.data.id);
|
||||
$('#demo1 img').attr('src', res.data.filepath);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
data.field.content = tinyMCE.editors['container'].getContent();
|
||||
if (data.field.content == '') {
|
||||
layer.msg('请先完善文章的内容');
|
||||
return false;
|
||||
}
|
||||
if(data.field.is_share == 0 || data.field.is_share == 1){
|
||||
data.field.share_dids = '';
|
||||
data.field.share_uids = '';
|
||||
}
|
||||
else if(data.field.is_share == 2){
|
||||
data.field.share_uids = '';
|
||||
if(data.field.share_dids==''){
|
||||
layer.msg('请先选择共享的部门');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(data.field.is_share == 3){
|
||||
data.field.share_dids = '';
|
||||
if(data.field.share_uids==''){
|
||||
layer.msg('请先选择共享的员工');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose(1000);
|
||||
}
|
||||
}
|
||||
tool.post("/article/index/add", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,221 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">编辑知识文章</h3>
|
||||
<table class="layui-table">
|
||||
<tr>
|
||||
<td class="layui-td-gray">文章标题<font>*</font></td>
|
||||
<td colspan="3"><input type="text" name="title" lay-verify="required" lay-reqText="请输入文章标题" autocomplete="off" placeholder="请输入文章标题"
|
||||
class="layui-input" value="{$article.title}"></td>
|
||||
<td class="layui-td-gray">文章分类<font>*</font></td>
|
||||
<td>
|
||||
<select name="cate_id" lay-verify="required" lay-reqText="请选择分类">
|
||||
<option value="">请选择分类</option>
|
||||
{volist name=":set_recursion(article_cate())" id="v"}
|
||||
<option value="{$v.id}" {eq name="$article.cate_id" value="$v.id" }selected{/eq}>{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">关键字<font>*</font></td>
|
||||
<td colspan="3">
|
||||
<input type="text" id="keyword_name" name="keyword_names" autocomplete="off" lay-verify="required" lay-reqText="请选择关键字" placeholder="请选择关键字"
|
||||
class="layui-input" value="{$article.keyword_names}" readonly>
|
||||
<input type="hidden" id="keyword_id" name="keywords_id" autocomplete="off" value="{$article.keyword_ids}">
|
||||
</td>
|
||||
<td class="layui-td-gray">属性</td>
|
||||
<td>
|
||||
<select name="type">
|
||||
<option value="">请选择属性</option>
|
||||
<option value="1" {eq name="$article.type" value="1" }selected{/eq}>精华</option>
|
||||
<option value="2" {eq name="$article.type" value="2" }selected{/eq}>热门</option>
|
||||
<option value="3" {eq name="$article.type" value="3" }selected{/eq}>推荐</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">是否共享<font>*</font></td>
|
||||
<td>
|
||||
<input type="radio" name="is_share" lay-filter="type" value="0" title="私有" {eq name="$article.is_share" value="0" }checked{/eq}>
|
||||
<input type="radio" name="is_share" lay-filter="type" value="1" title="所有人" {eq name="$article.is_share" value="1" }checked{/eq}>
|
||||
<input type="radio" name="is_share" lay-filter="type" value="2" title="部门" {eq name="$article.is_share" value="2" }checked{/eq}>
|
||||
<input type="radio" name="is_share" lay-filter="type" value="3" title="部分人员" {eq name="$article.is_share" value="3" }checked{/eq}>
|
||||
</td>
|
||||
<td class="layui-td-gray" style="width:50px">状态</td>
|
||||
<td>
|
||||
<input type="radio" name="status" value="1" title="正常" {eq name="$article.status" value="1" }checked{/eq}>
|
||||
<input type="radio" name="status" value="0" title="下架" {eq name="$article.status" value="0" }checked{/eq}>
|
||||
</td>
|
||||
<td class="layui-td-gray">排序</td>
|
||||
<td>
|
||||
<input type="text" name="sort" placeholder="请输入排序,数字" autocomplete="off" class="layui-input" value="{$article.sort}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="depament" style="{$article.is_share == 2?'':'display:none'}">
|
||||
<td class="layui-td-gray">共享部门<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<input type="text" name="share_depaments" value="{$article.share_depaments}" placeholder="请选择共享部门" readonly class="layui-input picker-depaments">
|
||||
<input type="hidden" name="share_dids" value="{$article.share_dids}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="person" style="{$article.is_share == 3?'':'display:none'}">
|
||||
<td class="layui-td-gray">共享人员<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<input type="text" name="share_names" value="{$article.share_names}" placeholder="请选择共享人员" readonly class="layui-input picker-more">
|
||||
<input type="hidden" name="share_uids" value="{$article.share_uids}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">
|
||||
<div class="layui-input-inline">关联附件</div>
|
||||
<div class="layui-input-inline">
|
||||
<button type="button" class="layui-btn layui-btn-xs" id="uploadBtn"><i class="layui-icon"></i></button>
|
||||
</div>
|
||||
</td>
|
||||
<td colspan="5" style="line-height:inherit">
|
||||
<div class="layui-row" id="fileBox">
|
||||
<input type="hidden" data-type="file" name="file_ids" value="{$article.file_ids}">
|
||||
{notempty name="$article.file_ids"}
|
||||
{volist name="$article.fileArray" id="vo"}
|
||||
<div class="layui-col-md4" id="uploadImg{$vo.id}">{:file_card($vo)}</div>
|
||||
{/volist}
|
||||
{/notempty}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top;">文章摘要</td>
|
||||
<td colspan="3">
|
||||
<textarea name="desc" placeholder="请输入摘要,不能超过200个字" class="layui-textarea">{$article.desc}</textarea>
|
||||
</td>
|
||||
<td class="layui-td-gray" style="vertical-align:top;">缩略图</td>
|
||||
<td>
|
||||
<div class="layui-upload">
|
||||
<button type="button" class="layui-btn layui-btn-normal layui-btn-sm" id="test1">缩略图(尺寸:640x360)</button>
|
||||
<div class="layui-upload-list" id="demo1" style="width: 120px; height:66px; overflow: hidden;">
|
||||
<img src="{:get_file($article.thumb)}" style="max-width: 100%; height:66px;" />
|
||||
<input type="hidden" name="thumb" value="{$article.thumb}">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top;">文章内容<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<textarea name="content" placeholder="请输入内容" class="layui-textarea" id="container" lay-verify="required" lay-reqText="请完善文章内容"
|
||||
style="border:0;padding:0">{$article.content}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="pt-3">
|
||||
<input type="hidden" name="id" value="{$article.id}">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','employeepicker','oaTool','tagpicker','tinymce'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,oaTool = layui.oaTool, tagspicker = layui.tagpicker, upload = layui.upload;
|
||||
|
||||
//选择共享类型
|
||||
form.on('radio(type)', function (data) {
|
||||
if(data.value==2){
|
||||
$('#person').hide();
|
||||
$('#depament').show();
|
||||
}
|
||||
else if(data.value==3){
|
||||
$('#person').show();
|
||||
$('#depament').hide();
|
||||
}
|
||||
else{
|
||||
$('#person').hide();
|
||||
$('#depament').hide();
|
||||
}
|
||||
});
|
||||
|
||||
//编辑器初始化
|
||||
var editor = layui.tinymce;
|
||||
var edit = editor.render({
|
||||
selector: "#container",
|
||||
menubar:false,
|
||||
images_upload_url: '/api/index/upload/sourse/tinymce',//图片上传接口
|
||||
height: 500
|
||||
});
|
||||
|
||||
//相关附件上传
|
||||
oaTool.addFile();
|
||||
|
||||
//tag选择
|
||||
var tags = new tagspicker({
|
||||
'url': "/api/index/get_keyword_cate",
|
||||
'target': 'keyword_name',
|
||||
'tag_ids': 'keyword_id',
|
||||
'tag_tags': 'keyword_name',
|
||||
'height': 500,
|
||||
'isDiy': 1
|
||||
});
|
||||
|
||||
//封面上传
|
||||
var uploadInst = upload.render({
|
||||
elem: '#test1',
|
||||
url: "/api/index/upload",
|
||||
done: function (res) {
|
||||
layer.msg(res.msg);
|
||||
if (res.code == 0) {
|
||||
//上传成功
|
||||
$('#demo1 input').attr('value', res.data.id);
|
||||
$('#demo1 img').attr('src', res.data.filepath);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
data.field.content = tinyMCE.editors['container'].getContent();
|
||||
if (data.field.content == '') {
|
||||
layer.msg('请先完善文章的内容');
|
||||
return false;
|
||||
}
|
||||
|
||||
if(data.field.is_share == 0 || data.field.is_share == 1){
|
||||
data.field.share_dids = '';
|
||||
data.field.share_uids = '';
|
||||
}
|
||||
else if(data.field.is_share == 2){
|
||||
data.field.share_uids = '';
|
||||
if(data.field.share_dids==''){
|
||||
layer.msg('请先选择共享的部门');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if(data.field.is_share == 3){
|
||||
data.field.share_dids = '';
|
||||
if(data.field.share_uids==''){
|
||||
layer.msg('请先选择共享的员工');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose(1000);
|
||||
}
|
||||
}
|
||||
tool.post("/article/index/add", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,84 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<form class="layui-form gg-form-bar border-x border-t">
|
||||
<div class="layui-input-inline">
|
||||
<select name="cate_id">
|
||||
<option value="">请选择知识文章分类</option>
|
||||
{volist name=":set_recursion(article_cate())" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:300px;">
|
||||
<input type="text" name="keywords" placeholder="标题/分类/描述/内容" class="layui-input" autocomplete="off" />
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="table-search"><i class="layui-icon layui-icon-search mr-1"></i>搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-reset" lay-filter="table-search-reset">清空</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="barDemo">
|
||||
<div class="layui-btn-group"><span class="layui-btn layui-btn-normal layui-btn-xs" lay-event="view">查看</span></div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','tablePlus'];
|
||||
function gouguInit() {
|
||||
var table = layui.tablePlus, tool = layui.tool ,form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test',
|
||||
title: '文章列表',
|
||||
url: "/article/index/index", //数据接口
|
||||
cols: [
|
||||
[ //表头
|
||||
{
|
||||
field: 'id',
|
||||
title: '编号',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'sort',
|
||||
title: '排序',
|
||||
align: 'center',
|
||||
width: 66
|
||||
}, {
|
||||
field: 'cate_title',
|
||||
title: '分类',
|
||||
align: 'center',
|
||||
width: 120
|
||||
}, {
|
||||
field: 'title',
|
||||
title: '文章标题',
|
||||
templet: '<div><a data-href="/article/index/view/id/{{d.id}}.html" class="side-a">{{d.title}}</a></div>'
|
||||
},{
|
||||
field: 'read',
|
||||
title: '阅读量',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'user',
|
||||
title: '发布人',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'department',
|
||||
title: '部门',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,148 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<form class="layui-form gg-form-bar border-x border-t">
|
||||
<div class="layui-input-inline">
|
||||
<select name="cate_id">
|
||||
<option value="">请选择知识文章分类</option>
|
||||
{volist name=":set_recursion(article_cate())" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:300px;">
|
||||
<input type="text" name="keywords" placeholder="标题/分类/描述/内容" class="layui-input" autocomplete="off" />
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="table-search"><i class="layui-icon layui-icon-search mr-1"></i>搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-reset" lay-filter="table-search-reset">清空</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="status">
|
||||
<i class="layui-icon {{# if(d.status == 1){ }}layui-icon-ok{{# } else { }}layui-icon-close{{# } }}"></i>
|
||||
</script>
|
||||
<script type="text/html" id="is_share">
|
||||
<i class="layui-icon {{# if(d.is_share == 0){ }}layui-icon-close{{# } else { }}layui-icon-ok{{# } }}"></i>
|
||||
</script>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<span class="layui-btn layui-btn-normal layui-btn-sm" title="添加文章" lay-event="add">+ 添加知识文章</span>
|
||||
</div>
|
||||
</script>
|
||||
<script type="text/html" id="barDemo">
|
||||
<div class="layui-btn-group"><span class="layui-btn layui-btn-xs" lay-event="edit">编辑</span><span class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</span></div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','tablePlus'];
|
||||
function gouguInit() {
|
||||
var table = layui.tablePlus, tool = layui.tool ,form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test',
|
||||
title: '文章列表',
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar:false,
|
||||
url: "/article/index/list", //数据接口
|
||||
cols: [
|
||||
[ //表头
|
||||
{
|
||||
field: 'id',
|
||||
title: '编号',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'sort',
|
||||
title: '排序',
|
||||
align: 'center',
|
||||
width: 66
|
||||
}, {
|
||||
field: 'cate_title',
|
||||
title: '分类',
|
||||
align: 'center',
|
||||
width: 120
|
||||
}, {
|
||||
field: 'title',
|
||||
title: '文章标题',
|
||||
templet: '<div><a data-href="/article/index/view/id/{{d.id}}.html" class="side-a">{{d.title}}</a></div>'
|
||||
},{
|
||||
field: 'read',
|
||||
title: '阅读量',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'status',
|
||||
title: '状态',
|
||||
toolbar: '#status',
|
||||
align: 'center',
|
||||
width: 66
|
||||
}, {
|
||||
field: 'is_share',
|
||||
title: '阅读权限范围',
|
||||
align: 'center',
|
||||
width: 100,
|
||||
templet: function(d){
|
||||
let html='<span class="green">私有</span>';
|
||||
if(d.is_share==1){
|
||||
html='<span class="blue">所有人</span>';
|
||||
}
|
||||
else if(d.is_share==2){
|
||||
html='<span class="yellow">部门</span>';
|
||||
}
|
||||
else if(d.is_share==3){
|
||||
html='<span class="red">部分人员</span>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
}, {
|
||||
field: 'right',
|
||||
title: '操作',
|
||||
toolbar: '#barDemo',
|
||||
width: 100,
|
||||
align: 'center'
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
//表头工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
if (obj.event === 'add') {
|
||||
tool.side("/article/index/add");
|
||||
return;
|
||||
}
|
||||
});
|
||||
//监听行工具事件
|
||||
table.on('tool(test)', function(obj) {
|
||||
var data = obj.data;
|
||||
if(obj.event === 'edit'){
|
||||
tool.side('/article/index/add?id='+data.id);
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'del') {
|
||||
layer.confirm('确定要删除吗?', {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function(index) {
|
||||
let callback = function (res) {
|
||||
layer.msg(res.msg);
|
||||
if (res.code == 0) {
|
||||
obj.del();
|
||||
}
|
||||
}
|
||||
tool.delete("/article/index/delete", {id: data.id}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,134 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
{block name="style"}
|
||||
<link rel="stylesheet" href="{__GOUGU__}/third_party/prism/prism.css"/>
|
||||
<style>
|
||||
.text-detial-ops{line-height: 30px; color:#999; font-size: 12px; padding: 12px 0;}
|
||||
.text-detial-ops span{margin-right: 20px;}
|
||||
.text-detial-ops a{margin-right:10px;}
|
||||
.text-detial-content{padding: 8px 0; color:#333; word-break: break-all; border-top:1px solid #e8e8e8;font-size: 16px!important; line-height: 1.72!important;}
|
||||
.text-detial-content p{padding: 8px 0;}
|
||||
.text-detial-content img{max-width:98%!important; margin:0 auto; display:block; border: 1px solid #e6e6e6; -webkit-box-shadow: 0 2px 6px rgba(26,26,26,.08); box-shadow: 0 2px 6px rgba(26,26,26,.08); border-radius: 4px;}
|
||||
.text-detial-content h1,.text-detial-content h2,.text-detial-content h3,.text-detial-content h4,.text-detial-content h5{margin-top:10px;}
|
||||
.text-detial-content a{color:#186AF2; font-style:italic;}
|
||||
.text-detial-content a:hover{text-decoration:underline;}
|
||||
|
||||
.text-detial-content p code,.blog-detial-content pre{margin:0 3px;font-size: 14px; font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; background: #f6f6f6; padding: 10px; border-radius: 2px;}
|
||||
.text-detial-content p code{border: 1px solid #eee;padding: 2px 4px;}
|
||||
.text-detial-content table {border-collapse: collapse; border-spacing: 0; display: block; width: 100%; overflow: auto; word-break: normal;word-break: keep-all; margin-top: 0;margin-bottom: 16px;}
|
||||
.text-detial-content table tr {background-color: #fff;border-top: 1px solid #ccc;}
|
||||
.text-detial-content table tr:nth-child(2n) {background-color: #f8f8f8;}
|
||||
.text-detial-content table td, .blog-detial-content table th { padding: 6px 12px;border: 1px solid #ddd; font-size:14px; }
|
||||
.text-detial-content table th {font-weight: 800;}
|
||||
.text-detial-content li {list-style: initial;margin-left: 20px;}
|
||||
:not(pre)>code[class*=language-], pre[class*=language-]{background:#fff!important;border:1px solid #e8e8e8!important; border-radius:3px;}
|
||||
|
||||
.comment-input .comment-image{width:40px; height:40px; border-radius:50%}
|
||||
.comment-item .comment-avatar{width:50px; float:left}
|
||||
.comment-item .comment-image{width:36px; height:36px; border-radius:50%}
|
||||
.comment-item .comment-body{margin-left:50px;}
|
||||
.comment-item .comment-content blockquote{border-left:3px solid #f1f1f1; padding:4px 8px;}
|
||||
.comment-item .comment-actions a{color:#8c95a8; cursor:pointer; font-size:12px;}
|
||||
.comment-item .comment-actions a:hover{color:#3582fb;}
|
||||
</style>
|
||||
{/block}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-4">
|
||||
<h1>{$detail.title}</h1>
|
||||
<div class="text-detial-ops">
|
||||
<span>发表于:{$detail.create_time | date='Y-m-d H:i:s'}</span>
|
||||
<span>发布人:{$detail.user}</span>
|
||||
<span>部门:{$detail.department}</span>
|
||||
<span>分类:{$detail.cate_title}</span>
|
||||
</div>
|
||||
<div class="text-detial-content">
|
||||
{$detail.content|raw}
|
||||
</div>
|
||||
{notempty name="$detail.file_ids"}
|
||||
<h3 class="py-3">相关附件</h3>
|
||||
<div class="layui-row" id="fileBox">
|
||||
{volist name="$detail.fileArray" id="vo"}
|
||||
<div class="layui-col-md4" id="uploadImg{$vo.id}">{:file_card($vo,'view')}</div>
|
||||
{/volist}
|
||||
</div>
|
||||
{/notempty}
|
||||
</div>
|
||||
<div class="px-4" id="commentBox">
|
||||
<h3 class="py-3">相关评论</h3>
|
||||
{volist name="$detail.comment" id="vo"}
|
||||
<div class="pt-3">
|
||||
<div class="comment-item py-3 border-t">
|
||||
<div class="comment-avatar" title="{vo.name}">
|
||||
<img src="{$vo.thumb}" alt="{vo.name}" class="comment-image">
|
||||
</div>
|
||||
<div class="comment-body">
|
||||
<div class="comment-meta">
|
||||
<strong class="comment-name">{$vo.name}</strong><span class="ml-2 gray">{$vo.create_time}{$vo.update_time}</span>
|
||||
{eq name="$vo.admin_id" value="$login_admin.id"}
|
||||
<button class="layui-btn layui-btn-xs layui-btn-danger layui-del" data-cid="{$vo.id}">删除</button>
|
||||
{/eq}
|
||||
</div>
|
||||
<div class="comment-content py-2">{$vo.content}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/volist}
|
||||
|
||||
<form class="layui-form">
|
||||
<textarea name="content" placeholder="请输入内容" class="layui-textarea" id="container"></textarea>
|
||||
<input type="hidden" name="article_id" value="{$detail.id}">
|
||||
<div class="py-3">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">提交评论</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script src="{__GOUGU__}/third_party/prism/prism.js"></script>
|
||||
<script>
|
||||
const moduleInit = ['tool','oaTool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool;
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
if (data.field.content == '') {
|
||||
layer.msg('请先输入评论内容');
|
||||
return false;
|
||||
}
|
||||
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
setTimeout(function () {
|
||||
location.reload();
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
tool.post("/article/api/add_comment", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
$('#commentBox').on('click','.layui-del', function () {
|
||||
let cid =$(this).data('cid');
|
||||
layer.confirm('确定要删除该评论吗?', { icon: 3, title: '提示' }, function (index) {
|
||||
let callback = function (e) {
|
||||
layer.closeAll();
|
||||
layer.msg(e.msg);
|
||||
if(e.code==0){
|
||||
setTimeout(function () {
|
||||
location.reload();
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
let postData = { "id": cid };
|
||||
tool.delete("/article/api/delete_comment", postData, callback);
|
||||
});
|
||||
})
|
||||
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,145 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\base;
|
||||
|
||||
use think\App;
|
||||
use think\exception\HttpResponseException;
|
||||
use think\facade\Cache;
|
||||
use think\facade\Db;
|
||||
use think\facade\Request;
|
||||
use think\facade\Session;
|
||||
use think\facade\View;
|
||||
use systematic\Systematic;
|
||||
|
||||
/**
|
||||
* 控制器基础类
|
||||
*/
|
||||
abstract class BaseController
|
||||
{
|
||||
/**
|
||||
* Request实例
|
||||
* @var \think\Request
|
||||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* 应用实例
|
||||
* @var \think\App
|
||||
*/
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
* 是否批量验证
|
||||
* @var bool
|
||||
*/
|
||||
protected $batchValidate = false;
|
||||
|
||||
/**
|
||||
* 控制器中间件
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [];
|
||||
|
||||
/**
|
||||
* 构造方法
|
||||
* @access public
|
||||
* @param App $app 应用对象
|
||||
*/
|
||||
public function __construct(App $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->request = $this->app->request;
|
||||
$this->module = strtolower(app('http')->getName());
|
||||
$this->controller = strtolower($this->request->controller());
|
||||
$this->action = strtolower($this->request->action());
|
||||
$this->uid = 0;
|
||||
$this->did = 0;
|
||||
$this->pid = 0;
|
||||
// 控制器初始化
|
||||
$this->initialize();
|
||||
}
|
||||
// 初始化
|
||||
protected function initialize()
|
||||
{
|
||||
// 检测权限
|
||||
$this->checkLogin();
|
||||
}
|
||||
|
||||
/**
|
||||
*验证用户登录
|
||||
*/
|
||||
protected function checkLogin()
|
||||
{
|
||||
if ($this->controller !== 'login' && $this->controller !== 'captcha') {
|
||||
$session_admin = get_config('app.session_admin');
|
||||
if (!Session::has($session_admin)) {
|
||||
if ($this->request->isAjax()) {
|
||||
return to_assign(404, '请先登录');
|
||||
} else {
|
||||
redirect('/home/login/index.html')->send();
|
||||
exit;
|
||||
}
|
||||
} else {
|
||||
$this->uid = Session::get($session_admin);
|
||||
$login_admin = Db::name('Admin')->where(['id' => $this->uid])->find();
|
||||
$this->did = $login_admin['did'];
|
||||
$this->pid = $login_admin['position_id'];
|
||||
View::assign('login_admin', $login_admin);
|
||||
$is_lock = $login_admin['is_lock'];
|
||||
if($is_lock==1){
|
||||
redirect('/home/login/lock.html')->send();
|
||||
exit;
|
||||
}
|
||||
// 验证用户访问权限
|
||||
if (($this->module == 'api') || ($this->module == 'message') || ($this->module == 'home' && $this->controller == 'index')) {
|
||||
return true;
|
||||
}
|
||||
else{
|
||||
$reg_pwd = $login_admin['reg_pwd'];
|
||||
if($reg_pwd!==''){
|
||||
redirect('/home/index/edit_password.html')->send();
|
||||
exit;
|
||||
}
|
||||
if (!$this->checkAuth()) {
|
||||
if ($this->request->isAjax()) {
|
||||
return to_assign(405, '你没有权限,请联系管理员或者HR');
|
||||
} else {
|
||||
echo '<div style="text-align:center;color:red;margin-top:20%;">你没有权限访问,请联系管理员或者人事部</div>';exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证用户访问权限
|
||||
* @DateTime 2020-12-21
|
||||
* @param string $controller 当前访问控制器
|
||||
* @param string $action 当前访问方法
|
||||
* @return [type]
|
||||
*/
|
||||
protected function checkAuth()
|
||||
{
|
||||
//Cache::delete('RulesSrc' . $uid);
|
||||
$uid = $this->uid;
|
||||
$GOUGU = new Systematic();
|
||||
$GOUGU->auth($uid);
|
||||
$auth_list_all = Cache::get('RulesSrc0');
|
||||
$auth_list = Cache::get('RulesSrc' . $uid);
|
||||
|
||||
$pathUrl = $this->module . '/' . $this->controller . '/' . $this->action;
|
||||
if (!in_array($pathUrl, $auth_list)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="renderer" content="webkit"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
{block name="meta"}
|
||||
<link rel="mobile-prefetch" href=""/>
|
||||
{/block}
|
||||
{block name="title"}
|
||||
<title>{:get_system_config('web','admin_title')}</title>
|
||||
{/block}
|
||||
{block name="keywords"}
|
||||
<meta name="keywords" content="{:get_system_config('web','keywords')}"/>
|
||||
<meta name="description" content="{:get_system_config('web','desc')}"/>
|
||||
{/block}
|
||||
{block name="css"}
|
||||
<link rel="stylesheet" href="{__GOUGU__}/gougu/css/gougu.css?v={:get_system_config('web','version')}" media="all">
|
||||
{/block}
|
||||
{block name="style"}{/block}
|
||||
<script>
|
||||
const login_admin={$login_admin.id};
|
||||
</script>
|
||||
{block name="js"}{/block}
|
||||
</head>
|
||||
<body class="main-body">
|
||||
<!-- 主体 -->
|
||||
{block name="body"}{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 底部 -->
|
||||
{block name="footer"}{/block}
|
||||
<!-- /底部 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}{/block}
|
||||
<!-- /脚本 -->
|
||||
<script src="{__GOUGU__}/layui/layui.js"></script>
|
||||
<script src="{__GOUGU__}/gougu/gouguInit.js"></script>
|
||||
<!-- 统计代码 -->
|
||||
{block name="code"}{/block}
|
||||
<!-- /统计代码 -->
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>找不到模板</title>
|
||||
<style type="text/css">
|
||||
html,body {width: 100%;height: 100%;background: #f7f7f7;margin: 0;padding: 0;border: 0;}
|
||||
div,p {margin: 0;padding: 0;border: 0;}
|
||||
.container {width: 100%;height: 100%;position: fixed;top: 0;left: 0;z-index: 999;overflow: hidden;}
|
||||
.info {width: 480px;position: absolute;top: 50%;left: 50%;margin-top: -200px;margin-left: -240px;text-align:center;}
|
||||
.info-status{width: 480px; display: -webkit-flex;display: flex;flex-direction: row;justify-content: space-between;align-items: center;flex-wrap: nowrap;}
|
||||
.info-status div{width:180px; height:180px; line-height:180px; font-size:180px; font-weight:200; color:#F35F37}
|
||||
.info-status div.face{font-size:60px; border:9px solid #F35F37; width:120px; height:120px; line-height:118px; background-color:#fff; border-radius:50%;}
|
||||
.info-tips{font-size:24px;color:#F35F37; padding-top:32px; font-weight:600;}
|
||||
.info-text{padding-top:20px; line-height:1.6; text-align:left; font-size:14px; color:#646464}
|
||||
.footer {position: absolute;font-size: 12px;bottom: 28px;text-align: center;width: 100%;color: #969696;}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="info">
|
||||
<div class="info-status">
|
||||
<div>4</div><div class="face">😔</div><div>6</div>
|
||||
</div>
|
||||
<div class="info-tips">哎呀!找不到模板文件</div>
|
||||
<div class="info-text">{$file | default=""}模板不存在,请检查对应的目录文件,注意区分大小写!</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© 2022 gougucms.com GPL-3.0 license,Powered by 勾股OA
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="renderer" content="webkit" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<title>你没有权限</title>
|
||||
<style type="text/css">
|
||||
html,body {width: 100%;height: 100%;background: #f7f7f7;margin: 0;padding: 0;border: 0;}
|
||||
div,p {margin: 0;padding: 0;border: 0;}
|
||||
.container {width: 100%;height: 100%;position: fixed;top: 0;left: 0;z-index: 999;overflow: hidden;}
|
||||
.info {width: 480px;position: absolute;top: 50%;left: 50%;margin-top: -200px;margin-left: -240px;text-align:center;}
|
||||
.info-status{width: 480px; display: -webkit-flex;display: flex;flex-direction: row;justify-content: space-between;align-items: center;flex-wrap: nowrap;}
|
||||
.info-status div{width:180px; height:180px; line-height:180px; font-size:180px; font-weight:200; color:#F35F37}
|
||||
.info-status div.face{font-size:60px; border:9px solid #F35F37; width:120px; height:120px; line-height:118px; background-color:#fff; border-radius:50%;}
|
||||
.info-tips{font-size:24px;color:#F35F37; padding-top:32px; font-weight:600;}
|
||||
.info-text{padding-top:20px; line-height:1.6; text-align:left; font-size:14px; color:#646464}
|
||||
.footer {position: absolute;font-size: 12px;bottom: 28px;text-align: center;width: 100%;color: #969696;}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="info">
|
||||
<div class="info-status">
|
||||
<div>4</div><div class="face">😔</div><div>6</div>
|
||||
</div>
|
||||
<div class="info-tips">哎呀!你没有权限,请联系管理员或者HR!</div>
|
||||
</div>
|
||||
<div class="footer">
|
||||
© 2022 gougucms.com GPL-3.0 license,Powered by 勾股OA
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
/**
|
||||
======================
|
||||
*模块数据获取公共文件
|
||||
======================
|
||||
*/
|
||||
use think\facade\Db;
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\business\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Analysis extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
// 这是系统自动生成的event定义文件
|
||||
return [
|
||||
|
||||
];
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
//开启session中间件
|
||||
//'think\middleware\SessionInit',
|
||||
//验证勾股OA是否完成安装
|
||||
\app\home\middleware\Install::class,
|
||||
];
|
|
@ -0,0 +1,431 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
|
||||
{block name="style"}
|
||||
<style type="text/css">
|
||||
/* 这段样式只是用于演示 */
|
||||
.layui-card-header span {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
}
|
||||
.layui-sales {
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
color: rgba(0,0,0,.85);
|
||||
font-size: 30px;
|
||||
}
|
||||
|
||||
.layui-sales-info {
|
||||
padding-top: 16px;
|
||||
color: rgba(0,0,0,.65);
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
fieldset.layui-field-title {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
{/block}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<div class="layui-row layui-col-space15">
|
||||
<div class="layui-col-xs6 layui-col-md3">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">报销售额</div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-sales">¥ 126,560</div>
|
||||
<div class="layui-sales-info" style="height: 125px;">
|
||||
周同比 <span>12%</span>
|
||||
<i class="layui-edge layui-edge-top" style="border-bottom-color: green"></i>
|
||||
日同比 <span>3%</span>
|
||||
<i class="layui-edge layui-edge-bottom" style="border-top-color: red"></i>
|
||||
<fieldset class="layui-elem-field layui-field-title"></fieldset>
|
||||
<div>日销报销 ¥12,423</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6 layui-col-md3">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">发票总数 <span class="layui-badge layui-badge-blue pull-right">月</span></div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-sales">6,560</div>
|
||||
<div class="layui-sales-info" >
|
||||
<div id="zfbs" style="height: 80px;"></div>
|
||||
<fieldset class="layui-elem-field layui-field-title"></fieldset>
|
||||
<div>总发票数 1,234</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6 layui-col-md3">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">访问量 <span class="layui-badge layui-badge-green pull-right">日</span></div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-sales">6,560</div>
|
||||
<div class="layui-sales-info" >
|
||||
<div id="fwl" style="height: 80px;"></div>
|
||||
<fieldset class="layui-elem-field layui-field-title" ></fieldset>
|
||||
<div>日访问量 1,234</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6 layui-col-md3">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">业绩效果 <span class="layui-badge layui-badge-red pull-right">周</span></div>
|
||||
<div class="layui-card-body">
|
||||
<div class="layui-sales">83%</div>
|
||||
<div class="layui-sales-info" >
|
||||
<div style="height: 80px;">
|
||||
<div class="layui-progress layui-progress-big">
|
||||
<div class="layui-progress-bar layui-bg-blue" lay-percent="83%" style="width: 83%;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<fieldset class="layui-elem-field layui-field-title" style="position: relative;"></fieldset>
|
||||
<div>回款金额 ¥ 12,234</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="layui-col-xs6 layui-col-md9">
|
||||
<div class="layui-card">
|
||||
<div class="layui-card-header">地域分布</div>
|
||||
<div class="layui-card-body">
|
||||
<div id="map" style="height: 578px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="layui-col-xs6 layui-col-md3">
|
||||
<div class="layui-card" >
|
||||
<div class="layui-card-header">在线人数</div>
|
||||
<div class="layui-card-body">
|
||||
<div id="zxrs" style="height: 250px" ></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layui-col-xs6 layui-col-md3">
|
||||
<div class="layui-card" >
|
||||
<div class="layui-card-header">浏览器分布</div>
|
||||
<div class="layui-card-body">
|
||||
<div id="llq" style="height: 250px" ></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script src="{__GOUGU__}/third_party/echart/echarts.min.js"></script>
|
||||
<script src="{__GOUGU__}/third_party/echart/china.js"></script>
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool;
|
||||
}
|
||||
|
||||
// 访问量
|
||||
var fwlCharts = echarts.init(document.getElementById('fwl'));
|
||||
var fwlOptions = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'cross',
|
||||
label: {
|
||||
backgroundColor: '#6a7985'
|
||||
}
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '-1%',
|
||||
right: '0',
|
||||
bottom: '0',
|
||||
top: '5px',
|
||||
containLabel: false
|
||||
},
|
||||
xAxis: [
|
||||
{
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
|
||||
show: false
|
||||
}
|
||||
],
|
||||
yAxis: [
|
||||
{
|
||||
type: 'value',
|
||||
show: false
|
||||
}
|
||||
],
|
||||
series: [
|
||||
{
|
||||
name: '总量',
|
||||
type: 'line',
|
||||
stack: '总量',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
width: 0
|
||||
},
|
||||
showSymbol: false,
|
||||
areaStyle: {
|
||||
opacity: 0.8,
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
|
||||
offset: 0,
|
||||
color: '#1890ff'
|
||||
}, {
|
||||
offset: 1,
|
||||
color: '#1890ff'
|
||||
}])
|
||||
},
|
||||
emphasis: {
|
||||
focus: 'series'
|
||||
},
|
||||
data: [120, 132, 156, 200, 90, 100, 165]
|
||||
},
|
||||
]
|
||||
};
|
||||
|
||||
fwlCharts.setOption(fwlOptions);
|
||||
|
||||
// 渲染表信息
|
||||
var zfbsCharts = echarts.init(document.getElementById('zfbs'));
|
||||
|
||||
var zfbsOptions = {
|
||||
color: ['#1890ff','#666'],
|
||||
tooltip: {},
|
||||
grid: {
|
||||
left: '0',
|
||||
right: '20',
|
||||
bottom: '30',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
data: ['1月', '2月', '3月', '4月', '6月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
|
||||
show:false,
|
||||
},
|
||||
yAxis: {
|
||||
show:false
|
||||
},
|
||||
series: [{
|
||||
type: 'bar',
|
||||
data: [726, 1013, 690, 892, 982, 570, 536, 546, 988, 1002, 500, 506],
|
||||
barMaxWidth: 45
|
||||
}]
|
||||
}
|
||||
|
||||
zfbsCharts.setOption(zfbsOptions);
|
||||
|
||||
|
||||
// 地图数据信息
|
||||
function randomValue() {
|
||||
return Math.round(Math.random()*1000);
|
||||
}
|
||||
var mapCharts = echarts.init(document.getElementById('map'));
|
||||
|
||||
var dataList=[
|
||||
{name:"南海诸岛",value:0},
|
||||
{name: '北京', value: randomValue()},
|
||||
{name: '天津', value: randomValue()},
|
||||
{name: '上海', value: randomValue()},
|
||||
{name: '重庆', value: randomValue()},
|
||||
{name: '河北', value: randomValue()},
|
||||
{name: '河南', value: randomValue()},
|
||||
{name: '云南', value: randomValue()},
|
||||
{name: '辽宁', value: randomValue()},
|
||||
{name: '黑龙江', value: randomValue()},
|
||||
{name: '湖南', value: randomValue()},
|
||||
{name: '安徽', value: randomValue()},
|
||||
{name: '山东', value: randomValue()},
|
||||
{name: '新疆', value: randomValue()},
|
||||
{name: '江苏', value: randomValue()},
|
||||
{name: '浙江', value: randomValue()},
|
||||
{name: '江西', value: randomValue()},
|
||||
{name: '湖北', value: randomValue()},
|
||||
{name: '广西', value: randomValue()},
|
||||
{name: '甘肃', value: randomValue()},
|
||||
{name: '山西', value: randomValue()},
|
||||
{name: '内蒙古', value: randomValue()},
|
||||
{name: '陕西', value: randomValue()},
|
||||
{name: '吉林', value: randomValue()},
|
||||
{name: '福建', value: randomValue()},
|
||||
{name: '贵州', value: randomValue()},
|
||||
{name: '广东', value: randomValue()},
|
||||
{name: '青海', value: randomValue()},
|
||||
{name: '西藏', value: randomValue()},
|
||||
{name: '四川', value: randomValue()},
|
||||
{name: '宁夏', value: randomValue()},
|
||||
{name: '海南', value: randomValue()},
|
||||
{name: '台湾', value: randomValue()},
|
||||
{name: '香港', value: randomValue()},
|
||||
{name: '澳门', value: randomValue()}
|
||||
]
|
||||
|
||||
// 世界地图
|
||||
var mapOption = {
|
||||
tooltip: {
|
||||
formatter:function(params,ticket, callback){
|
||||
return params.seriesName+'<br />'+params.name+':'+params.value
|
||||
}
|
||||
},
|
||||
visualMap: {
|
||||
min: 0,
|
||||
max: 1500,
|
||||
left: 'left',
|
||||
top: 'bottom',
|
||||
text: ['高','低'],//取值范围的文字
|
||||
inRange: {
|
||||
color: ['#e0ffff', '#006edd']//取值范围的颜色
|
||||
},
|
||||
show: true//图注
|
||||
},
|
||||
geo: {
|
||||
map: 'china',
|
||||
roam: false, //不开启缩放和平移
|
||||
zoom:1.23, //视角缩放比例
|
||||
label: {
|
||||
normal: {
|
||||
show: true,
|
||||
fontSize:'10',
|
||||
color: 'rgba(0,0,0,0.7)'
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal:{
|
||||
borderColor: 'rgba(0, 0, 0, 0.2)'
|
||||
},
|
||||
emphasis:{
|
||||
areaColor: '#F3B329',//鼠标选择区域颜色
|
||||
shadowOffsetX: 0,
|
||||
shadowOffsetY: 0,
|
||||
shadowBlur: 20,
|
||||
borderWidth: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
}
|
||||
}
|
||||
},
|
||||
series : [
|
||||
{
|
||||
name: '信息量',
|
||||
type: 'map',
|
||||
geoIndex: 0,
|
||||
data:dataList
|
||||
}
|
||||
]
|
||||
};
|
||||
mapCharts.setOption(mapOption);
|
||||
|
||||
|
||||
var myCharts = echarts.init(document.getElementById('zxrs'));
|
||||
var mData = [50, 100, 150, 80, 120, 150, 200, 250, 220, 250, 300, 350, 400, 380, 440, 450, 500, 550, 500];
|
||||
var option = {
|
||||
|
||||
|
||||
tooltip: {
|
||||
trigger: "axis"
|
||||
},
|
||||
xAxis: [{
|
||||
type: "category",
|
||||
boundaryGap: !1,
|
||||
data: ["06:00", "06:30", "07:00", "07:30", "08:00", "08:30", "09:00", "09:30", "10:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00"]
|
||||
}],
|
||||
yAxis: [{
|
||||
type: "value"
|
||||
}],
|
||||
series: [{
|
||||
name: "总量",
|
||||
type: "line",
|
||||
smooth: !0,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
areaStyle: {
|
||||
type: "default"
|
||||
}
|
||||
}
|
||||
},
|
||||
data: mData
|
||||
}]
|
||||
};
|
||||
myCharts.setOption(option);
|
||||
|
||||
// 动态改变图表1数据
|
||||
setInterval(function () {
|
||||
for (var i = 0; i < mData.length; i++) {
|
||||
mData[i] += (Math.random() * 50 - 25);
|
||||
if (mData[i] < 0) {
|
||||
mData[i] = 0;
|
||||
}
|
||||
}
|
||||
myCharts.setOption({
|
||||
series: [{
|
||||
data: mData
|
||||
}]
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
// 渲染浏览器分布
|
||||
var llqCharts = echarts.init(document.getElementById('llq'));
|
||||
var llqOptions = {
|
||||
tooltip: {
|
||||
trigger: 'item'
|
||||
},
|
||||
legend: {
|
||||
bottom: '1%',
|
||||
left: 'center',
|
||||
icon: 'circle', // 设置小圆点
|
||||
itemWidth: 10, // 设置宽度
|
||||
itemHeight: 10, // 设置高度
|
||||
},
|
||||
|
||||
series: [
|
||||
{
|
||||
name: '浏览器分布',
|
||||
type: 'pie',
|
||||
radius: ['40%', '70%'],
|
||||
avoidLabelOverlap: false,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'center'
|
||||
},
|
||||
emphasis: {
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: '14px',
|
||||
}
|
||||
},
|
||||
labelLine: {
|
||||
show: false
|
||||
},
|
||||
data: [
|
||||
{value: 1048, name: 'Chrome'},
|
||||
{value: 735, name: 'Safair'},
|
||||
{value: 580, name: 'Firefox'},
|
||||
{value: 484, name: 'Edge'},
|
||||
{value: 300, name: 'IE'},
|
||||
{value: 200, name: 'Other'},
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
llqCharts.setOption(llqOptions);
|
||||
|
||||
// 窗口大小改变事件
|
||||
window.onresize = function () {
|
||||
myCharts.resize();
|
||||
|
||||
mapCharts.resize();
|
||||
fwlCharts.resize();
|
||||
zfbsCharts.resize();
|
||||
llqCharts.resize();
|
||||
};
|
||||
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
/**
|
||||
======================
|
||||
*模块数据获取公共文件
|
||||
======================
|
||||
*/
|
||||
use think\facade\Db;
|
||||
|
||||
//是否是合同管理员权限
|
||||
function contract_auth($uid)
|
||||
{
|
||||
if($uid == 1){
|
||||
return 1;
|
||||
}
|
||||
$map = [];
|
||||
$map[] = ['name', '=', 'contract_admin'];
|
||||
$map[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',uids)")];
|
||||
$count = Db::name('DataAuth')->where($map)->count();
|
||||
return $count;
|
||||
}
|
||||
//读取分类列表
|
||||
function contract_cate()
|
||||
{
|
||||
$cate = Db::name('ContractCate')->where(['status' => 1])->order('id desc')->select()->toArray();
|
||||
return $cate;
|
||||
}
|
||||
|
||||
//读取签约主体
|
||||
function contract_subject()
|
||||
{
|
||||
$subject = Db::name('InvoiceSubject')->where(['status' => 1])->order('id desc')->select()->toArray();
|
||||
return $subject;
|
||||
}
|
||||
|
||||
//写入日志
|
||||
function to_log($uid,$new,$old)
|
||||
{
|
||||
$log_data = [];
|
||||
$key_array = ['id', 'create_time', 'update_time', 'sign_did'];
|
||||
foreach ($new as $key => $value) {
|
||||
if (!in_array($key, $key_array)) {
|
||||
if(isset($old[$key]) && ($old[$key]!=$value)){
|
||||
$log_data[] = array(
|
||||
'field' => $key,
|
||||
'contract_id' => $new['id'],
|
||||
'admin_id' => $uid,
|
||||
'old_content' => $old[$key],
|
||||
'new_content' => $value,
|
||||
'create_time' => time(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insertAll($log_data);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
勾股OA模块安装鉴定文件,请勿删除!!!!!此次模块标识为:contract
|
|
@ -0,0 +1,111 @@
|
|||
-- ----------------------------
|
||||
-- Table structure for oa_contract_cate
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_contract_cate`;
|
||||
CREATE TABLE `oa_contract_cate` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '合同类别名称',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '合同类别';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_contract_cate
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_contract_cate` VALUES (1, '销售合同', 1, 1637987189, 0);
|
||||
INSERT INTO `oa_contract_cate` VALUES (2, '采购合同', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_contract_cate` VALUES (3, '租赁合同', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_contract_cate` VALUES (4, '委托协议', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_contract_cate` VALUES (5, '代理协议', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_contract_cate` VALUES (6, '其他合同', 1, 1637987199, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_contract
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_contract`;
|
||||
CREATE TABLE `oa_contract` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`pid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '父协议id',
|
||||
`code` varchar(255) NOT NULL DEFAULT '' COMMENT '合同编号',
|
||||
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '合同名称',
|
||||
`cate_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '分类id',
|
||||
`type` tinyint(1) NOT NULL DEFAULT 0 COMMENT '合同性质:0未设置,1普通合同、2框架合同、3补充协议、4其他合同',
|
||||
`subject_id` varchar(255) NOT NULL DEFAULT '' COMMENT '签约主体',
|
||||
`customer_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联客户ID,预设数据',
|
||||
`customer` varchar(255) NOT NULL DEFAULT '' COMMENT '客户名称',
|
||||
`customer_name` varchar(255) NOT NULL DEFAULT '' COMMENT '客户代表',
|
||||
`customer_mobile` varchar(255) NOT NULL DEFAULT '' COMMENT '客户电话',
|
||||
`customer_address` varchar(255) NOT NULL DEFAULT '' COMMENT '客户地址',
|
||||
`start_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同开始时间',
|
||||
`end_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同结束时间',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`prepared_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同制定人',
|
||||
`sign_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同签订人',
|
||||
`keeper_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同保管人',
|
||||
`share_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '共享人员,如:1,2,3',
|
||||
`sign_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同签订时间',
|
||||
`sign_did` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '合同签订部门',
|
||||
`cost` decimal(15, 2) NOT NULL DEFAULT 0.00 COMMENT '合同金额',
|
||||
`is_tax` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否含税:0未含税,1含税',
|
||||
`tax` decimal(15, 2) NOT NULL DEFAULT 0.00 COMMENT '税点',
|
||||
`check_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '合同状态:0待审核,1审核中,2审核通过,3审核不通过,4撤销审核,5已中止,6已作废',
|
||||
`check_step_sort` int(11) NOT NULL DEFAULT 0 COMMENT '当前审批步骤',
|
||||
`check_admin_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '当前审批人ID,如:1,2,3',
|
||||
`flow_admin_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '历史审批人ID,如:1,2,3',
|
||||
`last_admin_id` varchar(200) NOT NULL DEFAULT '0' COMMENT '上一审批人',
|
||||
`copy_uids` varchar(500) NOT NULL DEFAULT '' COMMENT '抄送人ID,如:1,2,3',
|
||||
`check_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '审核人',
|
||||
`check_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '审核时间',
|
||||
`check_remark` text NULL COMMENT '审核备注信息',
|
||||
`stop_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '中止人',
|
||||
`stop_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '中止时间',
|
||||
`stop_remark` text NULL COMMENT '中止备注信息',
|
||||
`void_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '作废人',
|
||||
`void_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '作废时间',
|
||||
`void_remark` text NULL COMMENT '作废备注信息',
|
||||
`archive_status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '归档状态:0未归档,1已归档',
|
||||
`archive_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '归档人',
|
||||
`archive_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '归档时间',
|
||||
`remark` text NULL COMMENT '备注信息',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1000 CHARACTER SET = utf8mb4 COMMENT = '合同表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_contract_file
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_contract_file`;
|
||||
CREATE TABLE `oa_contract_file` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`contract_id` int(11) UNSIGNED NOT NULL COMMENT '关联合同id',
|
||||
`file_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '相关联附件id',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '合同附件关联表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_contract_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_contract_log`;
|
||||
CREATE TABLE `oa_contract_log` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`action` varchar(100) NOT NULL DEFAULT 'edit' COMMENT '动作:add,edit,del,check,upload',
|
||||
`field` varchar(100) NOT NULL DEFAULT '' COMMENT '字段',
|
||||
`contract_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联合同id',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作人',
|
||||
`old_content` text NULL COMMENT '修改前的内容',
|
||||
`new_content` text NULL COMMENT '修改后的内容',
|
||||
`remark` text NULL COMMENT '补充备注',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '合同操作记录表';
|
||||
|
||||
|
||||
INSERT INTO `oa_data_auth` VALUES ((SELECT MAX(id) +1 FROM `oa_data_auth` a), '合同管理员','contract_admin','拥有该权限的员工可以查看、编辑、作废、中止所有合同。', 'contract', '',1,1,0,'','','',1656143065, 0);
|
|
@ -0,0 +1,272 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\contract\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use app\contract\model\ContractLog;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Api extends BaseController
|
||||
{
|
||||
//获取合同协议
|
||||
public function get_contract()
|
||||
{
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['id|name', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
$where[] = ['delete_time', '=', 0];
|
||||
$where[] = ['check_status', '=', 2];
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'contract_admin');
|
||||
if($auth==0){
|
||||
$whereOr[] =['admin_id|prepared_uid|sign_uid|keeper_uid', '=', $uid];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',share_ids)")];
|
||||
$dids = get_department_role($this->uid);
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['sign_did', 'in', $dids];
|
||||
}
|
||||
}
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$list = Db::name('Contract')
|
||||
->field('id,name,code,customer_id,sign_uid,sign_time')
|
||||
->order('id desc')
|
||||
->where($where)
|
||||
->where(function ($query) use($whereOr) {
|
||||
$query->whereOr($whereOr);
|
||||
})
|
||||
->paginate($rows, false)->each(function($item, $key){
|
||||
$item['sign_name'] = Db::name('Admin')->where('id',$item['sign_uid'])->value('name');
|
||||
$item['sign_time'] = date('Y-m-d', $item['sign_time']);
|
||||
$item['customer'] = Db::name('Customer')->where('id',$item['customer_id'])->value('name');
|
||||
return $item;
|
||||
});
|
||||
table_assign(0, '', $list);
|
||||
}
|
||||
|
||||
//添加附件
|
||||
public function add_file()
|
||||
{
|
||||
$param = get_params();
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$fid = Db::name('ContractFile')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($fid) {
|
||||
$log_data = array(
|
||||
'field' => 'file',
|
||||
'action' => 'upload',
|
||||
'contract_id' => $param['contract_id'],
|
||||
'admin_id' => $param['admin_id'],
|
||||
'old_content' => '',
|
||||
'new_content' => $param['file_name'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, '上传成功', $fid);
|
||||
}
|
||||
}
|
||||
|
||||
//删除
|
||||
public function delete_file()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$id = get_params("id");
|
||||
$data['id'] = $id;
|
||||
$data['delete_time'] = time();
|
||||
if (Db::name('ContractFile')->update($data) !== false) {
|
||||
$detail = Db::name('ContractFile')->where('id', $id)->find();
|
||||
$file_name = Db::name('File')->where('id', $detail['file_id'])->value('name');
|
||||
$log_data = array(
|
||||
'field' => 'file',
|
||||
'action' => 'delete',
|
||||
'contract_id' => $detail['contract_id'],
|
||||
'admin_id' => $this->uid,
|
||||
'new_content' => $file_name,
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "删除成功");
|
||||
} else {
|
||||
return to_assign(1, "删除失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//状态改变等操作
|
||||
public function check()
|
||||
{
|
||||
if (request()->isPost()) {
|
||||
$param = get_params();
|
||||
if($param['check_status'] == 0){
|
||||
$param['check_step_sort'] = 0;
|
||||
}
|
||||
if($param['check_status'] == 1){
|
||||
$check_admin_ids = isset($param['check_admin_ids'])?$param['check_admin_ids']:'';
|
||||
$flow_data = set_flow($param['flow_id'],$check_admin_ids,$this->uid);
|
||||
$param['check_admin_ids'] = $flow_data['check_admin_ids'];
|
||||
$flow = $flow_data['flow'];
|
||||
$check_type = $flow_data['check_type'];
|
||||
//删除原来的审核流程和审核记录
|
||||
Db::name('FlowStep')->where(['action_id'=>$param['id'],'type'=>4,'delete_time'=>0])->update(['delete_time'=>time()]);
|
||||
Db::name('FlowRecord')->where(['action_id'=>$param['id'],'type'=>4,'delete_time'=>0])->update(['delete_time'=>time()]);
|
||||
if($check_type == 2){
|
||||
$flow_step = array(
|
||||
'action_id' => $param['id'],
|
||||
'type' => 4,
|
||||
'flow_uids' => $param['check_admin_ids'],
|
||||
'create_time' => time()
|
||||
);
|
||||
//增加审核流程
|
||||
Db::name('FlowStep')->strict(false)->field(true)->insertGetId($flow_step);
|
||||
}
|
||||
else{
|
||||
foreach ($flow as $key => &$value){
|
||||
$value['action_id'] = $param['id'];
|
||||
$value['sort'] = $key;
|
||||
$value['type'] = 4;
|
||||
$value['create_time'] = time();
|
||||
}
|
||||
//增加审核流程
|
||||
Db::name('FlowStep')->strict(false)->field(true)->insertAll($flow);
|
||||
}
|
||||
$checkData=array(
|
||||
'action_id' => $param['id'],
|
||||
'step_id' => 0,
|
||||
'check_user_id' => $this->uid,
|
||||
'type' => 4,
|
||||
'check_time' => time(),
|
||||
'status' => 0,
|
||||
'content' => '提交申请',
|
||||
'create_time' => time()
|
||||
);
|
||||
$aid = Db::name('FlowRecord')->strict(false)->field(true)->insertGetId($checkData);
|
||||
//发送消息通知
|
||||
$msg=[
|
||||
'from_uid'=>$this->uid,
|
||||
'title'=>'合同',
|
||||
'action_id'=>$param['id']
|
||||
];
|
||||
$users = $param['check_admin_ids'];
|
||||
sendMessage($users,51,$msg);
|
||||
}
|
||||
if($param['check_status'] == 3){
|
||||
$param['check_uid'] = $this->uid;
|
||||
$param['check_time'] = time();
|
||||
$param['check_remark'] = $param['mark'];
|
||||
}
|
||||
if($param['check_status'] == 5){
|
||||
$param['stop_uid'] = $this->uid;
|
||||
$param['stop_time'] = time();
|
||||
$param['stop_remark'] = $param['mark'];
|
||||
}
|
||||
if($param['check_status'] == 6){
|
||||
$param['void_uid'] = $this->uid;
|
||||
$param['void_time'] = time();
|
||||
$param['void_remark'] = $param['mark'];
|
||||
}
|
||||
$old = Db::name('Contract')->where('id', $param['id'])->find();
|
||||
if (Db::name('Contract')->strict(false)->update($param) !== false) {
|
||||
$log_data = array(
|
||||
'field' => 'check_status',
|
||||
'contract_id' => $param['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'new_content' => $param['check_status'],
|
||||
'old_content' => $old['check_status'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "操作成功");
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//归档等操作
|
||||
public function archive()
|
||||
{
|
||||
if (request()->isPost()) {
|
||||
$param = get_params();
|
||||
$old = 1;
|
||||
if($param['archive_status'] == 1){
|
||||
$param['archive_uid'] = $this->uid;
|
||||
$param['archive_time'] = time();
|
||||
$old = 0;
|
||||
}
|
||||
$old = Db::name('Contract')->where('id', $param['id'])->find();
|
||||
if (Db::name('Contract')->strict(false)->update($param) !== false) {
|
||||
$log_data = array(
|
||||
'field' => 'archive_status',
|
||||
'contract_id' => $param['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'new_content' => $param['archive_status'],
|
||||
'old_content' => $old['archive_status'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "操作成功");
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//合同操作日志列表
|
||||
public function contract_log()
|
||||
{
|
||||
$param = get_params();
|
||||
$list = new ContractLog();
|
||||
$content = $list->contract_log($param);
|
||||
return to_assign(0, '', $content);
|
||||
}
|
||||
|
||||
//获取客户列表
|
||||
public function get_customer()
|
||||
{
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['id|name', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
$where[] = ['delete_time', '=', 0];
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'customer_admin');
|
||||
$dids = get_department_role($this->uid);
|
||||
if($auth==0){
|
||||
$whereOr[] =['belong_uid', '=', $uid];
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['belong_did', 'in', $dids];
|
||||
}
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',share_ids)")];
|
||||
}
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$list = Db::name('Customer')->field('id,name,address')->order('id asc')->where($where)->paginate($rows, false)->each(function($item, $key){
|
||||
$contact = Db::name('CustomerContact')->where(['cid'=>$item['id'],'is_default'=>1])->find();
|
||||
if(!empty($contact)){
|
||||
$item['contact_name'] = $contact['name'];
|
||||
$item['contact_mobile'] = $contact['mobile'];
|
||||
}
|
||||
else{
|
||||
$item['contact_name'] = '';
|
||||
$item['contact_mobile'] = '';
|
||||
}
|
||||
return $item;
|
||||
});
|
||||
table_assign(0, '', $list);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\contract\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\contract\validate\ContractCateCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Cate extends BaseController
|
||||
{
|
||||
//类别
|
||||
public function cate()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('ContractCate')->order('create_time asc')->select();
|
||||
return to_assign(0, '', $cate);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//类别添加
|
||||
public function cate_add()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(ContractCateCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('ContractCate')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(ContractCateCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('ContractCate')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//类别设置
|
||||
public function cate_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$res = Db::name('ContractCate')->strict(false)->field('id,status')->update($param);
|
||||
if ($res) {
|
||||
if($param['status'] == 0){
|
||||
add_log('disable', $param['id'], $param);
|
||||
}
|
||||
else if($param['status'] == 1){
|
||||
add_log('recovery', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(0, '操作失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,334 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\contract\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\contract\model\Contract as ContractList;
|
||||
use app\contract\validate\ContractCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Index extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.name|c.title', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['cate_id'])) {
|
||||
$where[] = ['a.cate_id', '=', $param['cate_id']];
|
||||
}
|
||||
if (!empty($param['type'])) {
|
||||
$where[] = ['a.type', '=', $param['type']];
|
||||
}
|
||||
if (isset($param['check_status']) && $param['check_status']!='') {
|
||||
$where[] = ['a.check_status', '=', $param['check_status']];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
$where[] = ['a.archive_status', '=', 0];
|
||||
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'contract_admin');
|
||||
if($auth==0){
|
||||
$whereOr[] =['a.admin_id|a.prepared_uid|a.sign_uid|a.keeper_uid', '=', $uid];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.share_ids)")];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.check_admin_ids)")];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.flow_admin_ids)")];
|
||||
$dids = get_department_role($this->uid);
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['a.sign_did', 'in', $dids];
|
||||
}
|
||||
}
|
||||
|
||||
$model = new ContractList();
|
||||
$list = $model->get_list($param, $where, $whereOr);
|
||||
return table_assign(0, '', $list);
|
||||
} else {
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'contract_admin');
|
||||
View::assign('auth', $auth);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
public function archive()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.name|c.title', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['cate_id'])) {
|
||||
$where[] = ['a.cate_id', '=', $param['cate_id']];
|
||||
}
|
||||
if (!empty($param['cate_id'])) {
|
||||
$where[] = ['a.cate_id', '=', $param['cate_id']];
|
||||
}
|
||||
if (!empty($param['type'])) {
|
||||
$where[] = ['a.type', '=', $param['type']];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
$where[] = ['a.archive_status', '=', 1];
|
||||
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'contract_admin');
|
||||
if($auth==0){
|
||||
$whereOr[] =['a.admin_id|a.prepared_uid|a.sign_uid|a.keeper_uid', '=', $uid];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.share_ids)")];
|
||||
$dids = get_department_role($this->uid);
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['a.sign_did', 'in', $dids];
|
||||
}
|
||||
}
|
||||
$model = new ContractList();
|
||||
$list = $model->get_list($param, $where, $whereOr);
|
||||
return table_assign(0, '', $list);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//添加&&编辑
|
||||
public function add()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if (isset($param['sign_time'])) {
|
||||
$param['sign_time'] = strtotime($param['sign_time']);
|
||||
}
|
||||
if (isset($param['start_time'])) {
|
||||
$param['start_time'] = strtotime($param['start_time']);
|
||||
}
|
||||
if (isset($param['end_time'])) {
|
||||
$param['end_time'] = strtotime($param['end_time']);
|
||||
if ($param['end_time'] <= $param['start_time']) {
|
||||
return to_assign(1, "结束时间需要大于开始时间");
|
||||
}
|
||||
}
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(ContractCheck::class)->scene($param['scene'])->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$old = Db::name('Contract')->where(['id' => $param['id']])->find();
|
||||
$auth = isAuth($this->uid,'contract_admin');
|
||||
if($old['check_status'] == 0 || $old['check_status'] == 4){
|
||||
if($this->uid!=$old['admin_id'] && $auth==0){
|
||||
return to_assign(1, "只有录入人员和合同管理员有权限操作");
|
||||
}
|
||||
$res = contractList::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
to_log($this->uid,$param,$old);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
}
|
||||
else{
|
||||
return to_assign(1, "当前状态不允许编辑");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
validate(ContractCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$aid = ContractList::strict(false)->field(true)->insertGetId($param);
|
||||
if ($aid) {
|
||||
add_log('add', $aid, $param);
|
||||
$log_data = array(
|
||||
'field' => 'new',
|
||||
'action' => 'add',
|
||||
'contract_id' => $aid,
|
||||
'admin_id' => $param['admin_id'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
$type = isset($param['type']) ? $param['type'] : 0;
|
||||
$pid = isset($param['pid']) ? $param['pid'] : 0;
|
||||
$is_customer = Db::name('DataAuth')->where('name','contract_admin')->value('expected_1');
|
||||
$is_codeno = Db::name('DataAuth')->where('name','contract_admin')->value('expected_2');
|
||||
$codeno='';
|
||||
if($is_codeno==1){
|
||||
$codeno = get_codeno(1);
|
||||
}
|
||||
View::assign('is_customer', $is_customer);
|
||||
View::assign('codeno', $codeno);
|
||||
View::assign('id', $id);
|
||||
View::assign('type', $type);
|
||||
View::assign('pid', $pid);
|
||||
View::assign('auth', isAuth($this->uid,'contract_admin'));
|
||||
if ($id > 0) {
|
||||
$detail = (new ContractList())->detail($id);
|
||||
if($detail['check_status'] == 0 || $detail['check_status'] == 4){
|
||||
View::assign('detail', $detail);
|
||||
return view('edit');
|
||||
}
|
||||
else{
|
||||
echo '<div style="text-align:center;color:red;margin-top:20%;">当前状态不开放编辑,请联系合同管理员</div>';exit;
|
||||
}
|
||||
}
|
||||
if($pid>0){
|
||||
$p_contract = Db::name('Contract')->where(['id' => $pid])->find();
|
||||
View::assign('p_contract', $p_contract);
|
||||
}
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//查看
|
||||
public function view()
|
||||
{
|
||||
$id = get_params("id");
|
||||
$detail = (new ContractList())->detail($id);
|
||||
$auth = isAuth($this->uid,'contract_admin');
|
||||
$is_check_admin = 0;
|
||||
$is_create_admin = 0;
|
||||
$check_record = [];
|
||||
if($auth==0){
|
||||
$auth_array=[];
|
||||
if(!empty($detail['share_ids'])){
|
||||
$share_ids = explode(",",$detail['share_ids']);
|
||||
$auth_array = array_merge($auth_array,$share_ids);
|
||||
}
|
||||
if(!empty($detail['check_admin_ids'])){
|
||||
$check_admin_ids = explode(",",$detail['check_admin_ids']);
|
||||
$auth_array = array_merge($auth_array,$check_admin_ids);
|
||||
}
|
||||
if(!empty($detail['flow_admin_ids'])){
|
||||
$flow_admin_ids = explode(",",$detail['flow_admin_ids']);
|
||||
$auth_array = array_merge($auth_array,$flow_admin_ids);
|
||||
}
|
||||
array_push($auth_array,$detail['admin_id'],$detail['prepared_uid'],$detail['sign_uid'],$detail['keeper_uid']);
|
||||
//部门负责人
|
||||
$dids = get_department_role($this->uid);
|
||||
if(!in_array($this->uid,$auth_array) && !in_array($detail['sign_did'],$dids)){
|
||||
return view('../../base/view/common/roletemplate');
|
||||
}
|
||||
}
|
||||
|
||||
$detail['create_user'] = Db::name('Admin')->where(['id' => $detail['admin_id']])->value('name');
|
||||
|
||||
$detail['copy_user'] = '-';
|
||||
if($detail['copy_uids'] !=''){
|
||||
$copy_user = Db::name('Admin')->where('id','in',$detail['copy_uids'])->column('name');
|
||||
$detail['copy_user'] = implode(',',$copy_user);
|
||||
}
|
||||
|
||||
if($detail['check_status']==1){
|
||||
$flows = Db::name('FlowStep')->where(['action_id'=>$detail['id'],'type'=>4,'sort'=>$detail['check_step_sort'],'delete_time'=>0])->find();
|
||||
$flow_check = get_flow($this->uid,$flows);
|
||||
$detail['check_user'] = $flow_check['check_user'];
|
||||
$check_user_ids = $flow_check['check_user_ids'];
|
||||
if(in_array($this->uid,$check_user_ids)){
|
||||
$is_check_admin = 1;
|
||||
if($flows['flow_type'] == 4){
|
||||
$check_count = Db::name('FlowRecord')->where(['action_id'=>$detail['id'],'type'=>4,'step_id'=>$flows['id'],'check_user_id'=>$this->uid])->count();
|
||||
if($check_count>0){
|
||||
$is_check_admin = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
//获取合同审批流程
|
||||
$flows = get_type_department_flows(8,$this->did);
|
||||
$detail['check_user'] = '-';
|
||||
}
|
||||
|
||||
if($detail['admin_id'] == $this->uid){
|
||||
$is_create_admin = 1;
|
||||
}
|
||||
|
||||
$file_array_other = Db::name('ContractFile')
|
||||
->field('cf.id,f.filepath,f.name,f.filesize,f.fileext,f.create_time,f.admin_id')
|
||||
->alias('cf')
|
||||
->join('File f', 'f.id = cf.file_id', 'LEFT')
|
||||
->order('cf.create_time asc')
|
||||
->where(array('cf.contract_id' => $id, 'cf.delete_time' => 0))
|
||||
->select()->toArray();
|
||||
$detail['file_array_other'] = $file_array_other;
|
||||
|
||||
$check_record = Db::name('FlowRecord')->field('f.*,a.name,a.thumb')
|
||||
->alias('f')
|
||||
->join('Admin a', 'a.id = f.check_user_id', 'left')
|
||||
->where(['f.action_id'=>$detail['id'],'f.type'=>4])
|
||||
->order('check_time asc')
|
||||
->select()->toArray();
|
||||
foreach ($check_record as $kk => &$vv) {
|
||||
$vv['check_time_str'] = date('Y-m-d H:i', $vv['check_time']);
|
||||
$vv['status_str'] = '提交';
|
||||
if($vv['status'] == 1){
|
||||
$vv['status_str'] = '审核通过';
|
||||
}
|
||||
else if($vv['status'] == 2){
|
||||
$vv['status_str'] = '审核拒绝';
|
||||
}
|
||||
if($vv['status'] == 3){
|
||||
$vv['status_str'] = '撤销';
|
||||
}
|
||||
}
|
||||
|
||||
View::assign('is_check_admin', $is_check_admin);
|
||||
View::assign('is_create_admin', $is_create_admin);
|
||||
View::assign('check_record', $check_record);
|
||||
View::assign('flows', $flows);
|
||||
View::assign('auth', $auth);
|
||||
View::assign('detail', $detail);
|
||||
return view();
|
||||
}
|
||||
//删除
|
||||
public function delete()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$id = get_params("id");
|
||||
$data['id'] = $id;
|
||||
$data['delete_time'] = time();
|
||||
if (Db::name('Contract')->update($data) !== false) {
|
||||
add_log('delete', $id);
|
||||
$log_data = array(
|
||||
'field' => 'del',
|
||||
'action' => 'delete',
|
||||
'contract_id' => $id,
|
||||
'admin_id' => $this->uid,
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('ContractLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "删除成功");
|
||||
} else {
|
||||
return to_assign(1, "删除失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
// 这是系统自动生成的event定义文件
|
||||
return [
|
||||
|
||||
];
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
//开启session中间件
|
||||
//'think\middleware\SessionInit',
|
||||
//验证勾股OA是否完成安装
|
||||
\app\home\middleware\Install::class,
|
||||
];
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\contract\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class Contract extends Model
|
||||
{
|
||||
const ZERO = 0;
|
||||
const ONE = 1;
|
||||
const TWO = 2;
|
||||
const THREE = 3;
|
||||
const FORE = 4;
|
||||
const FIVE = 5;
|
||||
const SIX = 6;
|
||||
|
||||
public static $Type = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '普通合同',
|
||||
self::TWO => '框架合同',
|
||||
self::THREE => '补充协议',
|
||||
self::FORE => '其他合同',
|
||||
];
|
||||
|
||||
public static $Status = [
|
||||
self::ZERO => '待审核',
|
||||
self::ONE => '审核中',
|
||||
self::TWO => '审核通过',
|
||||
self::THREE => '审核拒绝',
|
||||
self::FORE => '已撤销',
|
||||
self::FIVE => '已中止',
|
||||
self::SIX => '已作废',
|
||||
];
|
||||
|
||||
public static $ArchiveStatus = [
|
||||
self::ZERO => '未归档',
|
||||
self::ONE => '已归档',
|
||||
];
|
||||
|
||||
//列表检索
|
||||
public function get_list($param = [], $where = [], $whereOr=[])
|
||||
{
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$list = self::where($where)
|
||||
->where(function ($query) use($whereOr) {
|
||||
$query->whereOr($whereOr);
|
||||
})
|
||||
->field('a.*,a.type as type_a, c.title as cate_title,d.title as sign_department')
|
||||
->alias('a')
|
||||
->join('contract_cate c', 'a.cate_id = c.id')
|
||||
->join('department d', 'a.sign_did = d.id','LEFT')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->keeper_name = Db::name('Admin')->where(['id' => $item->keeper_uid])->value('name');
|
||||
$item->sign_name = Db::name('Admin')->where(['id' => $item->sign_uid])->value('name');
|
||||
$item->sign_time = date('Y-m-d', $item->sign_time);
|
||||
$item->interval_time = date('Y-m-d', $item->start_time) . ' 至 ' . date('Y-m-d', $item->end_time);
|
||||
$item->type_name = self::$Type[(int)$item->type_a];
|
||||
$item->status_name = self::$Status[(int)$item->check_status];
|
||||
$item->delay = countDays(date("Y-m-d"),date('Y-m-d', $item->end_time));
|
||||
if($item->cost == 0){
|
||||
$item->cost = '-';
|
||||
}
|
||||
});
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
// 获取合同详情
|
||||
public function detail($id)
|
||||
{
|
||||
$detail = self::where(['id' => $id])->find();
|
||||
if (!empty($detail)) {
|
||||
$detail['status_name'] = self::$Status[(int) $detail['check_status']];
|
||||
$detail['archive_status_name'] = self::$ArchiveStatus[(int) $detail['archive_status']];
|
||||
$detail['sign_time'] = date('Y-m-d', $detail['sign_time']);
|
||||
$detail['start_time'] = date('Y-m-d', $detail['start_time']);
|
||||
$detail['end_time'] = date('Y-m-d', $detail['end_time']);
|
||||
$detail['cate_title'] = Db::name('ContractCate')->where(['id' => $detail['cate_id']])->value('title');
|
||||
$detail['sign_department'] = Db::name('Department')->where(['id' => $detail['sign_did']])->value('title');
|
||||
$detail['sign_name'] = Db::name('Admin')->where(['id' => $detail['sign_uid']])->value('name');
|
||||
$detail['admin_name'] = Db::name('Admin')->where(['id' => $detail['admin_id']])->value('name');
|
||||
$detail['prepared_name'] = Db::name('Admin')->where(['id' => $detail['prepared_uid']])->value('name');
|
||||
$detail['keeper_name'] = Db::name('Admin')->where(['id' => $detail['keeper_uid']])->value('name');
|
||||
|
||||
$share_names = Db::name('Admin')->where([['id','in',$detail['share_ids']]])->column('name');
|
||||
$detail['share_names'] = implode(',',$share_names);
|
||||
|
||||
//审核信息
|
||||
if($detail['check_uid'] > 0){
|
||||
$detail['check_name'] = Db::name('Admin')->where(['id' => $detail['check_uid']])->value('name');
|
||||
$detail['check_time'] = date('Y-m-d', $detail['check_time']);
|
||||
}
|
||||
//中止信息
|
||||
if($detail['stop_uid'] > 0){
|
||||
$detail['stop_name'] = Db::name('Admin')->where(['id' => $detail['stop_uid']])->value('name');
|
||||
$detail['stop_time'] = date('Y-m-d', $detail['stop_time']);
|
||||
}
|
||||
//作废信息
|
||||
if($detail['void_uid'] > 0){
|
||||
$detail['void_name'] = Db::name('Admin')->where(['id' => $detail['void_uid']])->value('name');
|
||||
$detail['void_time'] = date('Y-m-d', $detail['void_time']);
|
||||
}
|
||||
//归档信息
|
||||
if($detail['archive_status'] == 1){
|
||||
$detail['archive_name'] = Db::name('Admin')->where(['id' => $detail['archive_uid']])->value('name');
|
||||
$detail['archive_time'] = date('Y-m-d', $detail['archive_time']);
|
||||
}
|
||||
|
||||
if($detail['pid']>0){
|
||||
$detail['pname'] = self::where(['id' => $detail['pid']])->value('name');
|
||||
}
|
||||
|
||||
if($detail['file_ids'] !=''){
|
||||
$fileArray = Db::name('File')->where('id','in',$detail['file_ids'])->select();
|
||||
$detail['fileArray'] = $fileArray;
|
||||
}
|
||||
}
|
||||
return $detail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
namespace app\contract\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class ContractLog extends Model
|
||||
{
|
||||
public static $Sourse = [
|
||||
'type' => ['', '未设置', '普通合同', '框架合同', '补充协议', '其他合同'],
|
||||
'check_status' => ['待审核', '审核中', '审核通过', '审核拒绝', '已撤销', '已中止', '已作废'],
|
||||
'action' => [
|
||||
'add' => '添加',
|
||||
'edit' => '修改',
|
||||
'delete' => '删除',
|
||||
'upload' => '上传',
|
||||
],
|
||||
'field_array' => [
|
||||
'code' => '编号',
|
||||
'name' => '名称',
|
||||
'cate_id' => '类别',
|
||||
'type' => '性质',
|
||||
'subject_id' => '签约主体',
|
||||
'customer' => '客户名称',
|
||||
'customer_name' => '客户代表姓名',
|
||||
'customer_mobile' => '客户电话',
|
||||
'customer_address'=> '客户地址',
|
||||
'start_time' => '开始时间',
|
||||
'end_time' => '结束时间',
|
||||
'prepared_uid' => '制定人',
|
||||
'sign_uid' => '签订人',
|
||||
'keeper_uid' => '保管人',
|
||||
'share_ids' => '共享人员',
|
||||
'sign_time' => '签订时间',
|
||||
'cost' => '金额',
|
||||
'is_tax' => '是否含税',
|
||||
'tax' => '税点',
|
||||
'check_status' => '状态',
|
||||
'status' => '状态',
|
||||
'archive_status' => '归档状态',
|
||||
'file_ids' => '合同附件',
|
||||
'file' => '合同附件',
|
||||
'remark' => '备注信息',
|
||||
'new' => '新增',
|
||||
'del' => '删除',
|
||||
]
|
||||
];
|
||||
|
||||
public function contract_log($param = [])
|
||||
{
|
||||
$where = [];
|
||||
$where[] = ['a.contract_id', '=', $param['contract_id']];
|
||||
$page = intval($param['page']);
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = Db::name('ContractLog')
|
||||
->field('a.*,u.name,u.thumb')
|
||||
->alias('a')
|
||||
->join('Admin u', 'u.id = a.admin_id')
|
||||
->order('a.create_time desc')
|
||||
->where($where)
|
||||
->page($page, $rows)
|
||||
->select()->toArray();
|
||||
$data = [];
|
||||
$sourse = self::$Sourse;
|
||||
$field_array = $sourse['field_array'];
|
||||
$action = $sourse['action'];
|
||||
foreach ($content as $k => $v) {
|
||||
if (isset($sourse[$v['field']])) {
|
||||
$v['old_content'] = $sourse[$v['field']][$v['old_content']];
|
||||
$v['new_content'] = $sourse[$v['field']][$v['new_content']];
|
||||
}
|
||||
if (strpos($v['field'], '_time') !== false) {
|
||||
if ($v['old_content'] == '') {
|
||||
$v['old_content'] = '未设置';
|
||||
}
|
||||
$v['new_content'] = date('Y-m-d', (int) $v['new_content']);
|
||||
}
|
||||
if (strpos($v['field'], '_uid') !== false) {
|
||||
$v['old_content'] = Db::name('Admin')->where(['id' => $v['old_content']])->value('name');
|
||||
$v['new_content'] = Db::name('Admin')->where(['id' => $v['new_content']])->value('name');
|
||||
}
|
||||
if ($v['field'] == 'cate_id') {
|
||||
$v['old_content'] = Db::name('ContractCate')->where(['id' => $v['old_content']])->value('title');
|
||||
$v['new_content'] = Db::name('ContractCate')->where(['id' => $v['new_content']])->value('title');
|
||||
}
|
||||
if ($v['field'] == 'subject_id') {
|
||||
$v['old_content'] = Db::name('InvoiceSubject')->where(['id' => $v['old_content']])->value('title');
|
||||
$v['new_content'] = Db::name('InvoiceSubject')->where(['id' => $v['new_content']])->value('title');
|
||||
}
|
||||
if ($v['field'] == 'tax') {
|
||||
$v['old_content'] = $v['old_content'] . '%';
|
||||
$v['new_content'] = $v['new_content'] . '%';
|
||||
}
|
||||
if ($v['field'] == 'is_tax') {
|
||||
$v['old_content'] = $v['old_content'] == 1?'是':'否';
|
||||
$v['new_content'] = $v['new_content'] == 1?'是':'否';
|
||||
}
|
||||
if ($v['field'] == 'archive_status') {
|
||||
$v['old_content'] = $v['old_content'] == 1?'已归档':'未归档';
|
||||
$v['new_content'] = $v['new_content'] == 1?'已归档':'未归档';
|
||||
}
|
||||
if (strpos($v['field'], '_ids') !== false) {
|
||||
$old_ids = Db::name('Admin')->where('id', 'in', $v['old_content'])->column('name');
|
||||
$v['old_content'] = implode(',', $old_ids);
|
||||
$new_ids = Db::name('Admin')->where('id', 'in', $v['new_content'])->column('name');
|
||||
$v['new_content'] = implode(',', $new_ids);
|
||||
}
|
||||
if ($v['old_content'] == '' || $v['old_content'] == null) {
|
||||
$v['old_content'] = '未设置';
|
||||
}
|
||||
if ($v['new_content'] == '' || $v['new_content'] == null) {
|
||||
$v['new_content'] = '未设置';
|
||||
}
|
||||
$v['action'] = $action[$v['action']];
|
||||
$v['title'] = $field_array[$v['field']];
|
||||
$v['times'] = time_trans($v['create_time']);
|
||||
$v['create_time'] = date('Y-m-d', $v['create_time']);
|
||||
$data[] = $v;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\contract\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class ContractCateCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:contract_cate',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\contract\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class ContractCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'name' => 'require',
|
||||
'code' => 'require',
|
||||
'id' => 'require',
|
||||
'cost' => 'number',
|
||||
'cate_id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'name.require' => '合同名称不能为空',
|
||||
'code.require' => '合同编号不能为空',
|
||||
'cost.number' => '价格只能是数字',
|
||||
'cate_id.require' => '所属分类为必选',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['name', 'cate_id', 'code'],
|
||||
'edit' => ['name', 'cate_id', 'code', 'id'],
|
||||
'change' => ['id'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<div class="gg-form-bar border-x border-t red" style="padding-bottom:12px">
|
||||
<p><strong>说明</strong></p>
|
||||
<p>合同性质分为:普通合同、框架合同、补充协议、其他合同</p>
|
||||
<p>1、普通合同有合同金额,且金额为必填项;</p>
|
||||
<p>2、框架合同无合同金额;</p>
|
||||
<p>3、补充协议和其它合同有合同金额,但合同金额不是必填项;</p>
|
||||
<p>4、补充协议必须要选择一个母合同。</p>
|
||||
</div>
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<button class="layui-btn layui-btn-sm addNew" type="button">+ 添加合同类型</button>
|
||||
</div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool, form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test'
|
||||
,toolbar: '#toolbarDemo'
|
||||
,defaultToolbar: false
|
||||
,title:'合同类型列表'
|
||||
,url: "/contract/cate/cate"
|
||||
,page: false
|
||||
,cellMinWidth: 80
|
||||
,cols: [[
|
||||
{field:'id',width:80, title: 'ID号', align:'center'}
|
||||
,{field:'title',title: '类别名称'}
|
||||
,{field:'status', title: '状态',width:80,align:'center',templet: function(d){
|
||||
var html1='<span class="green">正常</span>';
|
||||
var html2='<span class="yellow">禁用</span>';
|
||||
if(d.status==1){
|
||||
return html1;
|
||||
}
|
||||
else{
|
||||
return html2;
|
||||
}
|
||||
}}
|
||||
,{width:100,title: '操作', align:'center',templet: function(d){
|
||||
var html='';
|
||||
var btn='<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>';
|
||||
var btn1='<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="disable">禁用</a>';
|
||||
var btn2='<a class="layui-btn layui-btn-normal layui-btn-xs" lay-event="open">启用</a>';
|
||||
if(d.status==1){
|
||||
html = '<div class="layui-btn-group">'+btn+btn1+'</div>';
|
||||
}
|
||||
else{
|
||||
html = '<div class="layui-btn-group">'+btn+btn2+'</div>';
|
||||
}
|
||||
return html;
|
||||
}}
|
||||
]]
|
||||
});
|
||||
|
||||
table.on('tool(test)',function (obj) {
|
||||
if(obj.event === 'edit'){
|
||||
addExpense(obj.data.id,obj.data.title);
|
||||
}
|
||||
if(obj.event === 'disable'){
|
||||
layer.confirm('确定要禁用该类别吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/contract/cate/cate_check", { id: obj.data.id,status: 0,title: obj.data.title}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
if(obj.event === 'open'){
|
||||
layer.confirm('确定要启用该类别吗?', {icon: 3, title:'提示'}, function(index){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/contract/cate/cate_check", { id: obj.data.id,status: 1,title: obj.data.title}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('body').on('click','.addNew',function(){
|
||||
addExpense(0,'');
|
||||
});
|
||||
|
||||
function addExpense(id,val){
|
||||
var title = '新增类别';
|
||||
if(id>0){
|
||||
title = '编辑类别';
|
||||
}
|
||||
layer.prompt({
|
||||
title: title,
|
||||
value: val,
|
||||
yes: function(index, layero) {
|
||||
// 获取文本框输入的值
|
||||
var value = layero.find(".layui-layer-input").val();
|
||||
if (value) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
layui.pageTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/contract/cate/cate_add", {id: id,title: value}, callback);
|
||||
layer.close(index);
|
||||
} else {
|
||||
layer.msg('请填写类别标题');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,259 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">新增合同</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
{gt name="$pid" value="0"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">母合同名称</td>
|
||||
<td colspan="5">{$p_contract.name}<input type="hidden" name="pid" value="{$pid}"></td>
|
||||
</tr>
|
||||
{/gt}
|
||||
<tr>
|
||||
<td class="layui-td-gray">合同名称<font>*</font></td>
|
||||
<td colspan="3"><input type="text" name="name" lay-verify="required" lay-reqText="请输入合同名称" autocomplete="off" placeholder="请输入合同名称" class="layui-input"></td>
|
||||
<td class="layui-td-gray">合同性质</td>
|
||||
<td>
|
||||
<input type="hidden" name="type" value="{$type}">
|
||||
{eq name="$type" value="1" }普通合同{/eq}
|
||||
{eq name="$type" value="2" }框架合同{/eq}
|
||||
{eq name="$type" value="3" }补充协议{/eq}
|
||||
{eq name="$type" value="4" }其他合同{/eq}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">签约主体<span style="font-size:12px;">(乙方)</span><font>*</font></td>
|
||||
<td>
|
||||
<select name="subject_id" lay-verify="required" lay-reqText="请选择签约主体公司">
|
||||
<option value="">请选择签约主体公司</option>
|
||||
{volist name=":contract_subject()" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">合同编号<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="code" value="{$codeno}" autocomplete="off" {notempty name="$codeno"}readonly{/notempty} lay-verify="required" lay-reqText="请输入合同编号" placeholder="请输入合同编号" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">合同类别<font>*</font></td>
|
||||
<td>
|
||||
<select name="cate_id" lay-verify="required" lay-reqText="请选择合同类别">
|
||||
<option value="">请选择合同类别</option>
|
||||
{volist name=":contract_cate()" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称<span style="font-size:12px;">(甲方)</span><font>*</font></td>
|
||||
<td>
|
||||
{gt name="$pid" value="0"}
|
||||
<input type="text" name="customer" autocomplete="off" value="{$p_contract.customer}" readonly lay-verify="required" lay-reqText="请输入客户名称" placeholder="请输入客户名称" class="layui-input">
|
||||
<input type="hidden" name="customer_id" value="{$p_contract.id}">
|
||||
{else/}
|
||||
|
||||
{if condition="(isModule('customer') > 0) AND ($is_customer == 1)"}
|
||||
<input type="text" name="customer" autocomplete="off" readonly lay-verify="required" lay-reqText="请输入客户名称" placeholder="请输入客户名称" class="layui-input customer-picker">
|
||||
|
||||
{else/}
|
||||
<input type="text" name="customer" autocomplete="off" lay-verify="required" lay-reqText="请输入客户名称" placeholder="请输入客户名称" class="layui-input">
|
||||
|
||||
{/if}
|
||||
<input type="hidden" name="customer_id" value="0">
|
||||
{/gt}
|
||||
|
||||
</td>
|
||||
<td class="layui-td-gray">签约客户代表<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="customer_name" autocomplete="off" lay-verify="required" lay-reqText="请输入客户代表姓名" placeholder="请输入客户代表姓名" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">客户联系电话<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="customer_mobile" autocomplete="off" lay-verify="required" lay-reqText="请输入客户联系电话" placeholder="请输入客户联系电话" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">客户联系地址</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="customer_address" autocomplete="off" placeholder="请输入客户联系地址" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">合同始止日期<font>*</font></td>
|
||||
<td>
|
||||
<div id="barDate" class="layui-input-inline">
|
||||
<div class="layui-input-inline" style="width:110px; margin-bottom:0">
|
||||
<input type="text" class="layui-input" id="start_time" placeholder="选择时间区间" readonly name="start_time" lay-verify="required" lay-reqText="请选择合同开始时间">
|
||||
</div>
|
||||
~
|
||||
<div class="layui-input-inline" style="width:110px;margin-bottom:0">
|
||||
<input type="text" class="layui-input" id="end_time" placeholder="选择时间区间" readonly name="end_time" lay-verify="required" lay-reqText="请选择合同结束时间">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{neq name="$type" value="2"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">合同金额{eq name="$type" value="1"}<font>*</font>{/eq}</td>
|
||||
<td>
|
||||
<input type="text" name="cost" value="" {eq name="$type" value="1"} lay-verify="required|number"{/eq} lay-reqText="请输入合同金额,数字" placeholder="请输入合同金额,数字" autocomplete="off" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">是否含税</td>
|
||||
<td>
|
||||
<input type="radio" name="is_tax" value="1" title="是" checked lay-filter="tax">
|
||||
<input type="radio" name="is_tax" value="0" title="否" lay-filter="tax">
|
||||
</td>
|
||||
<td class="layui-td-gray">税点(百分比)</td>
|
||||
<td>
|
||||
<input type="text" name="tax" value="" lay-verify="number" placeholder="请输入税点,数字" autocomplete="off" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
{/neq}
|
||||
<tr>
|
||||
<td colspan="6"><strong>签订信息</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同签订人<font>*</font></td>
|
||||
<td>
|
||||
<div class="layui-input-inline" style="width:50%;">
|
||||
<input type="text" name="sign_name" autocomplete="off" readonly lay-verify="required" lay-reqText="请选择合同签订人" placeholder="请选择合同签订人" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-input-inline gray" style="width:42%;" id="sign_department"></div>
|
||||
<input type="hidden" name="sign_uid">
|
||||
<input type="hidden" name="sign_did">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">合同签订时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="sign_time" readonly lay-verify="required" lay-reqText="请选择合同签订日期" placeholder="请选择合同签订日期" class="layui-input tool-time">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">合同制定人<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="prepared_name" autocomplete="off" readonly placeholder="请选择合同制定人" class="layui-input picker-one">
|
||||
<input type="hidden" name="prepared_uid" lay-verify="required" lay-reqText="请选择合同制定人">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同保管人<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="keeper_name" autocomplete="off" readonly placeholder="请选择合同保管人" class="layui-input picker-one">
|
||||
<input type="hidden" name="keeper_uid" lay-verify="required" lay-reqText="请选择合同保管人">
|
||||
</td>
|
||||
<td class="layui-td-gray">合同共享人员</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="share_names" autocomplete="off" readonly placeholder="请选择共享人员" class="layui-input picker-more">
|
||||
<input type="hidden" name="share_ids">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6"><strong>相关附件</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">
|
||||
<button type="button" class="layui-btn layui-btn-sm" id="uploadBtn"><i class="layui-icon"></i>附件上传</button>
|
||||
</td>
|
||||
<td colspan="5" style="line-height:inherit">
|
||||
<div class="layui-row" id="fileBox">
|
||||
<input type="hidden" id="fileBoxInput" data-type="file" name="file_ids" value="">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6"><strong>备注信息</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
<textarea name="remark" placeholder="请输入备注信息" class="layui-textarea"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="scene" value="add">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','employeepicker','oaTool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,table = layui.table,laydate = layui.laydate,oaTool = layui.oaTool, employeepicker = layui.employeepicker;
|
||||
//日期范围
|
||||
laydate.render({
|
||||
elem: '#barDate',
|
||||
range: ['#start_time', '#end_time']
|
||||
});
|
||||
|
||||
//相关附件上传
|
||||
oaTool.addFile();
|
||||
|
||||
//选择关联的客户
|
||||
$('.customer-picker').on('click', function () {
|
||||
let that = $(this);
|
||||
let callback = function(data){
|
||||
$('[name="customer_id"]').val(data.id);
|
||||
$('[name="customer"]').val(data.name);
|
||||
$('[name="customer_name"]').val(data.contact_name);
|
||||
$('[name="customer_mobile"]').val(data.contact_mobile);
|
||||
$('[name="customer_address"]').val(data.address);
|
||||
}
|
||||
oaTool.customerPicker(callback);
|
||||
});
|
||||
|
||||
//选择合同签订人弹窗
|
||||
$('body').on('click','[name="sign_name"]',function () {
|
||||
var ids=$('[name="sign_uid"]').val(),names=$('[name="sign_name"]').val();
|
||||
employeepicker.init({
|
||||
ids:ids,
|
||||
names:names,
|
||||
type:0,
|
||||
department_url: "/api/index/get_department_tree",
|
||||
employee_url: "/api/index/get_employee",
|
||||
callback:function(ids,names,dids,departments){
|
||||
$('[name="sign_uid"]').val(ids);
|
||||
$('[name="sign_name"]').val(names);
|
||||
$('[name="sign_did"]').val(dids);
|
||||
$('#sign_department').html('部门:'+departments);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//radio选择
|
||||
form.on('radio(tax)', function(data){
|
||||
if(data.value == 0){
|
||||
$('[name="tax"]').val('0').hide();
|
||||
}else{
|
||||
$('[name="tax"]').val('').show();
|
||||
}
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
if (data.field.type == 1 && data.field.cost == '') {
|
||||
layer.msg('请完善合同金额');
|
||||
return false;
|
||||
}
|
||||
if (data.field.is_tax == 1 && data.field.tax == '') {
|
||||
layer.msg('请完善税点');
|
||||
return false;
|
||||
}
|
||||
if (data.field.is_tax == 1 && data.field.cost == '') {
|
||||
layer.msg('请完善金额');
|
||||
return false;
|
||||
}
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose(1000);
|
||||
}
|
||||
}
|
||||
tool.post("/contract/index/add", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,151 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<form class="layui-form gg-form-bar border-x border-t">
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<select name="cate_id">
|
||||
<option value="">请选择合同类别</option>
|
||||
{volist name=":contract_cate()" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<select name="type">
|
||||
<option value="">请选择合同性质</option>
|
||||
<option value="1">普通合同</option>
|
||||
<option value="2">框架合同</option>
|
||||
<option value="3">补充协议</option>
|
||||
<option value="4">其他合同</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:240px;">
|
||||
<input type="text" name="keywords" placeholder="输入关键字" class="layui-input" autocomplete="off" />
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform"><i class="layui-icon layui-icon-search mr-1"></i>搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-reset" lay-filter="reset">清空</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool ,form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test',
|
||||
title: '合同归档列表',
|
||||
url: "/contract/index/archive", //数据接口
|
||||
cellMinWidth: 80,
|
||||
page: true, //开启分页
|
||||
limit: 20,
|
||||
cols: [
|
||||
[ //表头
|
||||
{
|
||||
field: 'id',
|
||||
title: '编号',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},{ field: 'check_status', title: '状态', align: 'center', width: 80, templet: function (d) {
|
||||
var html = '<span class="layui-btn layui-btn-xs layui-bg-' + d.check_status + '">' + d.status_name + '</span>';
|
||||
return html;
|
||||
}
|
||||
},{
|
||||
field: 'code',
|
||||
title: '合同编号',
|
||||
width: 160
|
||||
},{
|
||||
field: 'name',
|
||||
title: '合同名称',
|
||||
minWidth:240,
|
||||
templet: '<div><a data-href="/contract/index/view/id/{{d.id}}.html" class="side-a">{{d.name}}</a></div>'
|
||||
}, {
|
||||
field: 'cate_title',
|
||||
title: '合同类别',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'type_name',
|
||||
title: '合同性质',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
templet: function (d) {
|
||||
var html = '<span class="layui-color-' + d.type + '">' + d.type_name + '</span>';
|
||||
return html;
|
||||
}
|
||||
},{
|
||||
field: 'cost',
|
||||
title: '合同金额/元',
|
||||
align: 'right',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'sign_name',
|
||||
title: '签定人',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},{
|
||||
field: 'keeper_name',
|
||||
title: '保管人',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'sign_time',
|
||||
title: '签订时间',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'right',
|
||||
fixed:'right',
|
||||
title: '操作',
|
||||
width: 100,
|
||||
align: 'center',
|
||||
templet: function (d) {
|
||||
return '<span class="layui-btn layui-btn-normal layui-btn-xs" lay-event="view">详情</span>';
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
//表头工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
if (obj.event === 'add') {
|
||||
selectType();
|
||||
return;
|
||||
}
|
||||
});
|
||||
//监听行工具事件
|
||||
table.on('tool(test)', function(obj) {
|
||||
var data = obj.data;
|
||||
if(obj.event === 'view'){
|
||||
tool.side('/contract/index/view?id='+data.id);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//监听搜索提交
|
||||
form.on('submit(webform)', function(data) {
|
||||
layui.pageTable.reload({
|
||||
where: {
|
||||
keywords: data.field.keywords,
|
||||
cate_id: data.field.cate_id,
|
||||
type: data.field.type
|
||||
},
|
||||
page: {
|
||||
curr: 1
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,257 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">编辑合同</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
{gt name="$detail.pid" value="0"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">母合同名称</td>
|
||||
<td colspan="5">{$detail.pname}</td>
|
||||
</tr>
|
||||
{/gt}
|
||||
<tr>
|
||||
<td class="layui-td-gray">合同名称<font>*</font></td>
|
||||
<td colspan="3"><input type="text" name="name" value="{$detail.name}" lay-verify="required" lay-reqText="请输入合同名称" autocomplete="off" placeholder="请输入合同名称" class="layui-input"></td>
|
||||
<td class="layui-td-gray">合同性质</td>
|
||||
<td>
|
||||
{eq name="$detail.type" value="1" }普通合同{/eq}
|
||||
{eq name="$detail.type" value="2" }框架合同{/eq}
|
||||
{eq name="$detail.type" value="3" }补充协议{/eq}
|
||||
{eq name="$detail.type" value="4" }其他合同{/eq}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">签约主体<span style="font-size:12px;">(乙方)</span><font>*</font></td>
|
||||
<td>
|
||||
<select name="subject_id" lay-verify="required" lay-reqText="请选择签约主体公司">
|
||||
<option value="">请选择签约主体公司</option>
|
||||
{volist name=":contract_subject()" id="v"}
|
||||
<option value="{$v.id}" {eq name="$v.id" value="$detail.subject_id" } selected{/eq}>{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">合同编号<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="code" value="{$detail.code}" autocomplete="off" lay-verify="required" lay-reqText="请输入合同编号" placeholder="请输入合同编号" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">合同类别<font>*</font></td>
|
||||
<td>
|
||||
<select name="cate_id" lay-verify="required" lay-reqText="请选择合同类别">
|
||||
<option value="">请选择合同类别</option>
|
||||
{volist name=":contract_cate()" id="v"}
|
||||
<option value="{$v.id}" {eq name="$v.id" value="$detail.cate_id" } selected{/eq}>{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称<span style="font-size:12px;">(甲方)</span><font>*</font></td>
|
||||
<td>
|
||||
{if condition="(isModule('customer') > 0) AND ($is_customer == 1)"}
|
||||
<input type="text" name="customer" value="{$detail.customer}" autocomplete="off" readonly lay-verify="required" lay-reqText="请输入客户名称" placeholder="请输入客户名称" class="layui-input customer-picker">
|
||||
{else/}
|
||||
<input type="text" name="customer" value="{$detail.customer}" autocomplete="off" lay-verify="required" lay-reqText="请输入客户名称" placeholder="请输入客户名称" class="layui-input">
|
||||
{/if}
|
||||
<input type="hidden" name="customer_id" value="{$detail.customer_id}">
|
||||
</td>
|
||||
<td class="layui-td-gray">签约客户代表</td>
|
||||
<td>
|
||||
<input type="text" name="customer_name" value="{$detail.customer_name}" autocomplete="off" lay-verify="required" lay-reqText="请输入客户代表姓名" placeholder="请输入客户代表姓名" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">客户联系电话<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="customer_mobile" value="{$detail.customer_mobile}" autocomplete="off" lay-verify="required" lay-reqText="请输入客户联系电话" placeholder="请输入客户联系电话" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">客户联系地址</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="customer_address" value="{$detail.customer_address}" autocomplete="off" placeholder="请输入客户联系地址" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">合同始止日期<font>*</font></td>
|
||||
<td>
|
||||
<div id="barDate" class="layui-input-inline">
|
||||
<div class="layui-input-inline" style="width:110px; margin-bottom:0">
|
||||
<input type="text" class="layui-input" id="start_time" placeholder="选择时间区间" readonly name="start_time" value="{$detail.start_time}" readonly lay-verify="required" lay-reqText="请选择合同开始时间">
|
||||
</div>
|
||||
~
|
||||
<div class="layui-input-inline" style="width:110px;margin-bottom:0">
|
||||
<input type="text" class="layui-input" id="end_time" placeholder="选择时间区间" readonly name="end_time" value="{$detail.end_time}" readonly lay-verify="required" lay-reqText="请选择合同结束时间">
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{neq name="$detail.type" value="2"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">合同金额{eq name="$detail.type" value="1"}<font>*</font>{/eq}</td>
|
||||
<td>
|
||||
<input type="text" name="cost" value="{$detail.cost}" {eq name="$detail.type" value="1"} lay-verify="required|number"{/eq} lay-reqText="请输入合同金额,数字" placeholder="请输入合同金额,数字" autocomplete="off" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">是否含税</td>
|
||||
<td>
|
||||
<input type="radio" name="is_tax" value="1" title="是" {eq name="$detail.is_tax" value="1" } checked{/eq} lay-filter="tax">
|
||||
<input type="radio" name="is_tax" value="0" title="否" {eq name="$detail.is_tax" value="0" } checked{/eq} lay-filter="tax">
|
||||
</td>
|
||||
<td class="layui-td-gray">税点(百分比)</td>
|
||||
<td>
|
||||
<input type="text" name="tax" value="{$detail.tax}"
|
||||
<input type="text" name="tax" value="" lay-verify="number" placeholder="请输入税点,数字" autocomplete="off" class="layui-input" {eq name="$detail.is_tax" value="0" } style="display:none;"{/eq}>
|
||||
</td>
|
||||
</tr>
|
||||
{/neq}
|
||||
<tr>
|
||||
<td colspan="6"><strong>签订信息</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同签订人<font>*</font></td>
|
||||
<td>
|
||||
<div class="layui-input-inline" style="width:50%;">
|
||||
<input type="text" name="sign_name" value="{$detail.sign_name}" autocomplete="off" readonly lay-verify="required" lay-reqText="请选择合同签订人" placeholder="请选择合同签订人" class="layui-input">
|
||||
</div>
|
||||
<div class="layui-input-inline gray" style="width:42%;" id="sign_department">部门:{$detail.sign_department}</div>
|
||||
<input type="hidden" name="sign_uid" value="{$detail.sign_uid}">
|
||||
<input type="hidden" name="sign_did" value="{$detail.sign_did}">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">合同签订时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="sign_time" value="{$detail.sign_time}" readonly lay-verify="required" lay-reqText="请选择合同签订日期" placeholder="请选择合同签订日期" class="layui-input tool-time">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">合同制定人<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="prepared_name" value="{$detail.prepared_name}" autocomplete="off" readonly placeholder="请选择合同制定人" class="layui-input picker-one">
|
||||
<input type="hidden" name="prepared_uid" value="{$detail.prepared_uid}" lay-verify="required" lay-reqText="请选择合同制定人">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同保管人<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="keeper_name" value="{$detail.keeper_name}" autocomplete="off" readonly placeholder="请选择合同保管人" class="layui-input picker-one">
|
||||
<input type="hidden" name="keeper_uid" value="{$detail.keeper_uid}" lay-verify="required" lay-reqText="请选择合同保管人">
|
||||
</td>
|
||||
<td class="layui-td-gray">合同共享人员</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="share_names" value="{$detail.share_names}" autocomplete="off" readonly placeholder="请选择共享人员" class="layui-input picker-more">
|
||||
<input type="hidden" name="share_ids" value="{$detail.share_ids}">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6"><strong>相关附件</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">
|
||||
<button type="button" class="layui-btn layui-btn-sm" id="uploadBtn"><i class="layui-icon"></i>附件上传</button>
|
||||
</td>
|
||||
<td colspan="5" style="line-height:inherit">
|
||||
<div class="layui-row" id="fileBox">
|
||||
<input type="hidden" data-type="file" name="file_ids" value="{$detail.file_ids}">
|
||||
{notempty name="$detail.file_ids"}
|
||||
{volist name="$detail.fileArray" id="vo"}
|
||||
<div class="layui-col-md4" id="uploadImg{$vo.id}">{:file_card($vo)}</div>
|
||||
{/volist}
|
||||
{/notempty}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6"><strong>备注信息</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
<textarea name="remark" placeholder="请输入备注信息" class="layui-textarea">{$detail.remark}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="id" value="{$detail.id}">
|
||||
<input type="hidden" name="scene" value="edit">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','employeepicker','oaTool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,table = layui.table,laydate = layui.laydate,oaTool = layui.oaTool, employeepicker = layui.employeepicker;
|
||||
//日期范围
|
||||
laydate.render({
|
||||
elem: '#barDate',
|
||||
range: ['#start_time', '#end_time']
|
||||
});
|
||||
|
||||
//相关附件上传
|
||||
oaTool.addFile();
|
||||
|
||||
//选择关联的客户
|
||||
$('.customer-picker').on('click', function () {
|
||||
let that = $(this);
|
||||
let callback = function(data){
|
||||
$('[name="customer_id"]').val(data.id);
|
||||
$('[name="customer"]').val(data.name);
|
||||
$('[name="customer_name"]').val(data.contact_name);
|
||||
$('[name="customer_mobile"]').val(data.contact_mobile);
|
||||
$('[name="customer_address"]').val(data.address);
|
||||
}
|
||||
oaTool.customerPicker(callback);
|
||||
});
|
||||
|
||||
//选择合同签订人弹窗
|
||||
$('body').on('click','[name="sign_name"]',function () {
|
||||
var ids=$('[name="sign_uid"]').val(),names=$('[name="sign_name"]').val();
|
||||
employeepicker.init({
|
||||
ids:ids,
|
||||
names:names,
|
||||
type:0,
|
||||
department_url: "/api/index/get_department_tree",
|
||||
employee_url: "/api/index/get_employee",
|
||||
callback:function(ids,names,dids,departments){
|
||||
$('[name="sign_uid"]').val(ids);
|
||||
$('[name="sign_name"]').val(names);
|
||||
$('[name="sign_did"]').val(dids);
|
||||
$('[name="sign_department"]').val(departments);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//radio选择
|
||||
form.on('radio(tax)', function(data){
|
||||
if(data.value == 0){
|
||||
$('[name="tax"]').val('0').hide();
|
||||
}else{
|
||||
$('[name="tax"]').val('').show();
|
||||
}
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
if (data.field.type == 1 && data.field.cost == '') {
|
||||
layer.msg('请完善合同金额');
|
||||
return false;
|
||||
}
|
||||
if (data.field.is_tax == 1 && data.field.tax == '') {
|
||||
layer.msg('请完善税点');
|
||||
return false;
|
||||
}
|
||||
if (data.field.is_tax == 1 && data.field.cost == '') {
|
||||
layer.msg('请完善金额');
|
||||
return false;
|
||||
}
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose(1000);
|
||||
}
|
||||
}
|
||||
tool.post("/contract/index/add", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,332 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<div class="p-3">
|
||||
<form class="layui-form gg-form-bar border-x border-t" lay-filter="barsearchform">
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<select name="cate_id">
|
||||
<option value="">请选择合同类别</option>
|
||||
{volist name=":contract_cate()" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<select name="type">
|
||||
<option value="">请选择合同性质</option>
|
||||
<option value="1">普通合同</option>
|
||||
<option value="2">框架合同</option>
|
||||
<option value="3">补充协议</option>
|
||||
<option value="4">其他合同</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<select name="check_status">
|
||||
<option value="">请选择合同状态</option>
|
||||
<option value="0">待审核</option>
|
||||
<option value="1">审核中</option>
|
||||
<option value="2">审核通过</option>
|
||||
<option value="3">审核拒绝</option>
|
||||
<option value="4">已撤销</option>
|
||||
<option value="5">已中止</option>
|
||||
<option value="6">已作废</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:240px;">
|
||||
<input type="text" name="keywords" placeholder="输入关键字" class="layui-input" autocomplete="off" />
|
||||
</div>
|
||||
<div class="layui-input-inline" style="width:150px;">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform"><i class="layui-icon layui-icon-search mr-1"></i>搜索</button>
|
||||
<button type="reset" class="layui-btn layui-btn-reset" lay-filter="reset">清空</button>
|
||||
</div>
|
||||
</form>
|
||||
<table class="layui-hide" id="test" lay-filter="test"></table>
|
||||
</div>
|
||||
|
||||
<script type="text/html" id="toolbarDemo">
|
||||
<div class="layui-btn-container">
|
||||
<span class="layui-btn layui-btn-sm" title="添加合同" lay-event="add">+ 添加合同</span>
|
||||
</div>
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var table = layui.table, tool = layui.tool ,form = layui.form;
|
||||
layui.pageTable = table.render({
|
||||
elem: '#test',
|
||||
title: '合同列表',
|
||||
toolbar: '#toolbarDemo',
|
||||
defaultToolbar:['filter', {title:'导出EXCEL',layEvent: 'LAYTABLE_EXCEL',icon: 'layui-icon-export'}],
|
||||
url: "/contract/index/index", //数据接口
|
||||
cellMinWidth: 80,
|
||||
page: true, //开启分页
|
||||
limit: 20,
|
||||
cols: [
|
||||
[ //表头
|
||||
{
|
||||
field: 'id',
|
||||
title: '编号',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},{ field: 'check_status', title: '状态', align: 'center', width: 80, templet: function (d) {
|
||||
var html = '<span class="layui-btn layui-btn-xs layui-bg-' + d.check_status + '">' + d.status_name + '</span>';
|
||||
return html;
|
||||
}
|
||||
},{
|
||||
field: 'code',
|
||||
title: '合同编号',
|
||||
width: 160
|
||||
},{
|
||||
field: 'name',
|
||||
title: '合同名称',
|
||||
minWidth:240,
|
||||
templet: '<div><a data-href="/contract/index/view/id/{{d.id}}.html" class="side-a">{{d.name}}</a></div>'
|
||||
}, {
|
||||
field: 'cate_title',
|
||||
title: '合同类别',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'type_name',
|
||||
title: '合同性质',
|
||||
align: 'center',
|
||||
width: 80,
|
||||
templet: function (d) {
|
||||
var html = '<span class="layui-color-' + d.type_a + '">' + d.type_name + '</span>';
|
||||
return html;
|
||||
}
|
||||
},{
|
||||
field: 'interval_time',
|
||||
title: '合同有效时间',
|
||||
align: 'center',
|
||||
width: 248,
|
||||
templet: function (d) {
|
||||
var html = d.interval_time;
|
||||
if (d.delay > 0 && d.delay < 30) {
|
||||
html += '<span class="red ml-1" style="font-size:12px;">' + d.delay + '天后到期</span>';
|
||||
}
|
||||
if (d.delay == 0) {
|
||||
html += '<span class="red ml-1" style="font-size:12px;">已过期</span>';
|
||||
}
|
||||
return html;
|
||||
}
|
||||
},{
|
||||
field: 'cost',
|
||||
title: '合同金额/元',
|
||||
align: 'right',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'sign_name',
|
||||
title: '签定人',
|
||||
align: 'center',
|
||||
width: 80
|
||||
},{
|
||||
field: 'keeper_name',
|
||||
title: '保管人',
|
||||
align: 'center',
|
||||
width: 80
|
||||
}, {
|
||||
field: 'sign_time',
|
||||
title: '签订时间',
|
||||
align: 'center',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'right',
|
||||
fixed:'right',
|
||||
title: '操作',
|
||||
width: 120,
|
||||
align: 'center',
|
||||
templet: function (d) {
|
||||
var html = '<div class="layui-btn-group">';
|
||||
var btn0='<span class="layui-btn layui-btn-normal layui-btn-xs" lay-event="view">详情</span>';
|
||||
var btn1='<span class="layui-btn layui-btn-xs" lay-event="edit">编辑</span>';
|
||||
var btn2='<span class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</span>';
|
||||
if(d.check_status==0 || d.check_status==4){
|
||||
return html+btn0+btn1+btn2+'</div>';
|
||||
}
|
||||
else{
|
||||
return btn0;
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
//表头工具栏事件
|
||||
table.on('toolbar(test)', function(obj){
|
||||
if (obj.event === 'add') {
|
||||
selectType();
|
||||
return;
|
||||
}
|
||||
if(obj.event === 'LAYTABLE_EXCEL'){
|
||||
var formSelect = form.val('barsearchform');
|
||||
formSelect.limit=99999;
|
||||
$.ajax({
|
||||
url: '/contract/index/index',
|
||||
data: formSelect,
|
||||
success:function(res){
|
||||
table.exportFile('test', res.data,'xls');
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
});
|
||||
//监听行工具事件
|
||||
table.on('tool(test)', function(obj) {
|
||||
var data = obj.data;
|
||||
if(obj.event === 'view'){
|
||||
tool.side('/contract/index/view?id='+data.id);
|
||||
return;
|
||||
}
|
||||
|
||||
if(obj.event === 'edit'){
|
||||
tool.side('/contract/index/add?id='+data.id);
|
||||
return;
|
||||
}
|
||||
if (obj.event === 'del') {
|
||||
layer.confirm('确定要删除吗?', {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function(index) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
obj.del();
|
||||
}
|
||||
}
|
||||
tool.delete("/contract/index/delete", {id: data.id}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//选择合同性质
|
||||
var table_a;
|
||||
function selectType() {
|
||||
layer.open({
|
||||
title: '选择合同性质',
|
||||
type:1,
|
||||
area: ['480px', '336px'],
|
||||
content: '<div class="picker-table"><div id="boxselect"></div></div>',
|
||||
success: function() {
|
||||
table_a = table.render({
|
||||
elem: '#boxselect',
|
||||
cols: [
|
||||
[{
|
||||
type: 'radio',
|
||||
title: '选择',
|
||||
width: 100
|
||||
}, {
|
||||
field: 'title',
|
||||
title: '名称'
|
||||
}]
|
||||
],
|
||||
data: [{
|
||||
"type": "1",
|
||||
"title": "普通合同"
|
||||
},{
|
||||
"type": "2",
|
||||
"title": "框架合同"
|
||||
}, {
|
||||
"type": "3",
|
||||
"title": "补充协议"
|
||||
}, {
|
||||
"type": "4",
|
||||
"title": "其他合同"
|
||||
}]
|
||||
});
|
||||
},
|
||||
btn:['确定'],
|
||||
yes: function(index) {
|
||||
var checkStatus = table.checkStatus(table_a.config.id);
|
||||
var data = checkStatus.data;
|
||||
if (data.length > 0) {
|
||||
if(data[0].type == 3){
|
||||
selectCharge(data[0].type);
|
||||
}
|
||||
else{
|
||||
tool.side("/contract/index/add?type="+data[0].type);
|
||||
}
|
||||
layer.close(index);
|
||||
}
|
||||
else{
|
||||
layer.msg('选择合同性质');
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
//选择母合同
|
||||
var table_b;
|
||||
function selectCharge(type){
|
||||
layer.open({
|
||||
title:'选择母合同',
|
||||
area:['680px','580px'],
|
||||
type:1,
|
||||
content:'<div class="picker-table">\
|
||||
<form class="layui-form pb-2">\
|
||||
<div class="layui-input-inline" style="width:500px;">\
|
||||
<input type="text" name="keywords" placeholder="合同名称" class="layui-input" autocomplete="off" />\
|
||||
</div>\
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="search_form">提交搜索</button>\
|
||||
</form>\
|
||||
<div id="boxcontract"></div></div>',
|
||||
success:function(){
|
||||
table_b=table.render({
|
||||
elem: '#boxcontract'
|
||||
,url:'/contract/api/get_contract'
|
||||
,page: true //开启分页
|
||||
,limit: 10
|
||||
,cols: [[
|
||||
{type:'radio',title: '选择'}
|
||||
,{field:'name', title: '合同名称'}
|
||||
,{field:'sign_name', width:90, title: '签约人',align:'center'}
|
||||
,{field:'sign_time', width:110, title: '签约日期',align:'center'}
|
||||
]]
|
||||
});
|
||||
|
||||
//搜索提交
|
||||
form.on('submit(search_form)', function(data){
|
||||
table_b.reload({where:{keywords:data.field.keywords},page:{curr:1}});
|
||||
return false;
|
||||
});
|
||||
},
|
||||
btn: ['确定'],
|
||||
yes: function(index){
|
||||
var checkStatus = table.checkStatus(table_b.config.id);
|
||||
var data = checkStatus.data;
|
||||
if(data.length>0){
|
||||
tool.side("/contract/index/add?type="+type+"&pid="+data[0].id);
|
||||
layer.close(index);
|
||||
}else{
|
||||
layer.msg('请先选择合同');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
//监听搜索提交
|
||||
form.on('submit(webform)', function(data) {
|
||||
layui.pageTable.reload({
|
||||
where: {
|
||||
keywords: data.field.keywords,
|
||||
cate_id: data.field.cate_id,
|
||||
type: data.field.type,
|
||||
check_status: data.field.check_status
|
||||
},
|
||||
page: {
|
||||
curr: 1
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,428 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
{block name="style"}
|
||||
<style>
|
||||
html{background-color:#fff;}
|
||||
.log-timeline{ position: relative; min-height:600px; padding-left: 48px; background-color:#fff;}
|
||||
.log-timeline:after {content: ""; position: absolute; top: 0; left: 24px; width: 1px; height: 100%; background: #e3e9ed;}
|
||||
.log-timeline dl{padding-bottom: 8px; position: relative;}
|
||||
.log-timeline dt{font-size: 16px; line-height: 2.4; color: #323232; font-weight:600}
|
||||
.log-timeline dd{font-size: 14px; line-height: 1.6; padding:5px 0}
|
||||
.log-timeline .date-second-point{width: 10px; height: 10px; display: block; border-radius: 50%; border: 3px solid #FBBC05; background: #fff; position: absolute; z-index: 99; left:-32px; top:9px}
|
||||
.log-timeline .log-thumb{width: 24px; height: 24px; border-radius: 50%; margin-right:4px;}
|
||||
.log-timeline .open-a{margin:0 4px;}
|
||||
.log-item i{font-weight:800; color:#323232}
|
||||
.log-content strong{margin:0 4px; color:#323232}
|
||||
</style>
|
||||
{/block}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form px-4 pt-2" lay-filter="contract">
|
||||
<div class="layui-tab" style="margin:0;" lay-filter="contract" id="contractTab">
|
||||
<ul class="layui-tab-title">
|
||||
<li class="layui-this" data-load="true">合同详情</li>
|
||||
<li>操作记录</li>
|
||||
</ul>
|
||||
<div class="layui-tab-content">
|
||||
<div class="layui-tab-item layui-show">
|
||||
<table class="layui-table layui-table-form" style="margin:0">
|
||||
{gt name="$detail.pid" value="0"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">母合同名称</td>
|
||||
<td colspan="7">{$detail.pname}</td>
|
||||
</tr>
|
||||
{/gt}
|
||||
<tr>
|
||||
<td class="layui-td-gray">合同名称</td>
|
||||
<td colspan="5">{$detail.name}</td>
|
||||
<td class="layui-td-gray">合同编号</td>
|
||||
<td>{$detail.code}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">签约主体(乙方)</td>
|
||||
<td colspan="3">
|
||||
{volist name=":contract_subject()" id="v"}
|
||||
{eq name="$v.id" value="$detail.subject_id" }{$v.title}{/eq}
|
||||
{/volist}
|
||||
</td>
|
||||
<td class="layui-td-gray">合同性质</td>
|
||||
<td>
|
||||
{eq name="$detail.type" value="1" }普通合同{/eq}
|
||||
{eq name="$detail.type" value="2" }框架合同{/eq}
|
||||
{eq name="$detail.type" value="3" }补充协议{/eq}
|
||||
{eq name="$detail.type" value="4" }其他合同{/eq}
|
||||
</td>
|
||||
<td class="layui-td-gray">合同类别</td>
|
||||
<td>
|
||||
{volist name=":contract_cate()" id="v"}
|
||||
{eq name="$v.id" value="$detail.cate_id" }{$v.title}{/eq}
|
||||
{/volist}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称(甲方)</td>
|
||||
<td colspan="3">{$detail.customer}</td>
|
||||
<td class="layui-td-gray">签约客户代表</td>
|
||||
<td>{$detail.customer_name}</td>
|
||||
<td class="layui-td-gray">客户联系电话</td>
|
||||
<td>{$detail.customer_mobile}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">客户联系地址</td>
|
||||
<td colspan="3">{$detail.customer_address}</td>
|
||||
<td class="layui-td-gray-2">合同开始日期</td>
|
||||
<td>{$detail.start_time}</td>
|
||||
<td class="layui-td-gray-2">合同结束日期</td>
|
||||
<td>{$detail.end_time}</td>
|
||||
</tr>
|
||||
{neq name="$detail.type" value="2"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">合同金额</td>
|
||||
<td>{$detail.cost}</td>
|
||||
{eq name="$detail.is_tax" value="1" }
|
||||
<td class="layui-td-gray">是否含税</td>
|
||||
<td>是</td>
|
||||
<td class="layui-td-gray">税点(百分比)</td>
|
||||
<td colspan="3">{$detail.tax}%</td>
|
||||
{/eq}
|
||||
{eq name="$detail.is_tax" value="0" }
|
||||
<td class="layui-td-gray">是否含税</td>
|
||||
<td colspan="5">否</td>
|
||||
{/eq}
|
||||
</tr>
|
||||
{/neq}
|
||||
{notempty name="$detail.remark"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">备注信息</td>
|
||||
<td colspan="7">{$detail.remark|default=''}</td>
|
||||
</tr>
|
||||
{/notempty}
|
||||
{notempty name="$detail.file_ids"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">相关附件</td>
|
||||
<td colspan="7" style="line-height:inherit">
|
||||
<div class="layui-row">
|
||||
{volist name="$detail.fileArray" id="vo"}
|
||||
<div class="layui-col-md4" id="uploadImg{$vo.id}">{:file_card($vo,'view')}</div>
|
||||
{/volist}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/notempty}
|
||||
<tr>
|
||||
<td colspan="8"><strong>补充附件</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">
|
||||
<button type="button" class="layui-btn layui-btn-sm" id="uploadBtn"><i class="layui-icon"></i>附件上传</button>
|
||||
</td>
|
||||
<td colspan="7" style="line-height:inherit">
|
||||
<div id="fileBox">
|
||||
{volist name="$detail.file_array_other" id="vo"}
|
||||
<div class="layui-col-md4" id="fileItem{$vo.id}">{:file_card($vo)}</div>
|
||||
{/volist}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8"><strong>签订信息</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同制定人</td>
|
||||
<td>{$detail.prepared_name} </td>
|
||||
<td class="layui-td-gray-2">合同签订人</td>
|
||||
<td>{$detail.sign_name}</td>
|
||||
<td class="layui-td-gray-2">合同签订时间</td>
|
||||
<td>{$detail.sign_time}</td>
|
||||
<td class="layui-td-gray-2">合同签订部门</td>
|
||||
<td>{$detail.sign_department}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同保管人</td>
|
||||
<td>{$detail.keeper_name}{gt name="$auth" value="0"}<span id="keeper" data-ids="{$detail.keeper_uid}" data-names="{$detail.keeper_name}" class="layui-btn layui-btn-xs layui-btn-normal ml-1">更改</span>{/gt}</td>
|
||||
<td class="layui-td-gray">合同共享人员</td>
|
||||
<td colspan="5">{$detail.share_names}{gt name="$auth" value="0"}<span id="shares" data-ids="{$detail.share_ids}" data-names="{$detail.share_names}" class="layui-btn layui-btn-xs layui-btn-normal ml-1">更改</span>{/gt}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="8"><strong>审核信息</strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">合同状态</td>
|
||||
<td><span class="layui-color-{$detail.check_status}">{$detail.status_name}</span></td>
|
||||
<td class="layui-td-gray-2">录入人</td>
|
||||
<td>{$detail.admin_name|default=''} </td>
|
||||
<td class="layui-td-gray-2">录入时间</td>
|
||||
<td colspan="3">{$detail.create_time|default=''}</td>
|
||||
</tr>
|
||||
{notempty name="$check_record"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">历史审批记录</td>
|
||||
<td colspan="7">
|
||||
<ul class="layui-timeline flow-record pt-2">
|
||||
{volist name="$check_record" id="vo"}
|
||||
<li class="layui-timeline-item delete-{$vo.delete_time}">
|
||||
<i class="layui-icon layui-timeline-axis"></i>
|
||||
<p style="padding-left:24px">{$vo.check_time_str}<span class="black ml-2">{$vo.name}</span><span class="mx-2 layui-color-{$vo.status}">{$vo.status_str}</span>了此申请。操作意见:<span class="green">{$vo.content}</span></p>
|
||||
</li>
|
||||
{/volist}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
{/notempty}
|
||||
</table>
|
||||
|
||||
{if ($detail.check_status == 1)}
|
||||
{include file="/index/view_step" /}
|
||||
{elseif ($detail.check_status == 0) OR ($detail.check_status == 4)}
|
||||
{include file="/index/view_set" /}
|
||||
{else /}
|
||||
<table class="layui-table">
|
||||
{eq name="$detail.check_status" value="2" }
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">归档状态</td>
|
||||
{eq name="$detail.archive_status" value="0" }
|
||||
<td colspan="7"><span class="layui-color-{$detail.archive_status}">{$detail.archive_status_name}</span></td>
|
||||
{else/}
|
||||
<td><span class="layui-color-{$detail.archive_status}">{$detail.archive_status_name}</span></td>
|
||||
<td class="layui-td-gray-2">归档人</td>
|
||||
<td>{$detail.archive_name|default=''} </td>
|
||||
<td class="layui-td-gray-2">归档时间</td>
|
||||
<td colspan="3">{$detail.archive_time|default=''}</td>
|
||||
{/eq}
|
||||
</tr>
|
||||
{/eq}
|
||||
|
||||
{eq name="$detail.check_status" value="5" }
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">中止人</td>
|
||||
<td>{$detail.stop_name|default=''} </td>
|
||||
<td class="layui-td-gray-2">中止时间</td>
|
||||
<td colspan="5">{$detail.stop_time|default=''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">中止备注</td>
|
||||
<td colspan="7">{$detail.stop_remark|default=''}</td>
|
||||
</tr>
|
||||
{/eq}
|
||||
|
||||
{eq name="$detail.check_status" value="6" }
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">作废人</td>
|
||||
<td>{$detail.void_name|default=''} </td>
|
||||
<td class="layui-td-gray-2">作废时间</td>
|
||||
<td colspan="5">{$detail.void_time|default=''}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">作废备注</td>
|
||||
<td colspan="7">{$detail.void_remark|default=''}</td>
|
||||
</tr>
|
||||
{/eq}
|
||||
</table>
|
||||
<div class="pt-2">
|
||||
{gt name="$auth" value="0"}
|
||||
{eq name="$detail.check_status" value="2" }
|
||||
{eq name="$detail.archive_status" value="1" }
|
||||
<span class="layui-btn layui-btn-danger" data-event="archive" data-status="0">反确认归档</span>
|
||||
{else/}
|
||||
<span class="layui-btn layui-btn-normal" data-event="archive" data-status="1">合同归档</span>
|
||||
<span class="layui-btn layui-btn-danger" data-event="check" data-status="0">反确认审核</span>
|
||||
{/eq}
|
||||
{/eq}
|
||||
{eq name="$detail.check_status" value="5" }
|
||||
<div class="py-2">
|
||||
<span class="layui-btn layui-btn-danger" data-event="check" data-status="0">反中止合同</span>
|
||||
</div>
|
||||
{/eq}
|
||||
|
||||
{eq name="$detail.check_status" value="6" }
|
||||
<div class="py-2">
|
||||
<span class="layui-btn layui-btn-danger" data-event="check" data-status="0">反作废合同</span>
|
||||
</div>
|
||||
{/eq}
|
||||
{/gt}
|
||||
{if ( $detail.check_status eq 3) AND ( $is_create_admin eq 1) }
|
||||
<span class="layui-btn layui-btn-primary check_back"><i class="layui-icon layui-icon-reduce-circle"></i> 撤回</span>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
</div>
|
||||
<div class="layui-tab-item">
|
||||
{include file="/index/view_log" /}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const contract_id = '{$detail.id}';
|
||||
const contract_status = '{$detail.check_status}';
|
||||
const moduleInit = ['tool','employeepicker','oaTool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool, element = layui.element,employeepicker = layui.employeepicker,oaTool = layui.oaTool;
|
||||
element.on('tab(contract)', function(data){
|
||||
let index = data.index;
|
||||
if(index == 1){
|
||||
log(layui);
|
||||
}
|
||||
});
|
||||
if(typeof init==='function'){
|
||||
init(form,tool);
|
||||
}
|
||||
|
||||
if (typeof (flowStep) == "function") {
|
||||
flowStep();
|
||||
}
|
||||
|
||||
//选择合同保管人弹窗
|
||||
$('body').on('click','#keeper',function () {
|
||||
var ids=$(this).data('ids')+'',names = $(this).data('names')+'';
|
||||
employeepicker.init({
|
||||
ids:ids,
|
||||
names:names,
|
||||
type:0,
|
||||
department_url: "/api/index/get_department_tree",
|
||||
employee_url: "/api/index/get_employee",
|
||||
callback:function(ids,names,dids,departments){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/contract/index/add", {'id':contract_id,'keeper_uid':ids,'scene':'change'}, callback);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//选择共享成员弹窗
|
||||
$('body').on('click','#shares',function () {
|
||||
var ids=$(this).data('ids')+'',names = $(this).data('names')+'',share_ids_array=[],share_names_array=[];
|
||||
if(ids.length>0){
|
||||
share_ids_array=ids.split(',');
|
||||
share_names_array=names.split(',');
|
||||
}
|
||||
employeepicker.init({
|
||||
ids:share_ids_array,
|
||||
names:share_names_array,
|
||||
type:1,
|
||||
department_url: "/api/index/get_department_tree",
|
||||
employee_url: "/api/index/get_employee",
|
||||
callback:function(ids,names,dids,departments){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/contract/index/add", {'id':contract_id,'share_ids':ids.join(','),'scene':'change'}, callback);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
$('body').on('click','[data-event="check"]',function(){
|
||||
let status = $(this).data('status');
|
||||
let action = '';
|
||||
let title = ''
|
||||
if(contract_status == 2 && status == 0){
|
||||
title = '确定要反确认该合同的审核?';
|
||||
action = 'check_refue';
|
||||
}
|
||||
if(contract_status == 5 && status == 0){
|
||||
title = '确定要反中止该合同?';
|
||||
action = 'stop_no';
|
||||
}
|
||||
if(contract_status == 6 && status == 0){
|
||||
title = '确定要反作废该合同?';
|
||||
action = 'void_no';
|
||||
}
|
||||
layer.confirm(title, {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function(index) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
parent.layui.pageTable.reload();
|
||||
setTimeout(function(){
|
||||
location.reload();
|
||||
},2000)
|
||||
}
|
||||
tool.post("/contract/api/check", {id: contract_id,check_status:status,mark:''}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
});
|
||||
|
||||
$('body').on('click','[data-event="archive"]',function(){
|
||||
let status = $(this).data('status');
|
||||
layer.confirm('合同归档后将不能进行任何数据操作,确定要提交归档?', {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function(index) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
parent.layui.pageTable.reload();
|
||||
setTimeout(function(){
|
||||
location.reload();
|
||||
},2000)
|
||||
}
|
||||
tool.post("/contract/api/archive", {id: contract_id,archive_status:status}, callback);
|
||||
layer.close(index);
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
$('body').on('click','.check_back',function(){
|
||||
layer.prompt({
|
||||
formType: 2,
|
||||
title: '请输入撤回理由',
|
||||
area: ['500px', '120px'] //自定义文本域宽高
|
||||
}, function(value, index, elem){
|
||||
$.ajax({
|
||||
url: "/api/index/flow_check",
|
||||
type:'post',
|
||||
data:{
|
||||
id:contract_id,
|
||||
type:4,
|
||||
check:3,
|
||||
content:value
|
||||
},
|
||||
success: function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
parent.layui.pageTable.reload();
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
})
|
||||
layer.close(index);
|
||||
});
|
||||
})
|
||||
|
||||
oaTool.addFile({
|
||||
type:1,
|
||||
isSave:true,
|
||||
ajaxDelete:function(file_id){
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
$('#fileItem' + file_id).remove();
|
||||
}
|
||||
}
|
||||
tool.delete("/contract/api/delete_file", {id: file_id}, callback);
|
||||
},
|
||||
ajaxSave:function(res){
|
||||
let callback = function (e) {
|
||||
location.reload();
|
||||
}
|
||||
tool.post("/contract/api/add_file", {'contract_id':contract_id,'file_id':res.data.id,'file_name':res.data.name}, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,68 @@
|
|||
<div class="bg-white">
|
||||
<div id="logList" class="log-timeline p-3"></div>
|
||||
</div>
|
||||
<script>
|
||||
function log(){
|
||||
if($('#contractTab').find('li').eq(1).data('load') =='true'){
|
||||
return false;
|
||||
}
|
||||
$('#contractTab').find('li').eq(1).data('load','true');
|
||||
let tool = layui.tool;
|
||||
|
||||
//日志
|
||||
let callback = function(res){
|
||||
$('.log-more').remove();
|
||||
if(res.code==0 && res.data.length>0){
|
||||
let itemLog = '',log_time='';
|
||||
$.each(res.data, function (index, item) {
|
||||
let detail = "";
|
||||
if(log_time != item.create_time){
|
||||
if(log_time==''){
|
||||
itemLog+='<dl><dt><span class="date-second-point"></span>'+item.create_time+'</dt>'
|
||||
}
|
||||
else{
|
||||
itemLog+='</dl><dl><dt><span class="date-second-point"></span>'+item.create_time+'</dt>'
|
||||
}
|
||||
log_time = item.create_time;
|
||||
}
|
||||
if(item.field =='new' || item.field =='del'){
|
||||
detail= `
|
||||
<span class="log-content gray">${item.action}了合同</strong><span class="ml-4 gray" title="${item.create_time}">${item.times}</span>
|
||||
`;
|
||||
}
|
||||
else if(item.field =='file'){
|
||||
detail= `
|
||||
<span class="log-content gray">${item.action}了${item.title}<strong>${item.new_content}</strong><span class="ml-4 gray" title="${item.create_time}">${item.times}</span></span>
|
||||
`;
|
||||
}
|
||||
else{
|
||||
detail= `
|
||||
<span class="log-content gray">将合同<strong>${item.title}</strong>从 ${item.old_content} ${item.action}为<strong>${item.new_content}</strong><span class="ml-4 gray" title="${item.create_time}">${item.times}</span></span>
|
||||
`;
|
||||
}
|
||||
itemLog+= `
|
||||
<dd><img src="${item.thumb}" class="log-thumb" /><span class="log-name">${item.name}</span>${detail}</dd>
|
||||
`;
|
||||
});
|
||||
|
||||
itemLog+='</dl>';
|
||||
if(res.data.length>19){
|
||||
itemLog+='<div class="py-3 log-more"><button class="layui-btn layui-btn-normal layui-btn-sm" type="button">查看更多操作动态</button></div>';
|
||||
}
|
||||
$("#logList").append(itemLog);
|
||||
}
|
||||
else{
|
||||
if(project_page ==1){
|
||||
$("#logList").html('<div class="layui-data-none">暂无动态</div>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let contract_page=1;
|
||||
tool.get("/contract/api/contract_log",{contract_id:contract_id,page:contract_page},callback);
|
||||
$('#logList').on('click','.log-more',function(){
|
||||
contract_page++;
|
||||
tool.get("/contract/api/contract_log",{contract_id:contract_id,page:contract_page},callback);
|
||||
});
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,181 @@
|
|||
{eq name="$is_create_admin" value = "1"}
|
||||
<table class="layui-table layui-table-form">
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">选择审批流程<font>*</font></td>
|
||||
<td colspan="7">
|
||||
<select name="flow_id" lay-verify="required" lay-filter="flowtype" lay-reqText="请选择审批流程">
|
||||
<option value="">--请选择--</option>
|
||||
{volist name="flows" id="vo"}
|
||||
<option value="{$vo.id}" title="{$vo.check_type}">{$vo.name}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="flow_tr">
|
||||
<td class="layui-td-gray">审核人<font>*</font></td>
|
||||
<td colspan="7">
|
||||
<input type="text" name="check_admin_name" value="" autocomplete="off" placeholder="请选择审核人" lay-verify="required" lay-reqText="请选择审核人" class="layui-input picker-one" readonly>
|
||||
<input type="hidden" name="check_admin_ids" value="">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">抄送人</td>
|
||||
<td colspan="7">
|
||||
<input type="text" name="copy_names" value="" autocomplete="off" placeholder="请选择抄送人" class="layui-input picker-more" readonly>
|
||||
<input type="hidden" name="copy_uids" value="">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{/eq}
|
||||
<div class="pt-2">
|
||||
{eq name="$is_create_admin" value = "1"}
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">提交审核</button>
|
||||
<a class="layui-btn" href="/contract/index/add/id/{$detail.id}">编辑合同</a>
|
||||
{/eq}
|
||||
{gt name="$auth" value="0"}
|
||||
<span class="layui-btn layui-btn-warm" data-event="ctrl" data-status="5">中止合同</span>
|
||||
<span class="layui-btn layui-btn-danger" data-event="ctrl" data-status="6">作废合同</span>
|
||||
{/gt}
|
||||
</div>
|
||||
<script>
|
||||
function init(form,tool) {
|
||||
$('body').on('click','[data-event="ctrl"]',function(){
|
||||
let status = $(this).data('status');
|
||||
let action = '';
|
||||
let title = ''
|
||||
if(status == 5){
|
||||
title = '确定要中止该合同?';
|
||||
action = 'stop_ok';
|
||||
}
|
||||
if(status == 6){
|
||||
title = '确定要作废该合同?';
|
||||
action = 'void_ok';
|
||||
}
|
||||
layer.confirm(title, {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function(index) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
parent.layui.pageTable.reload();
|
||||
setTimeout(function(){
|
||||
location.reload();
|
||||
},2000)
|
||||
}
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: '请输入原因或理由',
|
||||
area: ['800px', '360px'],
|
||||
content: '<div style="padding:5px;"><textarea class="layui-textarea" id="remarkTextarea" style="width: 100%; height: 240px;"></textarea></div>',
|
||||
btnAlign: 'c',
|
||||
btn: ['提交保存'],
|
||||
yes: function () {
|
||||
let remark = $("#remarkTextarea").val();
|
||||
if (remark != '') {
|
||||
tool.post("/contract/api/check", {id: contract_id,check_status:status,mark:remark}, callback);
|
||||
} else {
|
||||
layer.msg('请输入原因或理由');
|
||||
}
|
||||
}
|
||||
})
|
||||
layer.close(index);
|
||||
});
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function(data){
|
||||
layer.confirm('提交审核后合同内容将不能编辑,确定要提交审核?', {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function(index) {
|
||||
data.field.id = contract_id;
|
||||
data.field.check_status = 1;
|
||||
$.ajax({
|
||||
url: "/contract/api/check",
|
||||
type:'post',
|
||||
data:data.field,
|
||||
success:function(e){
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
parent.layui.tool.close(1000);
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
form.on('select(flowtype)', function(data){
|
||||
var check_type = data.elem[data.elem.selectedIndex].title;
|
||||
var formHtml='<td class="layui-td-gray">审核人<font>*</font></td>\
|
||||
<td colspan="5">\
|
||||
<input type="text" name="check_admin_name" value="" autocomplete="off" placeholder="请选择审核人" lay-verify="required" lay-reqText="请选择审核人" class="layui-input picker-one"><input type="hidden" name="check_admin_ids" value="">\
|
||||
</td>';
|
||||
if(check_type == 2){
|
||||
$('#flow_tr').html(formHtml);
|
||||
form.render();
|
||||
}
|
||||
if(data.value==''){
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
url: "/api/index/get_flow_users",
|
||||
type:'get',
|
||||
data:{id:data.value},
|
||||
success: function (e) {
|
||||
if (e.code == 0) {
|
||||
var flowLi='';
|
||||
var flow_data = e.data.flow_data;
|
||||
if(e.data.copy_uids && e.data.copy_uids !=''){
|
||||
$('[name="copy_names"]').val(e.data.copy_unames);
|
||||
$('[name="copy_uids"]').val(e.data.copy_uids.split(','));
|
||||
}
|
||||
if(check_type == 1 || check_type == 3){
|
||||
for(var a=0;a<flow_data.length;a++){
|
||||
var userList='',sign_type = '';
|
||||
if(check_type == 1){
|
||||
if(flow_data[a].flow_type==1){
|
||||
userList+= '<li style="padding:3px 0">当前部门负责人</li>';
|
||||
}
|
||||
else if(flow_data[a].flow_type==2){
|
||||
userList+= '<li style="padding:3px 0">上级部门负责人</li>';
|
||||
}
|
||||
else{
|
||||
if(flow_data[a].flow_type==3){
|
||||
sign_type= ' <span class="layui-badge layui-bg-blue">或签</span>';
|
||||
}
|
||||
if(flow_data[a].flow_type==4){
|
||||
sign_type= ' <span class="layui-badge layui-bg-blue">会签</span>';
|
||||
}
|
||||
for(var b=0;b<flow_data[a].user_id_info.length;b++){
|
||||
userList+= '<li style="padding:3px 0"><img src="'+flow_data[a].user_id_info[b].thumb+'" style="width:24px; height:24px; border-radius:50%; margin-right:8px;" />'+flow_data[a].user_id_info[b].name+'</li>';
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(check_type == 3){
|
||||
sign_type= ' <span class="layui-badge layui-bg-blue">'+flow_data[a].flow_name+'</span>'
|
||||
for(var b=0;b<flow_data[a].user_id_info.length;b++){
|
||||
userList+= '<li style="padding:3px 0"><img src="'+flow_data[a].user_id_info[b].thumb+'" style="width:24px; height:24px; border-radius:50%; margin-right:8px;" />'+flow_data[a].user_id_info[b].name+'</li>';
|
||||
}
|
||||
}
|
||||
flowLi+='<li class="layui-timeline-item">\
|
||||
<i class="layui-icon layui-timeline-axis"></i>\
|
||||
<div class="layui-timeline-content">\
|
||||
<p class="layui-timeline-title"><strong>第'+(a+1)+'级审批</strong>'+sign_type+'</p>\
|
||||
<ul>'+userList+'</ul>\
|
||||
</div>\
|
||||
</li>';
|
||||
}
|
||||
formHtml = '<td class="layui-td-gray">审批流程</td>\
|
||||
<td colspan="7">\
|
||||
<ul id="flowList" class="layui-timeline">'+flowLi+'</ul>\
|
||||
</td>';
|
||||
$('#flow_tr').html(formHtml);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,255 @@
|
|||
<table class="layui-table layui-table-form" style="margin-top:12px">
|
||||
<tr>
|
||||
<td class="layui-td-gray-2">当前审核人</td>
|
||||
<td>{$detail.check_user}</td>
|
||||
<td class="layui-td-gray">抄送人</td>
|
||||
<td>{$detail.copy_user}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">审批流程</td>
|
||||
<td colspan="3">
|
||||
<div class="flow-flexbox check-items flow-flex-row" id="flowList">
|
||||
<div class="flow-flexbox check-item flow-flex-row">
|
||||
<i class="layui-icon layui-icon-add-circle" data-ok=""></i>
|
||||
<div class="check-item-name">{$detail.create_user}</div>
|
||||
<div class="check-item-status">提交申请</div>
|
||||
<span class="layui-icon layui-icon-right"></span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{if ( $is_check_admin eq 1) }
|
||||
{eq name="$flows.flow_type" value="0"}
|
||||
<tr>
|
||||
<td class="layui-td-gray">审批节点 <font>*</font></td>
|
||||
<td colspan="3">
|
||||
<input type="radio" name="check_node" lay-filter="check_node" value="1" title="审核结束">
|
||||
<input type="radio" name="check_node" lay-filter="check_node" value="2" title="下一审批人">
|
||||
<div class="layui-inline">
|
||||
<input type="text" name="check_admin_name" value="" autocomplete="off" placeholder="请选择下一审批人" lay-verify="required" lay-reqText="请选择下一审批人" class="layui-input picker-one"><input type="hidden" name="check_admin_ids" value="">
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/eq}
|
||||
<tr>
|
||||
<td class="layui-td-gray">审批意见 <font>*</font></td>
|
||||
<td colspan="3">
|
||||
<textarea name="content" placeholder="请输入审批意见" class="layui-textarea"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
{/if}
|
||||
</table>
|
||||
<input type="hidden" name="id" value="{$detail.id}">
|
||||
<input type="hidden" name="flow_type" value="{$flows.flow_type}">
|
||||
<input type="hidden" name="check_step_sort" value="{$detail.check_step_sort}">
|
||||
<input type="hidden" name="check_status" value="{$detail.check_status}">
|
||||
<div id="formBtn" style="padding: 10px 0">
|
||||
{eq name="$is_check_admin" value='1'}
|
||||
<span class="layui-btn layui-btn-normal" data-status="1"><i class="layui-icon layui-icon-ok"></i> 通过</span>
|
||||
<span class="layui-btn layui-btn-danger" data-status="2"><i class="layui-icon layui-icon-close"></i> {$flows.flow_type == 5?'回退':'拒绝'}</span>
|
||||
{/eq}
|
||||
{eq name="$is_create_admin" value='1'}
|
||||
<span class="layui-btn layui-btn-primary" data-status="3"><i class="layui-icon layui-icon-reduce-circle"></i> 撤回</span>
|
||||
{/eq}
|
||||
</div>
|
||||
<script>
|
||||
function flowStep(){
|
||||
var form = layui.form,tool=layui.tool, dropdown = layui.dropdown,employeepicker = layui.employeepicker;
|
||||
//获取审核信息
|
||||
$.ajax({
|
||||
url: "/api/index/get_flow_nodes",
|
||||
type:'get',
|
||||
data:{id:contract_id,type:4},
|
||||
success: function (e) {
|
||||
if (e.code == 0) {
|
||||
let flowHtml='',list = e.data,record_list='',sort = $('[name="check_step_sort"]').val();
|
||||
for(var f=0;f<list.length;f++){
|
||||
//审批流程
|
||||
let checkUser = '',
|
||||
iconRight ='<span class="layui-icon layui-icon-right"></span>',
|
||||
iconStatus ='<i class="layui-icon layui-icon-time"></i>',
|
||||
strStatus ='<div class="check-item-status">待审核</div>',
|
||||
sortClass ='';
|
||||
if(f == list.length-1){
|
||||
iconRight ='';
|
||||
}
|
||||
if(list[f].flow_type == 1 || list[f].flow_type == 2){
|
||||
checkUser=list[f].flow_type == 1?'部门负责人':'上级部门负责人';
|
||||
if(list[f].check_list.length>0){
|
||||
if(list[f].check_list[0].status == 1){
|
||||
iconStatus ='<i class="layui-icon layui-icon-ok-circle" data-ok=""></i>';
|
||||
strStatus ='<div class="check-item-status">通过</div>';
|
||||
}
|
||||
else if(list[f].check_list[0].status == 2){
|
||||
iconStatus ='<i class="layui-icon layui-icon-close" data-no=""></i>';
|
||||
strStatus ='<div class="check-item-status">拒绝</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(list[f].flow_type == 0 ){
|
||||
checkUser=list[f].user_id_info[0].name;
|
||||
if(list[f].check_list.length>0){
|
||||
iconStatus ='<i class="layui-icon layui-icon-close" data-no=""></i>';
|
||||
strStatus ='<div class="check-item-status">拒绝</div>';
|
||||
for(var m=0;m<list[f].check_list.length;m++){
|
||||
if(list[f].check_list[m].status == 1){
|
||||
iconStatus ='<i class="layui-icon layui-icon-ok-circle" data-ok=""></i>';
|
||||
strStatus ='<div class="check-item-status">通过</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(list[f].flow_type == 3 ){
|
||||
checkUser='多人或签';
|
||||
if(list[f].user_id_info.length>0){
|
||||
iconStatus ='<i class="layui-icon layui-icon-time"></i>';
|
||||
strStatus ='<div class="check-item-status">待审核</div>';
|
||||
for(var m=0;m<list[f].user_id_info.length;m++){
|
||||
if(list[f].user_id_info[m].status == 1){
|
||||
iconStatus ='<i class="layui-icon layui-icon-ok-circle" data-ok=""></i>';
|
||||
strStatus ='<div class="check-item-status">通过</div>';
|
||||
break;
|
||||
}
|
||||
if(list[f].user_id_info[m].status == 2){
|
||||
iconStatus ='<i class="layui-icon layui-icon-close" data-no=""></i>';
|
||||
strStatus ='<div class="check-item-status">拒绝</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(list[f].flow_type == 4){
|
||||
checkUser='多人会签';
|
||||
if(list[f].user_id_info.length>0){
|
||||
iconStatus ='<i class="layui-icon layui-icon-ok-circle" data-ok=""></i>';
|
||||
strStatus ='<div class="check-item-status">通过</div>';
|
||||
for(var m=0;m<list[f].user_id_info.length;m++){
|
||||
if(list[f].user_id_info[m].status == 2){
|
||||
iconStatus ='<i class="layui-icon layui-icon-close" data-no=""></i>';
|
||||
strStatus ='<div class="check-item-status">拒绝</div>';
|
||||
break;
|
||||
}
|
||||
if(list[f].user_id_info[m].status == 0){
|
||||
iconStatus ='<i class="layui-icon layui-icon-time"></i>';
|
||||
strStatus ='<div class="check-item-status">待审核</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(list[f].flow_type == 5){
|
||||
checkUser=list[f].flow_name+' ['+list[f].user_id_info[0].name+']';
|
||||
if(list[f].user_id_info.length>0){
|
||||
iconStatus ='<i class="layui-icon layui-icon-ok-circle" data-ok=""></i>';
|
||||
strStatus ='<div class="check-item-status">通过</div>';
|
||||
for(var m=0;m<list[f].user_id_info.length;m++){
|
||||
if(list[f].user_id_info[m].status == 2){
|
||||
iconStatus ='<i class="layui-icon layui-icon-close" data-no=""></i>';
|
||||
strStatus ='<div class="check-item-status">拒绝</div>';
|
||||
break;
|
||||
}
|
||||
if(list[f].user_id_info[m].status == 0){
|
||||
iconStatus ='<i class="layui-icon layui-icon-time"></i>';
|
||||
strStatus ='<div class="check-item-status">待审核</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(sort == list[f].sort){
|
||||
sortClass ='flow-this';
|
||||
iconStatus ='<i class="layui-icon layui-icon-time"></i>';
|
||||
strStatus ='<div class="check-item-status">当前审核</div>';
|
||||
}
|
||||
flowHtml+= '<div class="flow-flexbox check-item flow-flex-row '+sortClass+'" id="flow'+f+'">'+iconStatus+'\
|
||||
<div class="check-item-name">'+checkUser+'</div>'+strStatus+iconRight+'\
|
||||
</div>';
|
||||
}
|
||||
|
||||
$('#flowList').append(flowHtml);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
//监听提交
|
||||
$('#formBtn').on('click','span', function(data){
|
||||
let content=$('[name="content"]').val();
|
||||
let check_status=$(this).data('status');
|
||||
|
||||
let flow_type = $('input[name="flow_type"]').val();
|
||||
let check_node=0,check_admin_ids=0;
|
||||
if(flow_type == 0 && check_status==1){
|
||||
check_node = $('input[name="check_node"]:checked').val();
|
||||
check_admin_ids = $('input[name="check_admin_ids"]').val();
|
||||
if(!check_node){
|
||||
layer.msg('请选择下一审批节点');
|
||||
return false;
|
||||
}
|
||||
if(check_node == 2 && check_admin_ids==''){
|
||||
layer.msg('请选择下一审批人');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_status ==1 || check_status==2){
|
||||
if(content==''){
|
||||
layer.msg('请输入审批意见');
|
||||
return false;
|
||||
}
|
||||
let confirmTips='确定通过该审核?';
|
||||
if(check_status==2){
|
||||
confirmTips='确定拒绝该审核?';
|
||||
}
|
||||
layer.confirm(confirmTips, function(index){
|
||||
$.ajax({
|
||||
url: "/api/index/flow_check",
|
||||
type:'post',
|
||||
data:{
|
||||
id:contract_id,
|
||||
type:4,
|
||||
check_node:check_node,
|
||||
check_admin_ids:check_admin_ids,
|
||||
check:check_status,
|
||||
content:content
|
||||
},
|
||||
success: function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
parent.layui.pageTable.reload();
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
})
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
else if(check_status ==3){
|
||||
layer.prompt({
|
||||
formType: 2,
|
||||
title: '请输入撤回理由',
|
||||
area: ['500px', '120px'] //自定义文本域宽高
|
||||
}, function(value, index, elem){
|
||||
$.ajax({
|
||||
url: "/api/index/flow_check",
|
||||
type:'post',
|
||||
data:{
|
||||
id:contract_id,
|
||||
type:4,
|
||||
check:check_status,
|
||||
content:value
|
||||
},
|
||||
success: function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
parent.layui.pageTable.reload();
|
||||
location.reload();
|
||||
}
|
||||
}
|
||||
})
|
||||
layer.close(index);
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
</script>
|
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
/**
|
||||
======================
|
||||
*模块数据获取公共文件
|
||||
======================
|
||||
*/
|
||||
use think\facade\Db;
|
||||
|
||||
//客户查看编辑数据权限判断
|
||||
function customer_auth($uid,$customer_id,$ajax=0,$level=0)
|
||||
{
|
||||
$customer = Db::name('Customer')->where(['id' => $customer_id])->find();
|
||||
//是否是客户管理员
|
||||
$auth = isAuth($uid,'customer_admin');
|
||||
if($customer['belong_uid']==0){
|
||||
return $customer;
|
||||
}
|
||||
if($auth==1){
|
||||
return $customer;
|
||||
}
|
||||
else if($auth==0){
|
||||
$auth_array=[];
|
||||
if(!empty($customer['share_ids'])){
|
||||
$share_ids = explode(",",$customer['share_ids']);
|
||||
$auth_array = array_merge($auth_array,$share_ids);
|
||||
}
|
||||
array_push($auth_array,$customer['belong_uid']);
|
||||
//部门负责人
|
||||
$dids = get_department_role($uid);
|
||||
if(!in_array($uid,$auth_array) && !in_array($customer['belong_did'],$dids)){
|
||||
if($ajax == 1){
|
||||
to_assign(1,'无权限操作');
|
||||
}
|
||||
else{
|
||||
throw new \think\exception\HttpException(405, '无权限访问');
|
||||
}
|
||||
}
|
||||
else{
|
||||
return $customer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//读取分类列表
|
||||
function customer_grade()
|
||||
{
|
||||
$cate = Db::name('CustomerGrade')->where(['status' => 1])->select()->toArray();
|
||||
return $cate;
|
||||
}
|
||||
|
||||
//读取签约主体
|
||||
function customer_source()
|
||||
{
|
||||
$source = Db::name('CustomerSource')->where(['status' => 1])->select()->toArray();
|
||||
return $source;
|
||||
}
|
||||
|
||||
//读取联系人
|
||||
function customer_contact($cid)
|
||||
{
|
||||
$contact = Db::name('CustomerContact')->where(['delete_time' => 0,'cid'=>$cid])->select()->toArray();
|
||||
return $contact;
|
||||
}
|
||||
|
||||
//读取销售机会
|
||||
function customer_chance($cid)
|
||||
{
|
||||
$chance = Db::name('CustomerChance')->where(['delete_time' => 0,'cid'=>$cid])->select()->toArray();
|
||||
return $chance;
|
||||
}
|
||||
|
||||
//跟进方式
|
||||
function trace_type()
|
||||
{
|
||||
$type = ['其他','电话','微信','QQ','上门'];
|
||||
return $type;
|
||||
}
|
||||
|
||||
//跟进阶段
|
||||
function trace_stage()
|
||||
{
|
||||
$stage = ['未设置','立项评估','初期沟通','需求分析','方案制定','商务谈判','合同签订','失单'];
|
||||
return $stage;
|
||||
}
|
||||
|
||||
|
||||
//写入日志
|
||||
function to_log($uid,$type,$new,$old)
|
||||
{
|
||||
$log_data = [];
|
||||
$key_array = ['id', 'create_time', 'update_time', 'admin_id','belong_did','belong_time','distribute_time'];
|
||||
$type_array = ['customer_id', 'trace_id', 'contact_id', 'chance_id'];
|
||||
foreach ($new as $key => $value) {
|
||||
if (!in_array($key, $key_array)) {
|
||||
if(isset($old[$key]) && ($old[$key]!=$value)){
|
||||
$log_data[] = array(
|
||||
'field' => $key,
|
||||
'type' => $type,
|
||||
$type_array[$type] => $new['id'],
|
||||
'admin_id' => $uid,
|
||||
'old_content' => $old[$key],
|
||||
'new_content' => $value,
|
||||
'create_time' => time(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insertAll($log_data);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
勾股OA模块安装鉴定文件,请勿删除!!!!!此次模块标识为:customer
|
|
@ -0,0 +1,240 @@
|
|||
-- ----------------------------
|
||||
-- Table structure for oa_customer_grade
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_grade`;
|
||||
CREATE TABLE `oa_customer_grade` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '客户等级名称',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户等级';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_customer_grade
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_customer_grade` VALUES (1, '普通客户', 1, 1637987189, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (2, 'VIP客户', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (3, '白银客户', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (4, '黄金客户', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (5, '钻石客户', 1, 1637987199, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_source
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_source`;
|
||||
CREATE TABLE `oa_customer_source` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '客户渠道名称',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户来源';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_customer_source
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_customer_source` VALUES (1, '独立开发', 1, 1637987189, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (2, '微信公众号', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (3, '今日头条', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (4, '百度搜索', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (5, '销售活动', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (6, '电话来访', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (7, '客户介绍', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (8, '其他来源', 1, 1637987199, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_grade
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_grade`;
|
||||
CREATE TABLE `oa_customer_grade` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '客户等级名称',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户等级';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_customer_grade
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_customer_grade` VALUES (1, '普通客户', 1, 1637987189, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (2, 'VIP客户', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (3, '白银客户', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (4, '黄金客户', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_grade` VALUES (5, '钻石客户', 1, 1637987199, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_source
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_source`;
|
||||
CREATE TABLE `oa_customer_source` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(100) NOT NULL DEFAULT '' COMMENT '客户渠道名称',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '状态:-1删除 0禁用 1启用',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户来源';
|
||||
|
||||
-- ----------------------------
|
||||
-- Records of oa_customer_source
|
||||
-- ----------------------------
|
||||
INSERT INTO `oa_customer_source` VALUES (1, '独立开发', 1, 1637987189, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (2, '微信公众号', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (3, '今日头条', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (4, '百度搜索', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (5, '销售活动', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (6, '电话来访', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (7, '客户介绍', 1, 1637987199, 0);
|
||||
INSERT INTO `oa_customer_source` VALUES (8, '其他来源', 1, 1637987199, 0);
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer`;
|
||||
CREATE TABLE `oa_customer` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '客户名称',
|
||||
`source_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户来源id',
|
||||
`grade_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户等级id',
|
||||
`industry_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属行业id',
|
||||
`services_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户意向id',
|
||||
`provinceid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '省份id',
|
||||
`cityid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '城市id',
|
||||
`distid` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '区县id',
|
||||
`townid` bigint(20) NOT NULL DEFAULT 0 COMMENT '城镇id',
|
||||
`address` varchar(255) NOT NULL DEFAULT '' COMMENT '客户联系地址',
|
||||
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '客户状态:0未设置,1新进客户,2跟进客户,3正式客户,4流失客户',
|
||||
`intent_status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '意向状态:0未设置,1意向不明,2意向模糊,3意向一般,4意向强烈',
|
||||
`contact_first` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '第一联系人id',
|
||||
`admin_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '录入人',
|
||||
`belong_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属人',
|
||||
`belong_did` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属部门',
|
||||
`belong_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '获取时间',
|
||||
`distribute_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '分配时间',
|
||||
`share_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '共享人员,如:1,2,3',
|
||||
`content` text NULL COMMENT '客户描述',
|
||||
`market` text NULL COMMENT '主要经营业务',
|
||||
`remark` text NULL COMMENT '备注信息',
|
||||
`bank` varchar(60) NOT NULL DEFAULT '' COMMENT '开户银行',
|
||||
`bank_sn` varchar(60) NOT NULL DEFAULT '' COMMENT '银行帐号',
|
||||
`tax_num` varchar(100) NOT NULL DEFAULT '' COMMENT '纳税人识别号',
|
||||
`cperson_mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '开票电话',
|
||||
`cperson_address` varchar(200) NOT NULL DEFAULT '' COMMENT '开票地址',
|
||||
`discard_time` int(11) NOT NULL DEFAULT 0 COMMENT '废弃时间',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '添加时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1000 CHARACTER SET = utf8mb4 COMMENT = '客户表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_trace
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_trace`;
|
||||
CREATE TABLE `oa_customer_trace` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`cid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户ID',
|
||||
`contact_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '联系人id',
|
||||
`chance_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '销售机会id',
|
||||
`type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '跟进方式:0其他,1电话,2微信,3QQ,4上门',
|
||||
`stage` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '当前阶段:0未设置,1立项评估,2初期沟通,3需求分析,4方案制定,5商务谈判,6合同签订,7失单',
|
||||
`content` text NULL COMMENT '跟进内容',
|
||||
`follow_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '跟进时间',
|
||||
`next_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '下次跟进时间',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户跟进记录表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_contact
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_contact`;
|
||||
CREATE TABLE `oa_customer_contact` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`cid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户ID',
|
||||
`is_default` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否是第一联系人',
|
||||
`name` varchar(100) NOT NULL DEFAULT '' COMMENT '姓名',
|
||||
`sex` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户性别:0未知,1男,2女',
|
||||
`mobile` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号码',
|
||||
`qq` varchar(20) NOT NULL DEFAULT '' COMMENT 'QQ号',
|
||||
`wechat` varchar(100) NOT NULL DEFAULT '' COMMENT '微信号',
|
||||
`email` varchar(100) NOT NULL DEFAULT '' COMMENT '邮件地址',
|
||||
`nickname` varchar(50) NOT NULL DEFAULT '' COMMENT '称谓',
|
||||
`department` varchar(50) NOT NULL DEFAULT '' COMMENT '部门',
|
||||
`position` varchar(50) NOT NULL DEFAULT '' COMMENT '职务',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户联系人表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_chance
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_chance`;
|
||||
CREATE TABLE `oa_customer_chance` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`title` varchar(255) NOT NULL DEFAULT '' COMMENT '销售机会主题',
|
||||
`cid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户ID',
|
||||
`contact_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '联系人id',
|
||||
`services_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '需求服务id',
|
||||
`stage` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '当前阶段:0未设置,1立项评估,2初期沟通,3需求分析,4方案制定,5商务谈判,6合同签订,7失单',
|
||||
`content` text NULL COMMENT '需求描述',
|
||||
`discovery_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '发现时间',
|
||||
`expected_time` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '预计签单时间',
|
||||
`expected_amount` decimal(15, 2) NULL DEFAULT 0.00 COMMENT '预计签单金额',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`belong_uid` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '所属人',
|
||||
`assist_ids` varchar(500) NOT NULL DEFAULT '' COMMENT '协助人员,如:1,2,3',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '更新时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户销售机会表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_file
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_file`;
|
||||
CREATE TABLE `oa_customer_file` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`customer_id` int(11) UNSIGNED NOT NULL COMMENT '关联客户id',
|
||||
`file_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '相关联附件id',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '创建人',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
`update_time` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
|
||||
`delete_time` int(11) NOT NULL DEFAULT 0 COMMENT '删除时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户附件关联表';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for oa_customer_log
|
||||
-- ----------------------------
|
||||
DROP TABLE IF EXISTS `oa_customer_log`;
|
||||
CREATE TABLE `oa_customer_log` (
|
||||
`id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`type` tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作类型:0客户,1跟进记录,2客户联系人,3销售机会',
|
||||
`action` varchar(100) NOT NULL DEFAULT 'edit' COMMENT '动作:add,edit,del,check,upload',
|
||||
`field` varchar(100) NOT NULL DEFAULT '' COMMENT '字段',
|
||||
`customer_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '关联客户id',
|
||||
`trace_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '跟进记录id',
|
||||
`contact_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '客户联系人id',
|
||||
`chance_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '销售机会id',
|
||||
`admin_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作人',
|
||||
`old_content` text NULL COMMENT '修改前的内容',
|
||||
`new_content` text NULL COMMENT '修改后的内容',
|
||||
`remark` text NULL COMMENT '补充备注',
|
||||
`create_time` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COMMENT = '客户操作记录表';
|
||||
|
||||
INSERT INTO `oa_data_auth` VALUES ((SELECT MAX(id) +1 FROM `oa_data_auth` a), '客户管理员','customer_admin','拥有该权限的员工可以查看、转移所有客户。', 'customer', '',10,0,0,'','','',1656143065, 0);
|
|
@ -0,0 +1,383 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
declare (strict_types = 1);
|
||||
namespace app\customer\controller;
|
||||
|
||||
use app\api\BaseController;
|
||||
use app\customer\model\CustomerTrace;
|
||||
use app\customer\model\CustomerContact;
|
||||
use app\customer\model\CustomerChance;
|
||||
use app\customer\model\CustomerLog;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Api extends BaseController
|
||||
{
|
||||
|
||||
//分配客户
|
||||
public function distribute()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$params = get_params();
|
||||
//是否是客户管理员
|
||||
$auth = isAuth($this->uid,'customer_admin');
|
||||
if($auth==0){
|
||||
return to_assign(1, "只有客户管理员才有权限操作");
|
||||
}
|
||||
$data['id'] = $params['id'];
|
||||
$data['belong_uid'] = $params['uid'];
|
||||
$data['belong_did'] = $params['did'];
|
||||
$data['distribute_time'] = time();
|
||||
if (Db::name('Customer')->update($data) !== false) {
|
||||
add_log('allot', $data['id'],[],'客户');
|
||||
to_log($this->uid,0,$data,['belong_uid'=>0]);
|
||||
return to_assign(0, "操作成功");
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//跟进记录列表
|
||||
public function get_trace()
|
||||
{
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$where[] = ['delete_time', '=', 0];
|
||||
$where[] = ['cid', '=', $param['customer_id']];
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerTrace::where($where)
|
||||
->order('create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->admin_name = Db::name('Admin')->where(['id' => $item->admin_id])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i:s', (int) $item->create_time);
|
||||
$item->follow_time = date('Y-m-d H:i', (int) $item->follow_time);
|
||||
$item->next_time = date('Y-m-d H:i', (int) $item->next_time);
|
||||
$item->stage_name = CustomerTrace::$Stage[(int) $item->stage];
|
||||
$item->type_name = CustomerTrace::$Type[(int) $item->type];
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
}
|
||||
|
||||
//添加跟进记录
|
||||
public function add_trace()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if(isset($param['follow_time'])){
|
||||
$param['follow_time'] = strtotime($param['follow_time']);
|
||||
}
|
||||
if(isset($param['next_time'])){
|
||||
$param['next_time'] = strtotime($param['next_time']);
|
||||
}
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
$param['update_time'] = time();
|
||||
$old = CustomerTrace::where(['id' => $param['id']])->find();
|
||||
if($this->uid!=$old['admin_id'] && get_user_role($this->uid,$old['admin_id'])==0){
|
||||
return to_assign(1, "只有所属员工才有权限操作");
|
||||
}
|
||||
$res = CustomerTrace::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param,'客户跟进记录');
|
||||
to_log($this->uid,1,$param,$old);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$tid = CustomerTrace::strict(false)->field(true)->insertGetId($param);
|
||||
if ($tid) {
|
||||
add_log('add', $tid, $param,'客户跟进记录');
|
||||
$log_data = array(
|
||||
'field' => 'new',
|
||||
'action' => 'add',
|
||||
'type' => 1,
|
||||
'customer_id' => $param['cid'],
|
||||
'admin_id' => $param['admin_id'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$customer_id = isset($param['cid']) ? $param['cid'] : 0;
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
if ($id > 0) {
|
||||
View::assign('detail', (new CustomerTrace())->detail($id));
|
||||
return view('edit_trace');
|
||||
}
|
||||
$customer_name = Db::name('Customer')->where('id',$customer_id)->value('name');
|
||||
View::assign('customer_id', $customer_id);
|
||||
View::assign('customer_name', $customer_name);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//查看跟进记录
|
||||
public function view_trace()
|
||||
{
|
||||
$param = get_params();
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
$detail = (new CustomerTrace())->detail($id);
|
||||
if(empty($detail)){
|
||||
echo '<div style="text-align:center;color:red;margin-top:20%;">找不到该跟进记录</div>';exit;
|
||||
}
|
||||
View::assign('detail',$detail);
|
||||
return view();
|
||||
}
|
||||
|
||||
//删除跟进记录
|
||||
public function delete_trace()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$param = get_params();
|
||||
$admin_id = Db::name('CustomerTrace')->where(['id' => $param['id']])->value('admin_id');
|
||||
if($admin_id != $this->uid){
|
||||
return to_assign(1, '你不是该跟进记录的创建人,无权限删除');
|
||||
}
|
||||
$param['delete_time'] = time();
|
||||
$res = CustomerTrace::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('delete', $param['id'], $param,'客户跟进记录');
|
||||
to_log($this->uid,1,$param,['delete_time'=>0]);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, '参数错误');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//销售机会列表
|
||||
public function get_chance()
|
||||
{
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$where[] = ['delete_time', '=', 0];
|
||||
$where[] = ['cid', '=', $param['customer_id']];
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerChance::where($where)
|
||||
->order('create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->belong_name = Db::name('Admin')->where(['id' => $item->belong_uid])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i:s', (int) $item->create_time);
|
||||
$item->discovery_time = date('Y-m-d', (int) $item->discovery_time);
|
||||
$item->expected_time = date('Y-m-d', (int) $item->expected_time);
|
||||
$item->stage_name = CustomerTrace::$Stage[(int) $item->stage];
|
||||
$item->services_name = Db::name('Services')->where(['id' => $item->services_id])->value('title');
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
}
|
||||
|
||||
//添加销售机会
|
||||
public function add_chance()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if(isset($param['discovery_time'])){
|
||||
$param['discovery_time'] = strtotime($param['discovery_time']);
|
||||
}
|
||||
if(isset($param['expected_time'])){
|
||||
$param['expected_time'] = strtotime($param['expected_time']);
|
||||
}
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
$param['update_time'] = time();
|
||||
$old = CustomerChance::where(['id' => $param['id']])->find();
|
||||
if($this->uid!=$old['admin_id'] && get_user_role($this->uid,$old['admin_id'])==0){
|
||||
return to_assign(1, "只有所属员工才有权限操作");
|
||||
}
|
||||
$res = CustomerChance::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param,'客户销售机会');
|
||||
to_log($this->uid,3,$param,$old);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$tid = CustomerChance::strict(false)->field(true)->insertGetId($param);
|
||||
if ($tid) {
|
||||
add_log('add', $tid, $param,'客户销售机会');
|
||||
$log_data = array(
|
||||
'field' => 'new',
|
||||
'action' => 'add',
|
||||
'type' => 3,
|
||||
'customer_id' => $param['cid'],
|
||||
'admin_id' => $param['admin_id'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$customer_id = isset($param['cid']) ? $param['cid'] : 0;
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
if ($id > 0) {
|
||||
View::assign('detail', (new CustomerChance())->detail($id));
|
||||
return view('edit_chance');
|
||||
}
|
||||
$customer_name = Db::name('Customer')->where('id',$customer_id)->value('name');
|
||||
View::assign('customer_id', $customer_id);
|
||||
View::assign('customer_name', $customer_name);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//添加销售机会
|
||||
public function view_chance()
|
||||
{
|
||||
$param = get_params();
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
$detail = (new CustomerChance())->detail($id);
|
||||
if(empty($detail)){
|
||||
echo '<div style="text-align:center;color:red;margin-top:20%;">找不到该销售机会</div>';exit;
|
||||
}
|
||||
View::assign('detail',$detail);
|
||||
return view();
|
||||
}
|
||||
|
||||
//删除销售机会
|
||||
public function delete_chance()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$param = get_params();
|
||||
$admin_id = Db::name('CustomerChance')->where(['id' => $param['id']])->value('admin_id');
|
||||
if($admin_id != $this->uid){
|
||||
return to_assign(1, '你不是该跟销售机会的创建人,无权限删除');
|
||||
}
|
||||
$param['delete_time'] = time();
|
||||
$res = CustomerChance::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('delete', $param['id'], $param,'客户销售机会');
|
||||
to_log($this->uid,3,$param,['delete_time'=>0]);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, '参数错误');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//获取联系人数据
|
||||
public function get_contact()
|
||||
{
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$where[] = ['delete_time', '=', 0];
|
||||
$where[] = ['cid', '=', $param['customer_id']];
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerContact::where($where)
|
||||
->order('create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->admin_name = Db::name('Admin')->where(['id' => $item->admin_id])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i:s', (int) $item->create_time);
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
}
|
||||
|
||||
//设置联系人
|
||||
public function set_contact()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$detail= Db::name('CustomerContact')->where(['id' => $param['id']])->find();
|
||||
CustomerContact::where(['cid' => $detail['cid']])->strict(false)->field(true)->update(['is_default'=>0]);
|
||||
$res = CustomerContact::where(['id' => $param['id']])->update(['is_default'=>1]);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param,'客户联系人');
|
||||
to_log($this->uid,2,$param,$detail);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, '参数错误');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//添加附件
|
||||
public function add_file()
|
||||
{
|
||||
$param = get_params();
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$fid = Db::name('CustomerFile')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($fid) {
|
||||
$log_data = array(
|
||||
'field' => 'file',
|
||||
'action' => 'upload',
|
||||
'customer_id' => $param['customer_id'],
|
||||
'admin_id' => $param['admin_id'],
|
||||
'old_content' => '',
|
||||
'new_content' => $param['file_name'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, '上传成功', $fid);
|
||||
}
|
||||
}
|
||||
|
||||
//删除附件
|
||||
public function delete_file()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$id = get_params("id");
|
||||
$data['id'] = $id;
|
||||
$data['delete_time'] = time();
|
||||
if (Db::name('CustomerFile')->update($data) !== false) {
|
||||
$detail = Db::name('CustomerFile')->where('id', $id)->find();
|
||||
$file_name = Db::name('File')->where('id', $detail['file_id'])->value('name');
|
||||
$log_data = array(
|
||||
'field' => 'file',
|
||||
'action' => 'delete',
|
||||
'customer_id' => $detail['customer_id'],
|
||||
'admin_id' => $this->uid,
|
||||
'new_content' => $file_name,
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "删除成功");
|
||||
} else {
|
||||
return to_assign(1, "删除失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//操作日志列表
|
||||
public function customer_log()
|
||||
{
|
||||
$param = get_params();
|
||||
$list = new CustomerLog();
|
||||
$content = $list->customer_log($param);
|
||||
return to_assign(0, '', $content);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,179 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\customer\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\customer\model\CustomerChance;
|
||||
use app\customer\validate\CustomerChanceCheck;
|
||||
use app\customer\model\CustomerTrace;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Chance extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.title|c.name', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['stage'])) {
|
||||
$where[] = ['a.stage', '=', $param['stage']];
|
||||
}
|
||||
//按时间检索
|
||||
if (!empty($param['diff_time'])) {
|
||||
$diff_time =explode('~', $param['diff_time']);
|
||||
$where[] = ['a.expected_time', 'between', [strtotime(urldecode($diff_time[0])),strtotime(urldecode($diff_time[1]))]];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'customer_admin');
|
||||
|
||||
if (empty($param['uid'])) {
|
||||
if($auth==0){
|
||||
$dids = get_department_role($this->uid);
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['c.belong_did', 'in', $dids];
|
||||
}
|
||||
$whereOr[] =['c.belong_uid', '=', $uid];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',c.share_ids)")];
|
||||
}
|
||||
}
|
||||
else{
|
||||
$where[] = ['a.belong_uid', '=', $param['uid']];
|
||||
}
|
||||
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerChance::where($where)
|
||||
->where(function ($query) use($whereOr) {
|
||||
$query->whereOr($whereOr);
|
||||
})
|
||||
->field('a.*,c.name as customer')
|
||||
->alias('a')
|
||||
->join('customer c', 'a.cid = c.id')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->belong_name = Db::name('Admin')->where(['id' => $item->belong_uid])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i:s', (int) $item->create_time);
|
||||
$item->discovery_time = date('Y-m-d', (int) $item->discovery_time);
|
||||
$item->expected_time = date('Y-m-d', (int) $item->expected_time);
|
||||
$item->stage_name = CustomerTrace::$Stage[(int) $item->stage];
|
||||
$item->services_name = Db::name('Services')->where(['id' => $item->services_id])->value('title');
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//添加销售机会
|
||||
public function chance_add()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if(isset($param['discovery_time'])){
|
||||
$param['discovery_time'] = strtotime($param['discovery_time']);
|
||||
}
|
||||
if(isset($param['expected_time'])){
|
||||
$param['expected_time'] = strtotime($param['expected_time']);
|
||||
}
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
$param['update_time'] = time();
|
||||
$old = CustomerChance::where(['id' => $param['id']])->find();
|
||||
if($this->uid!=$old['admin_id'] && get_user_role($this->uid,$old['admin_id'])==0){
|
||||
return to_assign(1, "只有所属员工或者部门负责人才有权限操作");
|
||||
}
|
||||
$res = CustomerChance::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
to_log($this->uid,3,$param,$old);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$tid = CustomerChance::strict(false)->field(true)->insertGetId($param);
|
||||
if ($tid) {
|
||||
add_log('add', $tid, $param,'客户销售机会');
|
||||
$log_data = array(
|
||||
'field' => 'new',
|
||||
'action' => 'add',
|
||||
'type' => 3,
|
||||
'customer_id' => $param['cid'],
|
||||
'admin_id' => $param['admin_id'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$customer_id = isset($param['cid']) ? $param['cid'] : 0;
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
if ($id > 0) {
|
||||
View::assign('detail', (new CustomerChance())->detail($id));
|
||||
return view('chance_edit');
|
||||
}
|
||||
$customer_name = Db::name('Customer')->where('id',$customer_id)->value('name');
|
||||
View::assign('customer_id', $customer_id);
|
||||
View::assign('customer_name', $customer_name);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//查看销售机会
|
||||
public function chance_view()
|
||||
{
|
||||
$param = get_params();
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
$detail = (new CustomerChance())->detail($id);
|
||||
if(empty($detail)){
|
||||
echo '<div style="text-align:center;color:red;margin-top:20%;">找不到该销售机会</div>';exit;
|
||||
}
|
||||
View::assign('detail',$detail);
|
||||
return view();
|
||||
}
|
||||
|
||||
//删除销售机会
|
||||
public function chance_del()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$param = get_params();
|
||||
$admin_id = Db::name('CustomerChance')->where(['id' => $param['id']])->value('admin_id');
|
||||
if($admin_id != $this->uid){
|
||||
return to_assign(1, '你不是该跟销售机会的创建人,无权限删除');
|
||||
}
|
||||
$param['delete_time'] = time();
|
||||
$res = CustomerChance::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('delete', $param['id'], $param,'客户销售机会');
|
||||
to_log($this->uid,3,$param,['delete_time'=>0]);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, '参数错误');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\customer\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\customer\model\CustomerContact;
|
||||
use app\customer\validate\CustomerContactCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Contact extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.name|a.mobile|c.name', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'customer_admin');
|
||||
if($auth==0){
|
||||
$dids = get_department_role($this->uid);
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['c.belong_did', 'in', $dids];
|
||||
}
|
||||
$whereOr[] =['c.belong_uid', '=', $uid];
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',c.share_ids)")];
|
||||
}
|
||||
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerContact::where($where)
|
||||
->where(function ($query) use($whereOr) {
|
||||
$query->whereOr($whereOr);
|
||||
})
|
||||
->field('a.*,c.name as customer')
|
||||
->alias('a')
|
||||
->join('customer c', 'a.cid = c.id')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->create_time = date('Y-m-d H:i:s', (int) $item->create_time);
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//添加
|
||||
public function contact_add()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(CustomerContactCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$detail= Db::name('CustomerContact')->where(['id' => $param['id']])->find();
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('CustomerContact')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
to_log($this->uid,2,$param,$detail);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(CustomerContactCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$count= Db::name('CustomerContact')->where(['cid' => $param['cid'],'delete_time' => 0])->count();
|
||||
if($count == 0){
|
||||
$param['is_default'] = 1;
|
||||
}
|
||||
$param['admin_id'] = $this->uid;
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('CustomerContact')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
$log_data = array(
|
||||
'field' => 'new',
|
||||
'action' => 'add',
|
||||
'type' => 2,
|
||||
'customer_id' => $insertId,
|
||||
'admin_id' => $param['admin_id'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
} else {
|
||||
$customer_id = isset($param['cid']) ? $param['cid'] : 0;
|
||||
$id = isset($param['id']) ? $param['id'] : 0;
|
||||
if ($id > 0) {
|
||||
View::assign('detail', (new CustomerContact())->detail($id));
|
||||
return view('contact_edit');
|
||||
}
|
||||
$customer_name = Db::name('Customer')->where('id',$customer_id)->value('name');
|
||||
View::assign('customer_id', $customer_id);
|
||||
View::assign('customer_name', $customer_name);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//设置
|
||||
public function contact_del()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$param = get_params();
|
||||
$contact = Db::name('CustomerContact')->where(['id' => $param['id']])->find();
|
||||
if($contact['is_default'] == 1){
|
||||
return to_assign(1, '客户的首要联系人不能删除');
|
||||
}
|
||||
if($contact['admin_id'] != $this->uid){
|
||||
return to_assign(1, '你不是该联系人的创建人,无权限删除');
|
||||
}
|
||||
$param['delete_time'] = time();
|
||||
$res = CustomerContact::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
to_log($this->uid,2,$param,['delete_time'=>0]);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, '参数错误');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\customer\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\customer\validate\CustomerGradeCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Grade extends BaseController
|
||||
{
|
||||
//类别
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('CustomerGrade')->order('create_time asc')->select();
|
||||
return to_assign(0, '', $cate);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//添加
|
||||
public function grade_add()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(CustomerGradeCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('CustomerGrade')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(CustomerGradeCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('CustomerGrade')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//类别设置
|
||||
public function grade_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$res = Db::name('CustomerGrade')->strict(false)->field('id,status')->update($param);
|
||||
if ($res) {
|
||||
if($param['status'] == 0){
|
||||
add_log('disable', $param['id'], $param);
|
||||
}
|
||||
else if($param['status'] == 1){
|
||||
add_log('recovery', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(0, '操作失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,598 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\customer\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\customer\model\Customer as CustomerList;
|
||||
use app\customer\validate\CustomerCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Index extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$tab = isset($param['tab']) ? $param['tab'] : 0;
|
||||
$where = array();
|
||||
$whereOr = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.name|cc.name|cc.mobile', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['status'])) {
|
||||
$where[] = ['a.status', '=', $param['status']];
|
||||
}
|
||||
if (!empty($param['grade_id'])) {
|
||||
$where[] = ['a.grade_id', '=', $param['grade_id']];
|
||||
}
|
||||
if (!empty($param['source_id'])) {
|
||||
$where[] = ['a.source_id', '=', $param['source_id']];
|
||||
}
|
||||
if (!empty($param['type'])) {
|
||||
$where[] = ['a.intent_status', '=', $param['type']];
|
||||
}
|
||||
if (!empty($param['follow_time'])) {
|
||||
$follow_time =explode('~', $param['follow_time']);
|
||||
$where[] = ['ct.follow_time', 'between', [strtotime(urldecode($follow_time[0])),strtotime(urldecode($follow_time[1]))]];
|
||||
}
|
||||
if (!empty($param['next_time'])) {
|
||||
$next_time =explode('~', $param['next_time']);
|
||||
$where[] = ['ct.next_time', 'between', [strtotime(urldecode($next_time[0])),strtotime(urldecode($next_time[1]))]];
|
||||
}
|
||||
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'customer_admin');
|
||||
if (!empty($param['uid']) && $auth == 1) {
|
||||
$where[] =['a.belong_uid', '=', $param['uid']];
|
||||
}
|
||||
else{
|
||||
$dids = get_department_role($uid);
|
||||
if($auth == 0){
|
||||
if($tab == 1){
|
||||
$whereOr[] =['a.belong_uid', '=', $uid];
|
||||
}
|
||||
else if($tab == 2){
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['a.belong_did', 'in', $dids];
|
||||
}
|
||||
else{
|
||||
$whereOr[] =['a.belong_did', '=', 0];
|
||||
$where[] =['a.belong_uid', '>', 0];
|
||||
}
|
||||
}
|
||||
else if($tab == 3){
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.share_ids)")];
|
||||
}
|
||||
else{
|
||||
$whereOr[] =['a.belong_uid', '=', $uid];
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['a.belong_did', 'in', $dids];
|
||||
}
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.share_ids)")];
|
||||
}
|
||||
}
|
||||
else if($auth ==1 ){
|
||||
if($tab == 1){
|
||||
$whereOr[] =['a.belong_uid', '=', $uid];
|
||||
}
|
||||
else if($tab == 2){
|
||||
if(!empty($dids)){
|
||||
$whereOr[] =['a.belong_did', 'in', $dids];
|
||||
}
|
||||
else{
|
||||
$whereOr[] =['a.belong_did', '=', 0];
|
||||
$where[] =['a.belong_uid', '>', 0];
|
||||
}
|
||||
}
|
||||
else if($tab == 3){
|
||||
$whereOr[] = ['', 'exp', Db::raw("FIND_IN_SET('{$uid}',a.share_ids)")];
|
||||
}
|
||||
else{
|
||||
$whereOr[] =['a.belong_uid', '>', 0];
|
||||
}
|
||||
}
|
||||
}
|
||||
$cc_sql= Db::name('CustomerContact')->group('cid,name,mobile,qq,wechat,email')->field('cid,name,mobile,qq,wechat,email')->buildSql();
|
||||
$ct_sql= Db::name('CustomerTrace')->group('cid')->field('cid,MAX(follow_time) AS follow_time,MAX(next_time) AS next_time')->buildSql();
|
||||
$orderby = 'ct.next_time desc,a.create_time desc';
|
||||
if(isset($param['orderby'])){
|
||||
$orderby = 'ct.'.$param['orderby'];
|
||||
}
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerList::where($where)
|
||||
->where(function ($query) use($whereOr) {
|
||||
$query->whereOr($whereOr);
|
||||
})
|
||||
->field('a.*,d.title as belong_department,g.title as grade,s.title as source,i.title as industry,ct.follow_time,ct.next_time')
|
||||
->alias('a')
|
||||
->join('customer_source s', 'a.source_id = s.id')
|
||||
->join('customer_grade g', 'a.grade_id = g.id')
|
||||
->join('industry i', 'a.industry_id = i.id')
|
||||
->join('department d', 'a.belong_did = d.id')
|
||||
->join($ct_sql.' ct', 'ct.cid = a.id','left')
|
||||
->join($cc_sql.' cc', 'a.id = cc.cid','left')
|
||||
->group('a.id')
|
||||
->order($orderby)
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->belong_name = Db::name('Admin')->where(['id' => $item->belong_uid])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i', $item->create_time);
|
||||
if($item->update_time == 0){
|
||||
$item->update_time='-';
|
||||
}
|
||||
else{
|
||||
$item->update_time = date('Y-m-d H:i', $item->update_time);
|
||||
}
|
||||
$item->intent_status_name = CustomerList::$IntentStatus[(int) $item->intent_status];
|
||||
$item->status_name = CustomerList::$Status[(int) $item->status];
|
||||
$contact = Db::name('CustomerContact')->where(['is_default'=>1,'cid' => $item->id])->find();
|
||||
if(!empty($contact)){
|
||||
$item->user = $contact['name'];
|
||||
$item->mobile = $contact['mobile'];
|
||||
$item->qq = $contact['qq'];
|
||||
$item->wechat = $contact['wechat'];
|
||||
}
|
||||
|
||||
if($item->services_id == 0){
|
||||
$item->services_name = '-';
|
||||
}
|
||||
else{
|
||||
$item->services_name = Db::name('Services')->where(['id' => $item->services_id])->value('title');
|
||||
}
|
||||
|
||||
if(empty($item->follow_time)){
|
||||
$item->follow_time = '-';
|
||||
}
|
||||
else{
|
||||
$item->follow_time = date('Y-m-d H:i:s', $item->follow_time);
|
||||
}
|
||||
if(empty($item->next_time)){
|
||||
$item->next_time = '-';
|
||||
}
|
||||
else{
|
||||
$item->next_time = date('Y-m-d H:i:s', $item->next_time);
|
||||
}
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
$uid = $this->uid;
|
||||
$auth = isAuth($uid,'customer_admin');
|
||||
View::assign('auth', $auth);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//公海客户
|
||||
public function sea()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.name', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['status'])) {
|
||||
$where[] = ['a.status', '=', $param['status']];
|
||||
}
|
||||
if (!empty($param['industry_id'])) {
|
||||
$where[] = ['a.industry_id', '=', $param['industry_id']];
|
||||
}
|
||||
if (!empty($param['source_id'])) {
|
||||
$where[] = ['a.source_id', '=', $param['source_id']];
|
||||
}
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
$where[] = ['a.belong_uid', '=', 0];
|
||||
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerList::where($where)
|
||||
->field('a.*,d.title as belong_department,g.title as grade,s.title as source,i.title as industry')
|
||||
->alias('a')
|
||||
->join('customer_source s', 'a.source_id = s.id')
|
||||
->join('customer_grade g', 'a.grade_id = g.id')
|
||||
->join('industry i', 'a.industry_id = i.id')
|
||||
->join('department d', 'a.belong_did = d.id','LEFT')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->belong_name = Db::name('Admin')->where(['id' => $item->belong_uid])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i', $item->create_time);
|
||||
if($item->update_time == 0){
|
||||
$item->update_time='-';
|
||||
}
|
||||
else{
|
||||
$item->update_time = date('Y-m-d H:i', $item->update_time);
|
||||
}
|
||||
$item->intent_status_name = CustomerList::$IntentStatus[(int) $item->intent_status];
|
||||
$item->status_name = CustomerList::$Status[(int) $item->status];
|
||||
$contact = Db::name('CustomerContact')->where(['is_default'=>1,'cid' => $item->id])->find();
|
||||
if(!empty($contact)){
|
||||
$item->user = $contact['name'];
|
||||
$item->mobile = $contact['mobile'];
|
||||
$item->qq = $contact['qq'];
|
||||
$item->wechat = $contact['wechat'];
|
||||
}
|
||||
|
||||
if($item->services_id == 0){
|
||||
$item->services_name = '-';
|
||||
}
|
||||
else{
|
||||
$item->services_name = Db::name('Services')->where(['id' => $item->services_id])->value('title');
|
||||
}
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//移入公海
|
||||
public function to_sea()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$id = get_params("id");
|
||||
$uid = $this->uid;
|
||||
//是否有权限
|
||||
$customer = customer_auth($uid,$id,1,1);
|
||||
$data['id'] = $id;
|
||||
$data['belong_uid'] = 0;
|
||||
$data['belong_did'] = 0;
|
||||
$data['belong_time'] = 0;
|
||||
if (Db::name('Customer')->update($data) !== false) {
|
||||
add_log('tosea', $id);
|
||||
$log_data = array(
|
||||
'field' => 'belong',
|
||||
'action' => 'tosea',
|
||||
'type' => 0,
|
||||
'customer_id' => $data['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "操作成功");
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//废池客户
|
||||
public function trash()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
if (!empty($param['keywords'])) {
|
||||
$where[] = ['a.id|a.name|c.title', 'like', '%' . $param['keywords'] . '%'];
|
||||
}
|
||||
if (!empty($param['status'])) {
|
||||
$where[] = ['a.status', '=', $param['status']];
|
||||
}
|
||||
$where[] = ['a.delete_time', '>', 0];
|
||||
$where[] = ['a.belong_uid', '=', 0];
|
||||
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = CustomerList::where($where)
|
||||
->field('a.*,d.title as belong_department,g.title as grade,s.title as source,i.title as industry')
|
||||
->alias('a')
|
||||
->join('customer_source s', 'a.source_id = s.id')
|
||||
->join('customer_grade g', 'a.grade_id = g.id')
|
||||
->join('industry i', 'a.industry_id = i.id')
|
||||
->join('department d', 'a.belong_did = d.id','LEFT')
|
||||
->order('a.create_time desc')
|
||||
->paginate($rows, false, ['query' => $param])
|
||||
->each(function ($item, $key) {
|
||||
$item->belong_name = Db::name('Admin')->where(['id' => $item->belong_uid])->value('name');
|
||||
$item->create_time = date('Y-m-d H:i', $item->create_time);
|
||||
if($item->update_time == 0){
|
||||
$item->update_time='-';
|
||||
}
|
||||
else{
|
||||
$item->update_time = date('Y-m-d H:i', $item->update_time);
|
||||
}
|
||||
$item->intent_status_name = CustomerList::$IntentStatus[(int) $item->intent_status];
|
||||
$item->status_name = CustomerList::$Status[(int) $item->status];
|
||||
$contact = Db::name('CustomerContact')->where(['is_default'=>1,'cid' => $item->id])->find();
|
||||
if(!empty($contact)){
|
||||
$item->user = $contact['name'];
|
||||
$item->mobile = $contact['mobile'];
|
||||
$item->qq = $contact['qq'];
|
||||
$item->wechat = $contact['wechat'];
|
||||
}
|
||||
|
||||
if($item->services_id == 0){
|
||||
$item->services_name = '-';
|
||||
}
|
||||
else{
|
||||
$item->services_name = Db::name('Services')->where(['id' => $item->services_id])->value('title');
|
||||
}
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//抢客宝
|
||||
public function rush()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
$where = array();
|
||||
$where[] = ['a.delete_time', '=', 0];
|
||||
$where[] = ['a.belong_uid', '=', 0];
|
||||
$content = CustomerList::where($where)
|
||||
->field('a.*,d.title as belong_department,g.title as grade,s.title as source,i.title as industry')
|
||||
->alias('a')
|
||||
->join('customer_source s', 'a.source_id = s.id')
|
||||
->join('customer_grade g', 'a.grade_id = g.id')
|
||||
->join('industry i', 'a.industry_id = i.id')
|
||||
->join('department d', 'a.belong_did = d.id','LEFT')
|
||||
->orderRaw('rand()')
|
||||
->limit(10)
|
||||
->paginate()
|
||||
->each(function ($item, $key) {
|
||||
$item->create_time = date('Y-m-d H:i:s', (int) $item->create_time);
|
||||
$contact = Db::name('CustomerContact')->where(['is_default'=>1,'cid' => $item->id])->find();
|
||||
if(!empty($contact)){
|
||||
$item->user = $contact['name'];
|
||||
$item->mobile = $contact['mobile'];
|
||||
$item->qq = $contact['qq'];
|
||||
$item->wechat = $contact['wechat'];
|
||||
}
|
||||
if($item->services_id == 0){
|
||||
$item->services_name = '-';
|
||||
}
|
||||
else{
|
||||
$item->services_name = Db::name('Services')->where(['id' => $item->services_id])->value('title');
|
||||
}
|
||||
});
|
||||
return table_assign(0, '', $content);
|
||||
} else {
|
||||
$time = strtotime(date('Y-m-d')." 00:00:00");
|
||||
$max_num = Db::name('DataAuth')->where('name','customer_admin')->value('expected_1');
|
||||
$count = Db::name('Customer')->where([['belong_time','>',$time],['belong_uid','=',$this->uid]])->count();
|
||||
View::assign('max_num', $max_num);
|
||||
View::assign('count', $count);
|
||||
return view();
|
||||
}
|
||||
}
|
||||
|
||||
//添加&&编辑
|
||||
public function add()
|
||||
{
|
||||
$param = get_params();
|
||||
if (request()->isAjax()) {
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(CustomerCheck::class)->scene($param['scene'])->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$customer = customer_auth($this->uid,$param['id'],1);
|
||||
$param['update_time'] = time();
|
||||
$res = customerList::strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
to_log($this->uid,0,$param,$customer);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
validate(CustomerCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$param['admin_id'] = $this->uid;
|
||||
$cid = CustomerList::strict(false)->field(true)->insertGetId($param);
|
||||
|
||||
$contact = [
|
||||
'name' => $param['c_name'],
|
||||
'mobile' => $param['c_mobile'],
|
||||
'sex' => $param['c_sex'],
|
||||
'qq' => $param['c_qq'],
|
||||
'wechat' => $param['c_wechat'],
|
||||
'email' => $param['c_email'],
|
||||
'cid' => $cid,
|
||||
'is_default' => 1,
|
||||
'create_time' => time(),
|
||||
'admin_id' => $this->uid
|
||||
];
|
||||
Db::name('CustomerContact')->strict(false)->field(true)->insert($contact);
|
||||
if ($cid) {
|
||||
add_log('add', $cid, $param);
|
||||
$log_data = array(
|
||||
'field' => 'new',
|
||||
'action' => 'add',
|
||||
'type' => 0,
|
||||
'customer_id' => $cid,
|
||||
'admin_id' => $param['admin_id'],
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, '操作失败');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
$sea = isset($param['sea']) ? $param['sea'] : 0;
|
||||
//查看权限判断
|
||||
$customer = customer_auth($this->uid,$param['id']);
|
||||
$detail = (new CustomerList())->detail($param['id']);
|
||||
View::assign('sea', $sea);
|
||||
View::assign('detail', $detail);
|
||||
return view('edit');
|
||||
}
|
||||
else{
|
||||
$sea = isset($param['sea']) ? $param['sea'] : 0;
|
||||
View::assign('sea', $sea);
|
||||
View::assign('userinfo', get_admin($this->uid));
|
||||
return view();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//查看
|
||||
public function view()
|
||||
{
|
||||
$id = get_params("id");
|
||||
//查看权限判断
|
||||
$customer = customer_auth($this->uid,$id);
|
||||
|
||||
$detail = (new CustomerList())->detail($id);
|
||||
$contact = Db::name('CustomerContact')->where(['is_default'=>1,'cid'=>$id])->find();
|
||||
//是否是客户管理员
|
||||
$auth = isAuth($this->uid,'customer_admin');
|
||||
View::assign('auth', $auth);
|
||||
View::assign('contact', $contact);
|
||||
View::assign('detail', $detail);
|
||||
return view();
|
||||
}
|
||||
|
||||
//获取客户
|
||||
public function get()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$id = get_params("id");
|
||||
$time = strtotime(date('Y-m-d')." 00:00:00");
|
||||
$max_num = Db::name('DataAuth')->where('name','customer_admin')->value('expected_1');
|
||||
$count = Db::name('Customer')->where([['belong_time','>',$time],['belong_uid','=',$this->uid]])->count();
|
||||
if($count>=$max_num){
|
||||
return to_assign(1, "今日领取客户数已到达上限,请明天再来领取");
|
||||
}
|
||||
$data['id'] = $id;
|
||||
$data['belong_uid'] = $this->uid;
|
||||
$data['belong_did'] = $this->did;
|
||||
$data['belong_time'] = time();
|
||||
if (Db::name('Customer')->update($data) !== false) {
|
||||
add_log('tosea', $id);
|
||||
$log_data = array(
|
||||
'field' => 'belong',
|
||||
'action' => 'get',
|
||||
'type' => 0,
|
||||
'customer_id' => $data['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign(0, "操作成功");
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//客户移入废弃池
|
||||
public function to_trash()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$params = get_params();
|
||||
$data['id'] = $params['id'];
|
||||
$log_data = array(
|
||||
'field' => 'del',
|
||||
'action' => 'delete',
|
||||
'type' => 0,
|
||||
'customer_id' => $params['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'create_time' => time(),
|
||||
);
|
||||
$data['delete_time'] = time();
|
||||
$log_data['action'] = 'totrash';
|
||||
if (Db::name('Customer')->update($data) !== false) {
|
||||
add_log('totrash', $params['id']);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//还原客户
|
||||
public function revert()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$params = get_params();
|
||||
$data['id'] = $params['id'];
|
||||
$data['delete_time'] = 0;
|
||||
if (Db::name('Customer')->update($data) !== false) {
|
||||
add_log('recovery', $params['id']);
|
||||
$log_data = array(
|
||||
'field' => 'del',
|
||||
'action' => 'recovery',
|
||||
'type' => 0,
|
||||
'customer_id' => $params['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'create_time' => time(),
|
||||
);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
//彻底删除客户
|
||||
public function delete()
|
||||
{
|
||||
if (request()->isDelete()) {
|
||||
$params = get_params();
|
||||
//是否是客户管理员
|
||||
$auth = isAuth($this->uid,'customer_admin');
|
||||
if($auth==0){
|
||||
return to_assign(1, "只有客户管理员才有权限操作");
|
||||
}
|
||||
$data['id'] = $params['id'];
|
||||
$data['delete_time'] = -1;
|
||||
$log_data = array(
|
||||
'field' => 'del',
|
||||
'action' => 'delete',
|
||||
'type' => 0,
|
||||
'customer_id' => $params['id'],
|
||||
'admin_id' => $this->uid,
|
||||
'create_time' => time()
|
||||
);
|
||||
if (Db::name('Customer')->update($data) !== false) {
|
||||
//删除客户联系人
|
||||
Db::name('CustomerContact')->where(['cid' => $params['id']])->update(['delete_time'=>time()]);
|
||||
//删除客户机会
|
||||
Db::name('CustomerChance')->where(['cid' => $params['id']])->update(['delete_time'=>time()]);
|
||||
add_log('delete', $params['id']);
|
||||
Db::name('CustomerLog')->strict(false)->field(true)->insert($log_data);
|
||||
return to_assign();
|
||||
} else {
|
||||
return to_assign(1, "操作失败");
|
||||
}
|
||||
} else {
|
||||
return to_assign(1, "错误的请求");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
|
||||
namespace app\customer\controller;
|
||||
|
||||
use app\base\BaseController;
|
||||
use app\customer\validate\CustomerSourceCheck;
|
||||
use think\exception\ValidateException;
|
||||
use think\facade\Db;
|
||||
use think\facade\View;
|
||||
|
||||
class Source extends BaseController
|
||||
{
|
||||
|
||||
public function index()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$cate = Db::name('CustomerSource')->order('create_time asc')->select();
|
||||
return to_assign(0, '', $cate);
|
||||
} else {
|
||||
return view();
|
||||
}
|
||||
}
|
||||
//添加
|
||||
public function source_add()
|
||||
{
|
||||
if (request()->isAjax()) {
|
||||
$param = get_params();
|
||||
if (!empty($param['id']) && $param['id'] > 0) {
|
||||
try {
|
||||
validate(CustomerSourceCheck::class)->scene('edit')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['update_time'] = time();
|
||||
$res = Db::name('CustomerSource')->strict(false)->field(true)->update($param);
|
||||
if ($res) {
|
||||
add_log('edit', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
} else {
|
||||
try {
|
||||
validate(CustomerSourceCheck::class)->scene('add')->check($param);
|
||||
} catch (ValidateException $e) {
|
||||
// 验证失败 输出错误信息
|
||||
return to_assign(1, $e->getError());
|
||||
}
|
||||
$param['create_time'] = time();
|
||||
$insertId = Db::name('CustomerSource')->strict(false)->field(true)->insertGetId($param);
|
||||
if ($insertId) {
|
||||
add_log('add', $insertId, $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//设置
|
||||
public function source_check()
|
||||
{
|
||||
$param = get_params();
|
||||
$res = Db::name('CustomerSource')->strict(false)->field('id,status')->update($param);
|
||||
if ($res) {
|
||||
if($param['status'] == 0){
|
||||
add_log('disable', $param['id'], $param);
|
||||
}
|
||||
else if($param['status'] == 1){
|
||||
add_log('recovery', $param['id'], $param);
|
||||
}
|
||||
return to_assign();
|
||||
}
|
||||
else{
|
||||
return to_assign(0, '操作失败');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
// 这是系统自动生成的event定义文件
|
||||
return [
|
||||
|
||||
];
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
// 这是系统自动生成的middleware定义文件
|
||||
return [
|
||||
//开启session中间件
|
||||
//'think\middleware\SessionInit',
|
||||
//验证勾股OA是否完成安装
|
||||
\app\home\middleware\Install::class,
|
||||
];
|
|
@ -0,0 +1,99 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class Customer extends Model
|
||||
{
|
||||
protected $autoWriteTimestamp=false;
|
||||
const ZERO = 0;
|
||||
const ONE = 1;
|
||||
const TWO = 2;
|
||||
const THREE = 3;
|
||||
const FORE = 4;
|
||||
const FIVE = 5;
|
||||
const SIX = 6;
|
||||
const SEVEN = 7;
|
||||
|
||||
public static $Status = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '新进客户',
|
||||
self::TWO => '跟进客户',
|
||||
self::THREE => '正式客户',
|
||||
self::FORE => '流失客户',
|
||||
self::FIVE => '已成交客户',
|
||||
];
|
||||
public static $IntentStatus = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '意向不明',
|
||||
self::TWO => '意向模糊',
|
||||
self::THREE => '意向一般',
|
||||
self::FORE => '意向强烈',
|
||||
self::FIVE => '已成交',
|
||||
];
|
||||
|
||||
public static $Type = [
|
||||
self::ZERO => '其他',
|
||||
self::ONE => '电话',
|
||||
self::TWO => '微信',
|
||||
self::THREE => 'QQ',
|
||||
self::FORE => '上门'
|
||||
|
||||
];
|
||||
public static $Stage = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '立项评估',
|
||||
self::TWO => '初期沟通',
|
||||
self::THREE => '需求分析',
|
||||
self::FORE => '方案制定',
|
||||
self::FIVE => '商务谈判',
|
||||
self::SIX => '合同签订',
|
||||
self::SEVEN => '失单'
|
||||
];
|
||||
|
||||
// 获取详情
|
||||
public function detail($id)
|
||||
{
|
||||
$detail = Db::name('Customer')->where(['id' => $id])->find();
|
||||
if (!empty($detail)) {
|
||||
$file_array = Db::name('CustomerFile')
|
||||
->field('cf.id,f.filepath,f.name,f.filesize,f.fileext,f.create_time,f.admin_id')
|
||||
->alias('cf')
|
||||
->join('File f', 'f.id = cf.file_id', 'LEFT')
|
||||
->order('cf.create_time asc')
|
||||
->where(array('cf.customer_id' => $id, 'cf.delete_time' => 0))
|
||||
->select()->toArray();
|
||||
|
||||
$trace_array = Db::name('CustomerTrace')->where(array('cid' => $id, 'delete_time' => 0))->order('follow_time desc')->limit(1)->select()->toArray();
|
||||
|
||||
$detail['status_name'] = self::$Status[(int) $detail['status']];
|
||||
$detail['create_time'] = date('Y-m-d', $detail['create_time']);
|
||||
$detail['belong_department'] = Db::name('Department')->where(['id' => $detail['belong_did']])->value('title');
|
||||
$detail['belong_name'] = Db::name('Admin')->where(['id' => $detail['belong_uid']])->value('name');
|
||||
$detail['admin_name'] = Db::name('Admin')->where(['id' => $detail['admin_id']])->value('name');
|
||||
|
||||
$share_names = Db::name('Admin')->where([['id','in',$detail['share_ids']]])->column('name');
|
||||
$detail['share_names'] = implode(',',$share_names);
|
||||
|
||||
$detail['file_array'] = $file_array;
|
||||
$detail['trace'] = [];
|
||||
if(!empty($trace_array)){
|
||||
$trace = $trace_array[0];
|
||||
$trace['follow_time'] = date('Y-m-d H:i', $trace['follow_time']);
|
||||
$trace['next_time'] = date('Y-m-d H:i', $trace['next_time']);
|
||||
$trace['contact_name'] = Db::name('CustomerContact')->where('id',$trace['contact_id'])->value('name');
|
||||
$trace['stage_name'] = self::$Stage[(int) $trace['stage']];
|
||||
$trace['type_name'] = self::$Type[(int) $trace['type']];
|
||||
$detail['trace'] = $trace;
|
||||
}
|
||||
}
|
||||
return $detail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class CustomerChance extends Model
|
||||
{
|
||||
const ZERO = 0;
|
||||
const ONE = 1;
|
||||
const TWO = 2;
|
||||
const THREE = 3;
|
||||
const FORE = 4;
|
||||
const FIVE = 5;
|
||||
const SIX = 6;
|
||||
const SEVEN = 7;
|
||||
|
||||
public static $Stage = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '立项评估',
|
||||
self::TWO => '初期沟通',
|
||||
self::THREE => '需求分析',
|
||||
self::FORE => '商务谈判',
|
||||
self::FIVE => '方案制定',
|
||||
self::SIX => '合同签订',
|
||||
self::SEVEN => '失单',
|
||||
];
|
||||
|
||||
// 获取详情
|
||||
public function detail($id)
|
||||
{
|
||||
$detail = Db::name('CustomerChance')->where(['id' => $id])->find();
|
||||
if (!empty($detail)) {
|
||||
$detail['customer'] = Db::name('Customer')->where(['id' => $detail['cid']])->value('name');
|
||||
$detail['create_time'] = date('Y-m-d', $detail['create_time']);
|
||||
$detail['expected_time'] = date('Y-m-d', $detail['expected_time']);
|
||||
$detail['discovery_time'] = date('Y-m-d', $detail['discovery_time']);
|
||||
$detail['belong_name'] = Db::name('Admin')->where(['id' => $detail['belong_uid']])->value('name');
|
||||
$assist_names = Db::name('Admin')->where([['id','in',$detail['assist_ids']]])->column('name');
|
||||
$detail['assist_names'] = implode(',',$assist_names);
|
||||
$detail['stage_name'] = self::$Stage[(int) $detail['stage']];
|
||||
}
|
||||
return $detail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class CustomerContact extends Model
|
||||
{
|
||||
// 获取详情
|
||||
public function detail($id)
|
||||
{
|
||||
$detail = Db::name('CustomerContact')->where(['id' => $id])->find();
|
||||
if (!empty($detail)) {
|
||||
$detail['create_time'] = date('Y-m-d H:i:s', $detail['create_time']);
|
||||
$detail['customer'] = Db::name('Customer')->where(['id' => $detail['cid']])->value('name');
|
||||
}
|
||||
return $detail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2022 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
declare (strict_types = 1);
|
||||
namespace app\customer\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class CustomerLog extends Model
|
||||
{
|
||||
public static $Sourse = [
|
||||
'status' => ['未设置', '新进客户', '跟进客户', '正式客户', '流失客户','已成交客户'],
|
||||
'intent_status' => ['未设置', '意向不明', '意向模糊', '意向一般', '意向强烈','已成交'],
|
||||
'type' => ['其他','电话','微信','QQ','上门'],
|
||||
'stage' => ['未设置','立项评估','初期沟通','需求分析','方案制定','商务谈判','合同签订','失单'],
|
||||
'action' => [
|
||||
'add' => '创建',
|
||||
'edit' => '修改',
|
||||
'delete' => '删除',
|
||||
'upload' => '上传',
|
||||
'get' => '领取',
|
||||
'tosea' => '向公海放入',
|
||||
'totrash' => '向废池放入',
|
||||
'recovery' => '从废池移出',
|
||||
],
|
||||
'role'=>['客户','客户跟进记录','客户联系人','客户销售机会'],
|
||||
'field_array' =>[
|
||||
0 =>[
|
||||
'name' => '名称',
|
||||
'source_id' => '客户来源',
|
||||
'grade_id' => '客户等级',
|
||||
'industry_id' => '所属行业',
|
||||
'services_id' => '客户意向',
|
||||
'provinceid' => '省份',
|
||||
'cityid' => '城市',
|
||||
'distid'=> '区县',
|
||||
'address' => '联系地址',
|
||||
'status' => '状态',
|
||||
'intent_status' => '意向状态',
|
||||
'belong_uid' => '所属人',
|
||||
'belong_did' => '所属部门',
|
||||
'share_ids' => '共享人员',
|
||||
'content' => '客户描述',
|
||||
'market' => '主要经营业务',
|
||||
'remark' => '备注信息',
|
||||
'bank`' => '开户银行',
|
||||
'bank_sn' => '银行帐号',
|
||||
'tax_num' => '纳税人识别号',
|
||||
'cperson_mobile' => '开票电话',
|
||||
'cperson_address' => '开票地址',
|
||||
'discard_time' => '废弃时间',
|
||||
'delete_time' => '删除',
|
||||
'file' => '附件',
|
||||
'new' => '新增',
|
||||
'del' => '删除',
|
||||
'belong' => '所属人',
|
||||
],
|
||||
1 =>[
|
||||
'contact_id' => '联系人',
|
||||
'chance_id' => '销售机会',
|
||||
'type' => '跟进方式',
|
||||
'stage' => '当前阶段',
|
||||
'content' => '跟进内容',
|
||||
'follow_time' => '跟进时间',
|
||||
'next_time' => '下次跟进时间',
|
||||
'delete_time' => '删除',
|
||||
'new' => '新增',
|
||||
'del' => '删除',
|
||||
],
|
||||
2 =>[
|
||||
'name' => '姓名',
|
||||
'is_default' => '第一联系人',
|
||||
'sex' => '性别',
|
||||
'mobile' => '手机号码',
|
||||
'qq' => 'QQ号',
|
||||
'wechat' => '微信号',
|
||||
'email' => '邮件地址',
|
||||
'nickname' => '称谓',
|
||||
'department' => '部门',
|
||||
'position' => '职务',
|
||||
'delete_time' => '删除',
|
||||
'new' => '新增',
|
||||
'del' => '删除',
|
||||
],
|
||||
3 =>[
|
||||
'title' => '主题',
|
||||
'contact_id' => '联系人',
|
||||
'services_id' => '需求服务',
|
||||
'stage' => '当前阶段',
|
||||
'content' => '需求描述',
|
||||
'discovery_time' => '发现时间',
|
||||
'expected_time' => '预计签单时间',
|
||||
'expected_amount' => '预计签单金额',
|
||||
'belong_uid' => '所属人',
|
||||
'assist_ids' => '协助人员',
|
||||
'delete_time' => '删除',
|
||||
'new' => '新增',
|
||||
'del' => '删除',
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
public function customer_log($param = [])
|
||||
{
|
||||
$trace_ids = Db::name('CustomerTrace')->where(['cid' => $param['customer_id'], 'delete_time' => 0])->column('id');
|
||||
$contact_ids = Db::name('CustomerContact')->where(['cid' => $param['customer_id'], 'delete_time' => 0])->column('id');
|
||||
$chance_ids = Db::name('CustomerChance')->where(['cid' => $param['customer_id'], 'delete_time' => 0])->column('id');
|
||||
|
||||
$where1 = [];
|
||||
$where2 = [];
|
||||
$where3 = [];
|
||||
$where4 = [];
|
||||
|
||||
$where1[] = ['a.customer_id', '=', $param['customer_id']];
|
||||
|
||||
$where2[] = ['a.type', '=', 1];
|
||||
$where2[] = ['a.trace_id', 'in', $trace_ids];
|
||||
|
||||
$where3[] = ['a.type', '=', 2];
|
||||
$where3[] = ['a.contact_id', 'in', $contact_ids];
|
||||
|
||||
$where4[] = ['a.type', '=', 3];
|
||||
$where4[] = ['a.chance_id', 'in', $chance_ids];
|
||||
|
||||
$page = intval($param['page']);
|
||||
$rows = empty($param['limit']) ? get_config('app.page_size') : $param['limit'];
|
||||
$content = Db::name('CustomerLog')
|
||||
->field('a.*,u.name,u.thumb')
|
||||
->alias('a')
|
||||
->join('Admin u', 'u.id = a.admin_id')
|
||||
->order('a.create_time desc')
|
||||
->whereOr([$where1, $where2, $where3, $where4])
|
||||
->page($page, $rows)
|
||||
->select()->toArray();
|
||||
$data = [];
|
||||
$sourse = self::$Sourse;
|
||||
$role = $sourse['role'];
|
||||
$action = $sourse['action'];
|
||||
foreach ($content as $k => $v) {
|
||||
$field_array = $sourse['field_array'][$v['type']];
|
||||
if (isset($sourse[$v['field']])) {
|
||||
$v['old_content'] = $sourse[$v['field']][$v['old_content']];
|
||||
$v['new_content'] = $sourse[$v['field']][$v['new_content']];
|
||||
}
|
||||
if (strpos($v['field'], '_time') !== false) {
|
||||
if ($v['old_content'] == '') {
|
||||
$v['old_content'] = '未设置';
|
||||
}
|
||||
$v['new_content'] = date('Y-m-d', (int) $v['new_content']);
|
||||
}
|
||||
if (strpos($v['field'], '_uid') !== false) {
|
||||
$v['old_content'] = Db::name('Admin')->where(['id' => $v['old_content']])->value('name');
|
||||
$v['new_content'] = Db::name('Admin')->where(['id' => $v['new_content']])->value('name');
|
||||
}
|
||||
if ($v['field'] == 'contact_id') {
|
||||
$v['old_content'] = Db::name('CustomerContact')->where(['id' => $v['old_content']])->value('name');
|
||||
$v['new_content'] = Db::name('CustomerContact')->where(['id' => $v['new_content']])->value('name');
|
||||
}
|
||||
if ($v['field'] == 'source_id') {
|
||||
$v['old_content'] = Db::name('CustomerSource')->where(['id' => $v['old_content']])->value('title');
|
||||
$v['new_content'] = Db::name('CustomerSource')->where(['id' => $v['new_content']])->value('title');
|
||||
}
|
||||
if ($v['field'] == 'grade_id') {
|
||||
$v['old_content'] = Db::name('CustomerGrade')->where(['id' => $v['old_content']])->value('title');
|
||||
$v['new_content'] = Db::name('CustomerGrade')->where(['id' => $v['new_content']])->value('title');
|
||||
}
|
||||
if ($v['field'] == 'industry_id') {
|
||||
$v['old_content'] = Db::name('Industry')->where(['id' => $v['old_content']])->value('title');
|
||||
$v['new_content'] = Db::name('Industry')->where(['id' => $v['new_content']])->value('title');
|
||||
}
|
||||
if ($v['field'] == 'services_id') {
|
||||
$v['old_content'] = Db::name('Services')->where(['id' => $v['old_content']])->value('title');
|
||||
$v['new_content'] = Db::name('Services')->where(['id' => $v['new_content']])->value('title');
|
||||
}
|
||||
if ($v['field'] == 'is_default') {
|
||||
$v['old_content'] = $v['old_content'] == 1?'第一联系人':'普通联系人';
|
||||
$v['new_content'] = $v['new_content'] == 1?'第一联系人':'普通联系人';
|
||||
}
|
||||
if ($v['field'] == 'sex') {
|
||||
$v['old_content'] = $v['old_content'] == 1?'男':'女';
|
||||
$v['new_content'] = $v['new_content'] == 1?'男':'女';
|
||||
}
|
||||
if (strpos($v['field'], '_ids') !== false) {
|
||||
$old_ids = Db::name('Admin')->where('id', 'in', $v['old_content'])->column('name');
|
||||
$v['old_content'] = implode(',', $old_ids);
|
||||
$new_ids = Db::name('Admin')->where('id', 'in', $v['new_content'])->column('name');
|
||||
$v['new_content'] = implode(',', $new_ids);
|
||||
}
|
||||
if ($v['old_content'] == '' || $v['old_content'] == null) {
|
||||
$v['old_content'] = '未设置';
|
||||
}
|
||||
if ($v['new_content'] == '' || $v['new_content'] == null) {
|
||||
$v['new_content'] = '未设置';
|
||||
}
|
||||
$v['role'] = $role[$v['type']];
|
||||
$v['action'] = $action[$v['action']];
|
||||
$v['title'] = $field_array[$v['field']];
|
||||
$v['times'] = time_trans($v['create_time']);
|
||||
$v['create_time'] = date('Y-m-d', $v['create_time']);
|
||||
$data[] = $v;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\model;
|
||||
|
||||
use think\facade\Db;
|
||||
use think\Model;
|
||||
|
||||
class CustomerTrace extends Model
|
||||
{
|
||||
const ZERO = 0;
|
||||
const ONE = 1;
|
||||
const TWO = 2;
|
||||
const THREE = 3;
|
||||
const FORE = 4;
|
||||
const FIVE = 5;
|
||||
const SIX = 6;
|
||||
const SEVEN = 7;
|
||||
|
||||
public static $Type = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '电话',
|
||||
self::TWO => '微信',
|
||||
self::THREE => 'QQ',
|
||||
self::FORE => '上门'
|
||||
];
|
||||
public static $Stage = [
|
||||
self::ZERO => '未设置',
|
||||
self::ONE => '立项评估',
|
||||
self::TWO => '初期沟通',
|
||||
self::THREE => '需求分析',
|
||||
self::FORE => '商务谈判',
|
||||
self::FIVE => '方案制定',
|
||||
self::SIX => '合同签订',
|
||||
self::SEVEN => '失单',
|
||||
];
|
||||
|
||||
// 获取详情
|
||||
public function detail($id)
|
||||
{
|
||||
$detail = Db::name('CustomerTrace')->where(['id' => $id])->find();
|
||||
if (!empty($detail)) {
|
||||
$detail['stage_name'] = self::$Stage[(int) $detail['stage']];
|
||||
$detail['type_name'] = self::$Type[(int) $detail['type']];
|
||||
$detail['create_time'] = date('Y-m-d H:i:s', $detail['create_time']);
|
||||
$detail['follow_time'] = date('Y-m-d H:i:s', $detail['follow_time']);
|
||||
$detail['next_time'] = date('Y-m-d H:i:s', $detail['next_time']);
|
||||
$detail['customer'] = Db::name('Customer')->where(['id' => $detail['cid']])->value('name');
|
||||
}
|
||||
return $detail;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class CustomerCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'name' => 'require|unique:customer',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'name.require' => '客户名称不能为空',
|
||||
'name.unique' => '同样的客户名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['name',],
|
||||
'edit' => ['name','id'],
|
||||
'change' => ['id'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class CustomerContactCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'name' => 'require',
|
||||
'mobile' => 'require',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'name.require' => '联系人姓名不能为空',
|
||||
'mobile' => '手机号码不能为空',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['name','mobile'],
|
||||
'edit' => ['id', 'name','mobile'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class CustomerGradeCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:customer_grade',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2021 勾股工作室
|
||||
* @license https://opensource.org/licenses/GPL-3.0
|
||||
* @link https://www.gougucms.com
|
||||
*/
|
||||
|
||||
namespace app\customer\validate;
|
||||
|
||||
use think\Validate;
|
||||
|
||||
class CustomerSourceCheck extends Validate
|
||||
{
|
||||
protected $rule = [
|
||||
'title' => 'require|unique:customer_source',
|
||||
'id' => 'require',
|
||||
];
|
||||
|
||||
protected $message = [
|
||||
'title.require' => '名称不能为空',
|
||||
'title.unique' => '同样的名称已经存在',
|
||||
'id.require' => '缺少更新条件',
|
||||
];
|
||||
|
||||
protected $scene = [
|
||||
'add' => ['title'],
|
||||
'edit' => ['id', 'title'],
|
||||
];
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">新增销售机会</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称</td>
|
||||
<td colspan="3">{$customer_name}</td>
|
||||
<td class="layui-td-gray-2">客户联系人<font>*</font></td>
|
||||
<td>
|
||||
<select name="contact_id" lay-verify="required" lay-reqText="请选择联系人">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":customer_contact($customer_id)" id="v"}
|
||||
<option value="{$v.id}">{$v.name}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">机会标题<font>*</font></td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="title" autocomplete="off" lay-verify="required" lay-reqText="请输入机会标题" placeholder="请输入机会标题" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">发现时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="discovery_time" name="discovery_time" readonly autocomplete="off" lay-verify="required" lay-reqText="请选择发现时间" placeholder="请选择发现时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">销售阶段<font>*</font></td>
|
||||
<td>
|
||||
<select name="stage" lay-verify="required" lay-reqText="请选择">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":trace_stage()" id="v"}
|
||||
<option value="{$key}">{$v}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">预计金额<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="expected_amount" autocomplete="off" lay-verify="required|number" lay-reqText="请输入预计金额" placeholder="请输入预计金额" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">预计签单时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="expected_time" name="expected_time" readonly autocomplete="off" lay-verify="required" lay-reqText="请选择预计签单时间" placeholder="请选择预计签单时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top">需求描述<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<textarea name="content" placeholder="请输入需求描述" lay-verify="required" lay-reqText="请输入需求描述" class="layui-textarea"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">归属人员<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="belong_name" readonly autocomplete="off" placeholder="请选择归属人员" class="layui-input picker-one">
|
||||
<input type="hidden" name="belong_uid" lay-verify="required" lay-reqText="请选择归属人员">
|
||||
</td>
|
||||
<td class="layui-td-gray">协助人员</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="assist_names" autocomplete="off" placeholder="请选择协助人员" class="layui-input picker-more">
|
||||
<input type="hidden" name="assist_ids">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="cid" value="{$customer_id}">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','employeepicker'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,laydate = layui.laydate,employeepicker=layui.employeepicker;
|
||||
laydate.render({
|
||||
elem: '#discovery_time'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#expected_time'
|
||||
,min: 0
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose();
|
||||
parent.layui.chanceTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/customer/api/add_chance", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,106 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">新增跟进记录</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称</td>
|
||||
<td colspan="5">{$customer_name}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">联 系 人<font>*</font></td>
|
||||
<td>
|
||||
<select name="contact_id" lay-verify="required" lay-reqText="请选择联系人">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":customer_contact($customer_id)" id="v"}
|
||||
<option value="{$v.id}">{$v.name}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">跟进方式<font>*</font></td>
|
||||
<td>
|
||||
<select name="type" lay-verify="required" lay-reqText="请选择跟进方式">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":trace_type()" id="v"}
|
||||
<option value="{$key}">{$v}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">跟进时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="follow_time" name="follow_time" autocomplete="off" lay-verify="required" lay-reqText="请选择跟进时间" placeholder="请选择跟进时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top">沟通内容<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<textarea name="content" placeholder="请输入沟通内容" lay-verify="required" lay-reqText="请输入沟通内容" class="layui-textarea"></textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">当前阶段<font>*</font></td>
|
||||
<td>
|
||||
<select name="stage" lay-verify="required" lay-reqText="请选择">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":trace_stage()" id="v"}
|
||||
<option value="{$key}">{$v}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">销售机会</td>
|
||||
<td>
|
||||
<select name="grade_id">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":customer_chance($customer_id)" id="v"}
|
||||
<option value="{$v.id}">{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray-2">下次沟通时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="next_time" name="next_time" autocomplete="off" lay-verify="required" lay-reqText="请选择下次沟通时间" placeholder="请选择下次沟通时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="cid" value="{$customer_id}">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,laydate = layui.laydate;
|
||||
laydate.render({
|
||||
elem: '#follow_time'
|
||||
,type: 'datetime'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#next_time'
|
||||
,min: 0
|
||||
,type: 'datetime'
|
||||
});
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose();
|
||||
parent.layui.traceTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/customer/api/add_trace", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,107 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">编辑销售机会</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称</td>
|
||||
<td colspan="3">{$detail.customer}</td>
|
||||
<td class="layui-td-gray-2">客户联系人<font>*</font></td>
|
||||
<td>
|
||||
<select name="contact_id" lay-verify="required" lay-reqText="请选择联系人">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":customer_contact($detail.cid)" id="v"}
|
||||
<option value="{$v.id}" {eq name="$v.id" value="$detail.contact_id"} selected{/eq}>{$v.name}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">机会标题<font>*</font></td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="title" value="{$detail.title}" autocomplete="off" lay-verify="required" lay-reqText="请输入机会标题" placeholder="请输入机会标题" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray">发现时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="discovery_time" name="discovery_time" value="{$detail.discovery_time}" readonly autocomplete="off" lay-verify="required" lay-reqText="请选择发现时间" placeholder="请选择发现时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">销售阶段<font>*</font></td>
|
||||
<td>
|
||||
<select name="stage" lay-verify="required" lay-reqText="请选择">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":trace_stage()" id="v"}
|
||||
<option value="{$key}" {eq name="$key" value="$detail.stage"} selected{/eq}>{$v}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">预计金额<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="expected_amount" autocomplete="off" value="{$detail.expected_amount}" lay-verify="required|number" lay-reqText="请输入预计金额" placeholder="请输入预计金额" class="layui-input">
|
||||
</td>
|
||||
<td class="layui-td-gray-2">预计签单时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="expected_time" name="expected_time" value="{$detail.expected_time}" readonly autocomplete="off" lay-verify="required" lay-reqText="请选择预计签单时间" placeholder="请选择预计签单时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top">需求描述<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<textarea name="content" placeholder="请输入需求描述" lay-verify="required" lay-reqText="请输入需求描述" class="layui-textarea">{$detail.content}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">归属人员<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" name="belong_name" value="{$detail.belong_name}" readonly autocomplete="off" placeholder="请选择归属人员" class="layui-input picker-one">
|
||||
<input type="hidden" name="belong_uid" value="{$detail.belong_uid}" lay-verify="required" lay-reqText="请选择归属人员">
|
||||
</td>
|
||||
<td class="layui-td-gray">协助人员</td>
|
||||
<td colspan="3">
|
||||
<input type="text" name="assist_names" value="{$detail.assist_names}" autocomplete="off" placeholder="请选择协助人员" class="layui-input picker-more">
|
||||
<input type="hidden" name="assist_ids" value="{$detail.assist_ids}">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="id" value="{$detail.id}">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool','employeepicker'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,laydate = layui.laydate,employeepicker=layui.employeepicker;
|
||||
laydate.render({
|
||||
elem: '#discovery_time'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#expected_time'
|
||||
,min: 0
|
||||
});
|
||||
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose();
|
||||
parent.layui.chanceTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/customer/api/add_chance", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,106 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">新增跟进记录</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称</td>
|
||||
<td colspan="5">{$detail.customer}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">联 系 人<font>*</font></td>
|
||||
<td>
|
||||
<select name="contact_id" lay-verify="required" lay-reqText="请选择联系人">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":customer_contact($detail.cid)" id="v"}
|
||||
<option value="{$v.id}" {eq name="$v.id" value="$detail.contact_id"} selected{/eq}>{$v.name}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">跟进方式<font>*</font></td>
|
||||
<td>
|
||||
<select name="type" lay-verify="required" lay-reqText="请选择跟进方式">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":trace_type()" id="v"}
|
||||
<option value="{$key}" {eq name="$key" value="$detail.type"} selected{/eq}>{$v}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">跟进时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="follow_time" name="follow_time" value="{$detail.follow_time}" autocomplete="off" lay-verify="required" lay-reqText="请选择跟进时间" placeholder="请选择跟进时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top">沟通内容<font>*</font></td>
|
||||
<td colspan="5">
|
||||
<textarea name="content" placeholder="请输入沟通内容" lay-verify="required" lay-reqText="请输入沟通内容" class="layui-textarea">{$detail.content}</textarea>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">当前阶段<font>*</font></td>
|
||||
<td>
|
||||
<select name="stage" lay-verify="required" lay-reqText="请选择">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":trace_stage()" id="v"}
|
||||
<option value="{$key}" {eq name="$key" value="$detail.stage"} selected{/eq}>{$v}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray">销售机会</td>
|
||||
<td>
|
||||
<select name="chance_id">
|
||||
<option value="">请选择</option>
|
||||
{volist name=":customer_chance($detail.cid)" id="v"}
|
||||
<option value="{$v.id}" {eq name="$v.id" value="$detail.chance_id"} selected{/eq}>{$v.title}</option>
|
||||
{/volist}
|
||||
</select>
|
||||
</td>
|
||||
<td class="layui-td-gray-2">下次沟通时间<font>*</font></td>
|
||||
<td>
|
||||
<input type="text" id="next_time" name="next_time" value="{$detail.next_time}" autocomplete="off" lay-verify="required" lay-reqText="请选择下次沟通时间" placeholder="请选择下次沟通时间" class="layui-input">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="py-3">
|
||||
<input type="hidden" name="id" value="{$detail.id}">
|
||||
<button class="layui-btn layui-btn-normal" lay-submit="" lay-filter="webform">立即提交</button>
|
||||
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
|
||||
</div>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
const moduleInit = ['tool'];
|
||||
function gouguInit() {
|
||||
var form = layui.form,tool=layui.tool,laydate = layui.laydate;
|
||||
laydate.render({
|
||||
elem: '#follow_time'
|
||||
,type: 'datetime'
|
||||
});
|
||||
laydate.render({
|
||||
elem: '#next_time'
|
||||
,min: 0
|
||||
,type: 'datetime'
|
||||
});
|
||||
//监听提交
|
||||
form.on('submit(webform)', function (data) {
|
||||
let callback = function (e) {
|
||||
layer.msg(e.msg);
|
||||
if (e.code == 0) {
|
||||
tool.sideClose();
|
||||
parent.layui.traceTable.reload();
|
||||
}
|
||||
}
|
||||
tool.post("/customer/api/add_trace", data.field, callback);
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
|
@ -0,0 +1,52 @@
|
|||
{extend name="../../base/view/common/base" /}
|
||||
<!-- 主体 -->
|
||||
{block name="body"}
|
||||
<form class="layui-form p-4">
|
||||
<h3 class="pb-3">销售机会</h3>
|
||||
<table class="layui-table layui-table-form">
|
||||
<tr>
|
||||
<td class="layui-td-gray">客户名称</td>
|
||||
<td colspan="3">{$detail.customer}</td>
|
||||
<td class="layui-td-gray-2">客户联系人</td>
|
||||
<td>
|
||||
{volist name=":customer_contact($detail.cid)" id="v"}
|
||||
{eq name="$v.id" value="$detail.contact_id"}{$v.name}{/eq}
|
||||
{/volist}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">机会标题</td>
|
||||
<td colspan="3">{$detail.title}</td>
|
||||
<td class="layui-td-gray">发现时间</td>
|
||||
<td>{$detail.discovery_time}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">销售阶段</td>
|
||||
<td>{$detail.stage_name}</td>
|
||||
<td class="layui-td-gray">预计金额</td>
|
||||
<td>{$detail.expected_amount}</td>
|
||||
<td class="layui-td-gray-2">预计签单时间</td>
|
||||
<td>{$detail.expected_time}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray" style="vertical-align:top">需求描述</td>
|
||||
<td colspan="5">{$detail.content}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="layui-td-gray">归属人员</td>
|
||||
<td>{$detail.belong_name}</td>
|
||||
<td class="layui-td-gray">协助人员</td>
|
||||
<td colspan="3">{$detail.assist_names}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
{/block}
|
||||
<!-- /主体 -->
|
||||
|
||||
<!-- 脚本 -->
|
||||
{block name="script"}
|
||||
<script>
|
||||
|
||||
</script>
|
||||
{/block}
|
||||
<!-- /脚本 -->
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue