adsfasdfas

This commit is contained in:
2025-12-18 11:21:31 +08:00
parent 9c47f313b7
commit 26a6152ecc
81 changed files with 6160 additions and 0 deletions

2
rc_autoplc_backend/.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

26
rc_autoplc_backend/.gitignore vendored Normal file
View File

@@ -0,0 +1,26 @@
# Compiled class file
*.class
*.bak
*.swp
target/
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

View File

@@ -0,0 +1,28 @@
# Getting Started
### Reference Documentation
For further reference, please consider the following sections:
* [Official Apache Maven documentation](https://maven.apache.org/guides/index.html)
* [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/3.4.12/maven-plugin)
* [Create an OCI image](https://docs.spring.io/spring-boot/3.4.12/maven-plugin/build-image.html)
* [Spring Boot DevTools](https://docs.spring.io/spring-boot/3.4.12/reference/using/devtools.html)
* [Spring Web](https://docs.spring.io/spring-boot/3.4.12/reference/web/servlet.html)
### Guides
The following guides illustrate how to use some features concretely:
* [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/)
* [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/)
* [Building REST services with Spring](https://spring.io/guides/tutorials/rest/)
### Maven Parent overrides
Due to Maven's design, elements are inherited from the parent POM to the project POM.
While most of the inheritance is fine, it also inherits unwanted elements like `<license>` and `<developers>` from the
parent.
To prevent this, the project POM contains empty overrides for these elements.
If you manually switch to a different parent and actually want the inheritance, you need to remove those overrides.

661
rc_autoplc_backend/LICENSE Normal file
View File

@@ -0,0 +1,661 @@
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are 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.
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.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
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 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 work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero 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 Affero 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 Affero 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 Affero 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 Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
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 AGPL, see
<https://www.gnu.org/licenses/>.

View File

@@ -0,0 +1,36 @@
# 融创智能PLC后台系统
#### Description
智能plc管理后台系统
#### Software Architecture
Software architecture description
#### Installation
1. xxxx
2. xxxx
3. xxxx
#### Instructions
1. xxxx
2. xxxx
3. xxxx
#### Contribution
1. Fork the repository
2. Create Feat_xxx branch
3. Commit your code
4. Create Pull Request
#### Gitee Feature
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
4. The most valuable open source project [GVP](https://gitee.com/gvp)
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

View File

@@ -0,0 +1,37 @@
# 融创智能PLC后台系统
#### 介绍
智能plc管理后台系统
#### 软件架构
软件架构说明
#### 安装教程
1. xxxx
2. xxxx
3. xxxx
#### 使用说明
1. xxxx
2. xxxx
3. xxxx
#### 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
#### 特技
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)

295
rc_autoplc_backend/mvnw vendored Normal file
View File

@@ -0,0 +1,295 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.4
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
scriptDir="$(dirname "$0")"
scriptName="$(basename "$0")"
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"$scriptDir/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${scriptName#mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c - >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
# Find the actual extracted directory name (handles snapshots where filename != directory name)
actualDistributionDir=""
# First try the expected directory name (for regular distributions)
if [ -d "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" ]; then
if [ -f "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/bin/$MVN_CMD" ]; then
actualDistributionDir="$distributionUrlNameMain"
fi
fi
# If not found, search for any directory with the Maven executable (for snapshots)
if [ -z "$actualDistributionDir" ]; then
# enable globbing to iterate over items
set +f
for dir in "$TMP_DOWNLOAD_DIR"/*; do
if [ -d "$dir" ]; then
if [ -f "$dir/bin/$MVN_CMD" ]; then
actualDistributionDir="$(basename "$dir")"
break
fi
fi
done
set -f
fi
if [ -z "$actualDistributionDir" ]; then
verbose "Contents of $TMP_DOWNLOAD_DIR:"
verbose "$(ls -la "$TMP_DOWNLOAD_DIR")"
die "Could not find Maven distribution directory in extracted archive"
fi
verbose "Found extracted Maven distribution directory: $actualDistributionDir"
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$actualDistributionDir/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$actualDistributionDir" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

189
rc_autoplc_backend/mvnw.cmd vendored Normal file
View File

@@ -0,0 +1,189 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.4
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_M2_PATH = "$HOME/.m2"
if ($env:MAVEN_USER_HOME) {
$MAVEN_M2_PATH = "$env:MAVEN_USER_HOME"
}
if (-not (Test-Path -Path $MAVEN_M2_PATH)) {
New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null
}
$MAVEN_WRAPPER_DISTS = $null
if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) {
$MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists"
} else {
$MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists"
}
$MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain"
$MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
# Find the actual extracted directory name (handles snapshots where filename != directory name)
$actualDistributionDir = ""
# First try the expected directory name (for regular distributions)
$expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain"
$expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD"
if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) {
$actualDistributionDir = $distributionUrlNameMain
}
# If not found, search for any directory with the Maven executable (for snapshots)
if (!$actualDistributionDir) {
Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object {
$testPath = Join-Path $_.FullName "bin/$MVN_CMD"
if (Test-Path -Path $testPath -PathType Leaf) {
$actualDistributionDir = $_.Name
}
}
}
if (!$actualDistributionDir) {
Write-Error "Could not find Maven distribution directory in extracted archive"
}
Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir"
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

102
rc_autoplc_backend/pom.xml Normal file
View File

@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.4.12</version>
<relativePath/>
</parent>
<groupId>com.rczn</groupId>
<artifactId>Rc-autoplc-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Rc-autoplc-backend</name>
<description>Rc-autoplc-backend 聚合父模块</description>
<packaging>pom</packaging>
<modules>
<module>rczn-common</module>
<module>rczn-autoplc</module>
<module>rczn-admin</module>
</modules>
<properties>
<java.version>17</java.version>
<!-- 项目特定依赖版本 -->
<mybatis.version>3.0.3</mybatis.version>
<pagehelper.version>2.1.0</pagehelper.version>
<jwt.version>4.4.0</jwt.version>
<knife4j.version>4.5.0</knife4j.version>
<jakarta.servlet-api.version>6.0.0</jakarta.servlet-api.version>
</properties>
<!-- 使用 dependencyManagement 管理项目特定版本 -->
<dependencyManagement>
<dependencies>
<!-- 项目内部模块 -->
<dependency>
<groupId>com.rczn</groupId>
<artifactId>rczn-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.rczn</groupId>
<artifactId>rczn-autoplc</artifactId>
<version>${project.version}</version>
</dependency>
<!-- 项目特定的外部依赖版本管理 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!-- Jakarta Servlet API -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<version>${jakarta.servlet-api.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<encoding>UTF-8</encoding>
<annotationProcessorPaths>
<path>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

View File

@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.rczn</groupId>
<artifactId>Rc-autoplc-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>rczn-admin</artifactId>
<name>rczn-admin</name>
<description>rczn-admin后台管理模块</description>
<packaging>jar</packaging>
<dependencies>
<!-- 依赖公共模块 -->
<dependency>
<groupId>com.rczn</groupId>
<artifactId>rczn-common</artifactId>
</dependency>
<!-- 依赖PLC模块 -->
<dependency>
<groupId>com.rczn</groupId>
<artifactId>rczn-autoplc</artifactId>
</dependency>
<!-- Spring Boot Web 依赖包含Servlet API -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 如果 spring-boot-starter-web 仍然找不到,显式添加 -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring Boot 其他依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- 数据库相关 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- 其他依赖 -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- 测试依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.rczn.RcznAdminApplication</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,15 @@
package com.rczn;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
@SpringBootApplication
@ComponentScan(value = "com.rczn.*")
public class RcznAdminApplication {
public static void main(String[] args) {
SpringApplication.run(RcznAdminApplication.class, args);
}
}

View File

@@ -0,0 +1,20 @@
package com.rczn.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 所有接口允许跨域
// 替换allowedOrigins为allowedOriginPatterns支持通配符*
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST","PATCH", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true) // 允许携带Cookie
.maxAge(3600); // 预检请求缓存1小时
}
}

View File

@@ -0,0 +1,120 @@
package com.rczn.controller;
import com.rczn.domain.PageBean;
import com.rczn.domain.Result;
import com.rczn.system.domain.Department;
import com.rczn.system.service.DepartmentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/depart")
@Tag(name = "部门管理", description = "部门增删改查+分页查询接口")
public class DepartmentController {
@Autowired
private DepartmentService departmentService;
/**
* 分页查询部门
*/
@GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "分页查询部门", description = "支持部门名称、编码、父ID模糊/精准查询")
@Parameters({
@Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "deptName", description = "部门名称(可选,模糊查询)", required = false, example = "技术部", in = ParameterIn.QUERY),
@Parameter(name = "deptCode", description = "部门编码(可选,模糊查询)", required = false, example = "TECH", in = ParameterIn.QUERY),
@Parameter(name = "parentId", description = "父部门ID可选精准查询", required = false, example = "1", in = ParameterIn.QUERY)
})
public Result<PageBean<Department>> getDeptPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String deptName,
@RequestParam(required = false) String deptCode,
@RequestParam(required = false) Integer parentId) {
PageBean<Department> pageBean = departmentService.selectPage(pageNum, pageSize, deptName, deptCode, parentId);
return Result.success(pageBean);
}
/**
* 根据ID查询部门
*/
@GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "查询单个部门", description = "根据部门ID查询详情")
public Result getDeptById(@PathVariable Long id) {
Department department = departmentService.selectById(id);
return department != null ? Result.success(department) : Result.error("部门不存在");
}
/**
* 新增部门
*/
@PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "新增部门", description = "部门名称和编码为必填项")
public Result addDept(@RequestBody Department department) {
try {
Long deptId = departmentService.insert(department);
return Result.success(deptId);
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 修改部门
*/
@PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "修改部门", description = "需传入部门ID其他字段可选非空则更新")
public Result updateDept(@RequestBody Department department) {
try {
Boolean success = departmentService.update(department);
return success ? Result.success(true) : Result.error("修改失败(部门不存在或已删除)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 删除部门(逻辑删除)
*/
@DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "删除部门", description = "逻辑删除设置delSign=1不物理删除数据")
public Result deleteDept(@PathVariable Long id) {
try {
Boolean success = departmentService.deleteById(id);
return success ? Result.success(true) : Result.error("删除失败(部门不存在或已删除)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 新增接口:获取完整部门树(包含所有字段)
*/
@GetMapping(value = "/tree", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "获取完整部门树", description = "返回包含所有字段的部门层级结构")
public Result getDeptTree() {
List<Department> deptTree = departmentService.getDeptTree();
return Result.success(deptTree);
}
/**
* 新增接口获取简化部门树仅ID、名称、子部门用于下拉选择
*/
@GetMapping(value = "/simple-tree", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "获取简化部门树", description = "仅返回ID、名称、子部门适用于下拉选择框等场景")
public Result getSimpleDeptTree() {
List<Department> simpleDeptTree = departmentService.getSimpleDeptTree();
return Result.success(simpleDeptTree);
}
}

View File

@@ -0,0 +1,19 @@
package com.rczn.controller;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/admin")
@Tag(name = "用户管理", description = "用户新增、查询、修改接口")
public class HellowAdminController {
@GetMapping("/hellow")
@Operation(summary = "查询用户", description = "根据ID查询用户详情") // 替代@ApiOperation
public String hellow(){
return "hellow admin!!!";
}
}

View File

@@ -0,0 +1,115 @@
package com.rczn.controller;
import com.rczn.domain.PageBean;
import com.rczn.domain.Result;
import com.rczn.system.domain.ManageLog;
import com.rczn.system.service.ManageLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
@RestController
@RequestMapping("/manage-log")
@Tag(name = "操作日志管理", description = "操作日志增删改查+分页查询接口")
public class ManageLogController {
@Autowired
private ManageLogService manageLogService;
/**
* 分页查询日志
*/
@GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "分页查询操作日志", description = "支持多条件筛选,空条件自动忽略")
@Parameters({
@Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "logName", description = "日志名称(可选,模糊查询)", required = false, example = "登录操作", in = ParameterIn.QUERY),
@Parameter(name = "logType", description = "日志类型(可选,精准查询)", required = false, example = "LOGIN", in = ParameterIn.QUERY),
@Parameter(name = "createId", description = "创建人ID可选", required = false, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "logWritetimeStart", description = "日志开始时间可选格式yyyy-MM-dd HH:mm:ss", required = false, example = "2025-01-01 00:00:00", in = ParameterIn.QUERY),
@Parameter(name = "logWritetimeEnd", description = "日志结束时间可选格式yyyy-MM-dd HH:mm:ss", required = false, example = "2025-12-31 23:59:59", in = ParameterIn.QUERY)
})
public Result<PageBean<ManageLog>> getLogPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String logName,
@RequestParam(required = false) String logType,
@RequestParam(required = false) Long createId,
@RequestParam(required = false) LocalDateTime logWritetimeStart,
@RequestParam(required = false) LocalDateTime logWritetimeEnd) {
// 构建查询条件(空字段自动忽略)
ManageLog query = new ManageLog();
query.setLogName(logName);
query.setLogType(logType);
query.setCreateId(createId);
// 扩展字段用于时间范围查询实体类无需新增字段MyBatis 支持直接取参)
query.setStartTime(logWritetimeStart); // 实际用 logWritetimeStart这里仅为传递参数
query.setEndTime(logWritetimeEnd);
PageBean<ManageLog> pageBean = manageLogService.selectPage(pageNum, pageSize, query);
return Result.success(pageBean);
}
/**
* 按 ID 查询日志
*/
@GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "查询单个操作日志", description = "按日志ID查询详情")
public Result getLogById(@PathVariable Long id) {
ManageLog log = manageLogService.selectById(id);
return log != null ? Result.success(log) : Result.error("日志不存在或已删除");
}
/**
* 新增操作日志
*/
@PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "新增操作日志", description = "日志名称、类型为必填项,其他字段可选")
public Result addLog(@RequestBody ManageLog manageLog) {
try {
Long logId = manageLogService.insert(manageLog);
return Result.success("日志新增成功");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 更新操作日志
*/
@PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "更新操作日志", description = "需传入日志ID其他字段非空则更新")
public Result updateLog(@RequestBody ManageLog manageLog) {
try {
Boolean success = manageLogService.update(manageLog);
return success ? Result.success( "日志更新成功") : Result.error("更新失败(日志不存在或已删除)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 逻辑删除操作日志
*/
@DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "删除操作日志", description = "逻辑删除设置delSign=1不物理删除")
public Result deleteLog(
@PathVariable Long id,
@RequestParam(required = false) Long updateId) {
try {
Boolean success = manageLogService.deleteById(id, updateId);
return success ? Result.success("日志删除成功") : Result.error("删除失败(日志不存在或已删除)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,95 @@
package com.rczn.controller;
import com.rczn.domain.PageBean;
import com.rczn.domain.Result;
import com.rczn.system.domain.Position;
import com.rczn.system.service.PositionService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/position")
@Tag(name = "职位管理", description = "职位增删改查+分页查询接口")
public class PositionController {
@Autowired
private PositionService positionService;
@GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "分页查询职位", description = "支持职位名称、编码模糊查询")
@Parameters({
@Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "posiName", description = "职位名称(可选,模糊查询)", required = false, example = "工程师", in = ParameterIn.QUERY),
@Parameter(name = "posiCode", description = "职位编码(可选,模糊查询)", required = false, example = "ENG", in = ParameterIn.QUERY)
})
public Result<PageBean<Position>> getPosiPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String posiName,
@RequestParam(required = false) String posiCode) {
PageBean<Position> pageBean = positionService.selectPage(pageNum, pageSize, posiName, posiCode);
return Result.success(pageBean);
}
@GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "条件查询列表", description = "支持职位名称、编码模糊查询")
@Parameters({
@Parameter(name = "posiName", description = "职位名称(可选,模糊查询)", required = false, example = "工程师", in = ParameterIn.QUERY),
@Parameter(name = "posiCode", description = "职位编码(可选,模糊查询)", required = false, example = "ENG", in = ParameterIn.QUERY)
})
public Result getList(
@RequestParam(required = false) String posiName,
@RequestParam(required = false) String posiCode) {
List<Position> list = positionService.selectList( posiName, posiCode);
return Result.success(list);
}
@GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "查询单个职位", description = "根据职位ID查询详情")
public Result getPosiById(@PathVariable Long id) {
Position position = positionService.selectById(id);
return position != null ? Result.success(position) : Result.error("职位不存在");
}
@PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "新增职位", description = "职位名称和编码为必填项")
public Result addPosi(@RequestBody Position position) {
try {
Long posiId = positionService.insert(position);
return Result.success(posiId);
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "修改职位", description = "需传入职位ID其他字段可选非空则更新")
public Result updatePosi(@RequestBody Position position) {
try {
Boolean success = positionService.update(position);
return success ? Result.success(true) : Result.error("修改失败(职位不存在或已删除)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "删除职位", description = "逻辑删除设置delSign=1")
public Result deletePosi(@PathVariable Long id) {
try {
Boolean success = positionService.deleteById(id);
return success ? Result.success(true) : Result.error("删除失败(职位不存在或已删除)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,129 @@
package com.rczn.controller;
import com.rczn.domain.PageBean;
import com.rczn.domain.Result;
import com.rczn.system.domain.Role;
import com.rczn.system.service.RoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.*;
/**
* 角色管理 CRUD APIMyBatis+PageHelper 实现)
*/
@RestController
@RequestMapping("/role") // RESTful 规范:复数形式
@Tag(name = "角色管理", description = "角色增删改查接口(支持分页+多条件查询+编码唯一性校验)")
public class RoleController {
private final RoleService roleService;
// 构造器注入
public RoleController(RoleService roleService) {
this.roleService = roleService;
}
/**
* 1. 分页查询角色(多条件模糊查询)
*/
@GetMapping("/listPage")
@Operation(summary = "分页查询角色", description = "支持角色名、角色编码模糊查询页码从1开始")
@Parameters({
@Parameter(name = "pageNum", description = "页码必填从1开始", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "roleName", description = "角色名(模糊查询,可选)", required = false, example = "管理员", in = ParameterIn.QUERY),
@Parameter(name = "roleCode", description = "角色编码(模糊查询,可选)", required = false, example = "ADMIN", in = ParameterIn.QUERY)
})
public Result<PageBean<Role>> getRolePage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String roleName,
@RequestParam(required = false) String roleCode) {
PageBean<Role> pageBean = roleService.selectRolePage(pageNum, pageSize, roleName, roleCode);
return Result.success(pageBean);
}
/**
* 2. 根据ID查询单个角色
*/
@GetMapping("/getById/{id}")
@Operation(summary = "查询单个角色", description = "根据角色ID查询详情")
public Result getRoleById(
@Parameter(name = "id", description = "角色ID必填", required = true, example = "1", in = ParameterIn.PATH)
@PathVariable Long id) {
Role role = roleService.selectById(id);
if (role == null) {
return Result.error("角色ID" + id + " 不存在");
}
return Result.success(role);
}
/**
* 3. 新增角色(校验编码唯一性)
*/
@PostMapping("/add")
@Operation(summary = "新增角色", description = "提交角色信息角色编码不可重复ID无需传入")
public Result addRole(
@Parameter(name = "role", description = "角色信息ID无需传入roleName和roleCode必填", required = true)
@RequestBody Role role) {
try {
// 校验必填字段也可通过JSR-380注解+@Valid实现
if (role.getRoleName() == null || role.getRoleName().trim().isEmpty()) {
return Result.error("角色名不能为空");
}
if (role.getRoleCode() == null || role.getRoleCode().trim().isEmpty()) {
return Result.error("角色编码不能为空");
}
Long roleId = roleService.insert(role);
return Result.success(roleId);
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 4. 修改角色(部分字段更新+编码唯一性校验)
*/
@PutMapping("/update")
@Operation(summary = "修改角色", description = "传入角色ID和需要修改的字段角色编码不可重复")
public Result updateRole(
@Parameter(name = "role", description = "角色信息ID必填roleName/roleCode可选但至少传一个", required = true)
@RequestBody Role role) {
try {
// 校验必填字段
if (role.getId() == null) {
return Result.error("角色ID不能为空");
}
if ((role.getRoleName() == null || role.getRoleName().trim().isEmpty())
&& (role.getRoleCode() == null || role.getRoleCode().trim().isEmpty())) {
return Result.error("至少需要修改角色名或角色编码");
}
Boolean success = roleService.update(role);
return success ? Result.success("修改角色成功") : Result.error("修改失败(角色不存在)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 5. 根据ID删除角色
*/
@DeleteMapping("/del/{id}")
@Operation(summary = "删除角色", description = "根据角色ID删除角色")
public Result deleteRole(
@Parameter(name = "id", description = "角色ID必填", required = true, example = "1", in = ParameterIn.PATH)
@PathVariable Long id) {
Boolean success = roleService.deleteById(id);
return success ? Result.success("删除角色成功") : Result.error("删除失败(角色不存在)");
}
}

View File

@@ -0,0 +1,105 @@
package com.rczn.controller;
import com.rczn.domain.PageBean;
import com.rczn.domain.Result;
import com.rczn.system.domain.User;
import com.rczn.system.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* 用户管理 CRUD APIMyBatis+PageHelper 实现)
*/
@RestController
@RequestMapping("/user") // RESTful 规范:复数形式+api前缀
@Tag(name = "用户管理", description = "用户增删改查接口(支持分页+模糊查询)")
public class UserController {
// 注入 Service 层(构造器注入,推荐)
@Autowired
UserService userService;
/**
* 1. 分页查询用户(支持用户名模糊查询)
*/
@GetMapping("/listPage")
@Operation(summary = "分页查询用户", description = "支持分页、用户名模糊查询页码从1开始")
@Parameters({
@Parameter(name = "pageNum", description = "页码从1开始", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "userName", description = "用户名(模糊查询,可选)", required = false, example = "张三", in = ParameterIn.QUERY)
})
public Result<PageBean<User>> getUserPage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) String userName) {
// 调用 Service 分页查询
PageBean<User> pageBean = userService.selectUserPage(pageNum, pageSize, userName);
return Result.success(pageBean);
}
/**
* 2. 根据ID查询单个用户
*/
@GetMapping("/getById/{id}")
@Operation(summary = "查询单个用户", description = "根据用户ID查询详情")
public Result getUserById(
@Parameter(name = "id", description = "用户ID", required = true, example = "1", in = ParameterIn.PATH)
@PathVariable Long id) {
User user = userService.selectById(id);
if (user == null) {
return Result.error("用户ID" + id + " 不存在");
}
return Result.success(user);
}
/**
* 3. 新增用户
*/
@PostMapping("/add")
@Operation(summary = "新增用户", description = "提交用户完整信息创建新用户ID无需传入")
public Result addUser(
@Parameter(name = "user", description = "用户信息ID无需传入", required = true)
@RequestBody User user) {
Long userId = userService.insert(user);
return Result.success("新增用户成功");
}
/**
* 4. 修改用户(支持部分字段更新)
*/
@PutMapping("/update")
@Operation(summary = "修改用户", description = "传入用户ID和需要修改的字段非空字段才会更新")
public Result updateUser(
@Parameter(name = "user", description = "用户信息必须包含ID", required = true)
@RequestBody User user) {
try {
Boolean success = userService.update(user);
return success ? Result.success("修改用户成功") : Result.error("修改失败(用户不存在或无字段更新)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
/**
* 5. 根据ID删除用户
*/
@DeleteMapping("/del/{id}")
@Operation(summary = "删除用户", description = "根据用户ID删除用户")
public Result deleteUser(
@Parameter(name = "id", description = "用户ID", required = true, example = "1", in = ParameterIn.PATH)
@PathVariable Long id) {
Boolean success = userService.deleteById(id);
return success ? Result.success("删除用户成功") : Result.error("删除失败(用户不存在)");
}
}

View File

@@ -0,0 +1,100 @@
package com.rczn.controller;
import com.rczn.domain.PageBean;
import com.rczn.domain.Result;
import com.rczn.system.domain.UserRole;
import com.rczn.system.service.UserRoleService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/user-role")
@Tag(name = "用户角色关联管理", description = "用户与角色的关联增删改查接口")
public class UserRoleController {
@Autowired
private UserRoleService userRoleService;
@GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "分页查询关联", description = "支持用户ID、角色ID精准查询")
@Parameters({
@Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "userId", description = "用户ID可选", required = false, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "roleId", description = "角色ID可选", required = false, example = "2", in = ParameterIn.QUERY)
})
public Result<PageBean<UserRole>> getUserRolePage(
@RequestParam Integer pageNum,
@RequestParam Integer pageSize,
@RequestParam(required = false) Integer userId,
@RequestParam(required = false) Integer roleId) {
PageBean<UserRole> pageBean = userRoleService.selectPage(pageNum, pageSize, userId, roleId);
return Result.success(pageBean);
}
@GetMapping(value = "/user/{userId}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "根据用户ID查询关联角色", description = "查询指定用户的所有关联角色")
public Result<List<UserRole>> getByUserId(@PathVariable Integer userId) {
List<UserRole> userRoles = userRoleService.selectByUserId(userId);
return Result.success(userRoles);
}
@GetMapping(value = "/role/{roleId}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "根据角色ID查询关联用户", description = "查询指定角色的所有关联用户")
public Result<List<UserRole>> getByRoleId(@PathVariable Integer roleId) {
List<UserRole> userRoles = userRoleService.selectByRoleId(roleId);
return Result.success(userRoles);
}
@PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "新增用户角色关联", description = "用户ID和角色ID为必填项")
public Result addUserRole(@RequestBody UserRole userRole) {
try {
Long id = userRoleService.insert(userRole);
return Result.success(id);
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "根据关联ID删除", description = "删除单个用户-角色关联")
public Result deleteById(@PathVariable Long id) {
try {
Boolean success = userRoleService.deleteById(id);
return success ? Result.success(true) : Result.error("删除失败(关联不存在)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@DeleteMapping(value = "/user/{userId}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "根据用户ID删除所有关联", description = "删除指定用户的所有角色关联")
public Result deleteByUserId(@PathVariable Integer userId) {
try {
Boolean success = userRoleService.deleteByUserId(userId);
return success ? Result.success(true) : Result.error("删除失败(无关联数据)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
@DeleteMapping(value = "/role/{roleId}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "根据角色ID删除所有关联", description = "删除指定角色的所有用户关联")
public Result deleteByRoleId(@PathVariable Integer roleId) {
try {
Boolean success = userRoleService.deleteByRoleId(roleId);
return success ? Result.success(true) : Result.error("删除失败(无关联数据)");
} catch (IllegalArgumentException e) {
return Result.error(e.getMessage());
}
}
}

View File

@@ -0,0 +1,88 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
import java.util.List;
public class Department extends BaseBean {
private String deptName;
private String deptCode;
private Integer parentId;
private Integer leaderId;
private User leader;
// 新增:子部门列表(核心字段,用于存储树形结构)
private List<Department> children;
public Department() {
}
public Department(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
public String getDeptName() {
return deptName;
}
public void setDeptName(String deptName) {
this.deptName = deptName;
}
public String getDeptCode() {
return deptCode;
}
public void setDeptCode(String deptCode) {
this.deptCode = deptCode;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public Integer getLeaderId() {
return leaderId;
}
public void setLeaderId(Integer leaderId) {
this.leaderId = leaderId;
}
public User getLeader() {
return leader;
}
public void setLeader(User leader) {
this.leader = leader;
}
public List<Department> getChildren() {
return children;
}
public void setChildren(List<Department> children) {
this.children = children;
}
@Override
public String toString() {
return "Department{" +
"deptName='" + deptName + '\'' +
", deptCode='" + deptCode + '\'' +
", parentId=" + parentId +
", leaderId=" + leaderId +
", leader=" + leader +
", children=" + children +
'}';
}
}

View File

@@ -0,0 +1,65 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class ManageLog extends BaseBean {
private String logName;
private String logType;
private LocalDateTime logWritetime;
private String logContent;
public ManageLog() {
}
public ManageLog(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
@Override
public String toString() {
return "ManageLog{" +
"logName='" + logName + '\'' +
", logType='" + logType + '\'' +
", logWritetime=" + logWritetime +
", logContent='" + logContent + '\'' +
'}';
}
public String getLogName() {
return logName;
}
public void setLogName(String logName) {
this.logName = logName;
}
public String getLogType() {
return logType;
}
public void setLogType(String logType) {
this.logType = logType;
}
public LocalDateTime getLogWritetime() {
return logWritetime;
}
public void setLogWritetime(LocalDateTime logWritetime) {
this.logWritetime = logWritetime;
}
public String getLogContent() {
return logContent;
}
public void setLogContent(String logContent) {
this.logContent = logContent;
}
}

View File

@@ -0,0 +1,16 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class Permission extends BaseBean {
private String permissionName;
private String permissionCode;}

View File

@@ -0,0 +1,42 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class Position extends BaseBean {
private String posiName;
private String posiCode;
public Position() {
}
public Position(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
@Override
public String toString() {
return "Position{" +
"posiName='" + posiName + '\'' +
", posiCode='" + posiCode + '\'' +
'}';
}
public String getPosiName() {
return posiName;
}
public void setPosiName(String posiName) {
this.posiName = posiName;
}
public String getPosiCode() {
return posiCode;
}
public void setPosiCode(String posiCode) {
this.posiCode = posiCode;
}
}

View File

@@ -0,0 +1,27 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class Role extends BaseBean {
private String roleName;
private String roleCode;
// 全参构造器同步修改 delSign 类型Boolean → boolean
public Role(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark, String roleName, String roleCode) {
super(id, createId, createTime, updateId, updateTime, delSign, remark); // 父类参数类型同步
this.roleName = roleName;
this.roleCode = roleCode;
}
// 其他构造器、getter/setter 保持不变
public Role() { }
public Role(String roleName, String roleCode) {
this.roleName = roleName;
this.roleCode = roleCode;
}
public String getRoleName() { return roleName; }
public void setRoleName(String roleName) { this.roleName = roleName; }
public String getRoleCode() { return roleCode; }
public void setRoleCode(String roleCode) { this.roleCode = roleCode; }
}

View File

@@ -0,0 +1,56 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class RolePermission extends BaseBean {
private Integer roleId;
private Integer permissionId;
private Role role;
private Permission permission;
public RolePermission() {
}
public RolePermission(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public Integer getPermissionId() {
return permissionId;
}
public void setPermissionId(Integer permissionId) {
this.permissionId = permissionId;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public Permission getPermission() {
return permission;
}
public void setPermission(Permission permission) {
this.permission = permission;
}
}

View File

@@ -0,0 +1,152 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class User extends BaseBean {
private String userName;
private String password;
private String salt;
private String nicke;
private Boolean sex; // 0-女, 1-男
private String emailAddr;
private String address;
private String telephone;
private Integer depId;
private Integer posId;
private Department department;
private Position position;
public User() {
}
public User(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", password='" + password + '\'' +
", salt='" + salt + '\'' +
", nicke='" + nicke + '\'' +
", sex=" + sex +
", emailAddr='" + emailAddr + '\'' +
", address='" + address + '\'' +
", telephone='" + telephone + '\'' +
", depId=" + depId +
", posId=" + posId +
", department=" + department +
", position=" + position +
'}';
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getSalt() {
return salt;
}
public void setSalt(String salt) {
this.salt = salt;
}
public String getNicke() {
return nicke;
}
public void setNicke(String nicke) {
this.nicke = nicke;
}
public Boolean getSex() {
return sex;
}
public void setSex(Boolean sex) {
this.sex = sex;
}
public String getEmailAddr() {
return emailAddr;
}
public void setEmailAddr(String emailAddr) {
this.emailAddr = emailAddr;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public Integer getDepId() {
return depId;
}
public void setDepId(Integer depId) {
this.depId = depId;
}
public Integer getPosId() {
return posId;
}
public void setPosId(Integer posId) {
this.posId = posId;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public Position getPosition() {
return position;
}
public void setPosition(Position position) {
this.position = position;
}
}

View File

@@ -0,0 +1,89 @@
package com.rczn.system.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class UserRole extends BaseBean {
private Long id;
private Integer userId;
private Integer roleId;
private User user;
private Role role;
@Override
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
public UserRole() {
}
public UserRole(Long id, Integer userId, Integer roleId, User user, Role role) {
this.id = id;
this.userId = userId;
this.roleId = roleId;
this.user = user;
this.role = role;
}
public UserRole(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark, Long id1, Integer userId, Integer roleId, User user, Role role) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
this.id = id1;
this.userId = userId;
this.roleId = roleId;
this.user = user;
this.role = role;
}
@Override
public String toString() {
return "UserRole{" +
"id=" + id +
", userId=" + userId +
", roleId=" + roleId +
", user=" + user +
", role=" + role +
'}';
}
}

View File

@@ -0,0 +1,27 @@
package com.rczn.system.domain;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
/**
* 用户实体类
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Schema(description = "用户实体类") // 替代@ApiModel
public class UserTest {
@Schema(description = "用户ID", example = "1001") // 替代@ApiModelProperty
private Long id;
@Schema(description = "用户名", required = true, example = "张三")
private String name;
@Schema(description = "年龄", example = "25")
private Integer age;
}

View File

@@ -0,0 +1,44 @@
package com.rczn.system.mapper;
import com.rczn.system.domain.Department;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface DepartmentMapper {
// 新增部门
int insert(Department department);
// 根据ID删除部门逻辑删除更新delSign=1
int deleteById(Long id);
// 根据ID更新部门
int updateById(Department department);
// 根据ID查询部门
Department selectById(Long id);
// 分页查询部门(支持模糊查询)
List<Department> selectPage(
@Param("deptName") String deptName,
@Param("deptCode") String deptCode,
@Param("parentId") Integer parentId
);
// 查询分页总数(配合分页查询)
int selectTotal(
@Param("deptName") String deptName,
@Param("deptCode") String deptCode,
@Param("parentId") Integer parentId
);
// 新增:查询所有未删除的部门(用于递归组装树)
List<Department> selectAllDept();
// 新增按父部门ID查询子部门用于递归查询
List<Department> selectChildrenByParentId(@Param("parentId") Integer parentId);
// 新增查询顶级部门parent_id IS NULL
List<Department> selectTopDept();
}

View File

@@ -0,0 +1,26 @@
package com.rczn.system.mapper;
import com.rczn.system.domain.ManageLog;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper // 标记为 MyBatis Mapper 接口,确保被 Spring 扫描
public interface ManageLogMapper {
// 新增日志(支持空字段,空字段用数据库默认值)
int insert(ManageLog manageLog);
// 逻辑删除日志(按 ID设置 delSign=1
int deleteById(Long id);
// 更新日志(仅更新非空字段,空字段不更新)
int update(ManageLog manageLog);
// 按 ID 查询日志(仅查未删除数据)
ManageLog selectById(Long id);
// 分页查询日志(支持按字段筛选,空字段忽略条件)
List<ManageLog> selectPage(ManageLog manageLog);
// 查询分页总数(与分页查询条件一致)
Long selectTotal(ManageLog manageLog);
}

View File

@@ -0,0 +1,26 @@
package com.rczn.system.mapper;
import com.rczn.system.domain.Position;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface PositionMapper {
int insert(Position position);
int deleteById(Long id);
int updateById(Position position);
Position selectById(Long id);
List<Position> selectPage(
@Param("posiName") String posiName,
@Param("posiCode") String posiCode
);
int selectTotal(
@Param("posiName") String posiName,
@Param("posiCode") String posiCode
);
List<Position> selectList(
@Param("posiName") String posiName,
@Param("posiCode") String posiCode
);
}

View File

@@ -0,0 +1,55 @@
package com.rczn.system.mapper;
import com.rczn.system.domain.Role;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* Role MyBatis Mapper 接口
*/
@Mapper
public interface RoleMapper {
/**
* 分页查询角色(支持角色名/角色编码模糊查询)
*/
List<Role> selectRolePage(
@Param("roleName") String roleName,
@Param("roleCode") String roleCode);
/**
* 根据ID查询单个角色
*/
Role selectById(@Param("id") Long id);
/**
* 新增角色
*/
int insert(Role role);
/**
* 修改角色(部分字段更新)
*/
int update(Role role);
/**
* 根据ID删除角色
*/
int deleteById(@Param("id") Long id);
/**
* 查询总条数(支持模糊查询条件)
*/
Long selectTotal(
@Param("roleName") String roleName,
@Param("roleCode") String roleCode);
/**
* 校验角色编码唯一性(新增/修改时使用)
*/
Integer checkRoleCodeUnique(
@Param("roleCode") String roleCode,
@Param("id") Long id);
}

View File

@@ -0,0 +1,34 @@
package com.rczn.system.mapper;
import com.rczn.system.domain.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface UserMapper {
// 分页查询(参数支持空值,为空时忽略该条件)
List<User> selectUserPage(User user);
// 根据ID查询支持传delSign筛选状态
User selectById(@Param("id") Long id, @Param("delSign") Boolean delSign);
// 新增用户空参数会插入默认值或null
int insert(User user);
// 修改用户(仅更新非空字段)
int update(User user);
// 逻辑删除用户
int deleteById(@Param("id") Long id, @Param("updateId") Long updateId);
// 查询总条数(与分页查询参数一致)
Long selectTotal(
@Param("userName") String userName,
@Param("depId") Integer depId,
@Param("posId") Integer posId,
@Param("createId") Long createId,
@Param("sex") Integer sex,
@Param("delSign") Boolean delSign
);
}

View File

@@ -0,0 +1,44 @@
package com.rczn.system.mapper;
import com.rczn.system.domain.UserRole;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface UserRoleMapper {
// 新增用户-角色关联
int insert(UserRole userRole);
// 根据ID删除关联
int deleteById(Long id);
// 根据用户ID删除所有关联
int deleteByUserId(Integer userId);
// 根据角色ID删除所有关联
int deleteByRoleId(Integer roleId);
// 根据ID查询关联
UserRole selectById(Long id);
// 根据用户ID查询关联的角色列表
List<UserRole> selectByUserId(Integer userId);
// 根据角色ID查询关联的用户列表
List<UserRole> selectByRoleId(Integer roleId);
// 分页查询所有关联
List<UserRole> selectPage(
@Param("userId") Integer userId,
@Param("roleId") Integer roleId,
@Param("start") Integer start,
@Param("pageSize") Integer pageSize
);
// 查询分页总数
int selectTotal(
@Param("userId") Integer userId,
@Param("roleId") Integer roleId
);
}

View File

@@ -0,0 +1,35 @@
package com.rczn.system.service;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Department;
import java.util.List;
public interface DepartmentService {
// 新增部门
Long insert(Department department);
// 根据ID删除部门
Boolean deleteById(Long id);
// 根据ID更新部门
Boolean update(Department department);
// 根据ID查询部门
Department selectById(Long id);
// 分页查询部门
PageBean<Department> selectPage(
Integer pageNum,
Integer pageSize,
String deptName,
String deptCode,
Integer parentId
);
// 新增:获取完整部门树(递归组装)
List<Department> getDeptTree();
// 新增获取简化版部门树仅包含ID、名称、子部门用于下拉选择
List<Department> getSimpleDeptTree();
}

View File

@@ -0,0 +1,21 @@
package com.rczn.system.service;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.ManageLog;
public interface ManageLogService {
// 新增日志
Long insert(ManageLog manageLog);
// 逻辑删除日志
Boolean deleteById(Long id, Long updateId);
// 更新日志(仅更新非空字段)
Boolean update(ManageLog manageLog);
// 按 ID 查询日志
ManageLog selectById(Long id);
// 分页查询日志(支持多条件筛选)
PageBean<ManageLog> selectPage(Integer pageNum, Integer pageSize, ManageLog manageLog);
}

View File

@@ -0,0 +1,15 @@
package com.rczn.system.service;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Position;
import java.util.List;
public interface PositionService {
Long insert(Position position);
Boolean deleteById(Long id);
Boolean update(Position position);
Position selectById(Long id);
PageBean<Position> selectPage(Integer pageNum, Integer pageSize, String posiName, String posiCode);
List<Position> selectList(String posiName, String posiCode);
}

View File

@@ -0,0 +1,50 @@
package com.rczn.system.service;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Role;
/**
* Role 业务逻辑层接口
*/
public interface RoleService {
/**
* 分页查询角色(支持多条件模糊查询)
* @param pageNum 页码从1开始
* @param pageSize 每页条数
* @param roleName 角色名(可选)
* @param roleCode 角色编码(可选)
* @return 分页结果
*/
PageBean<Role> selectRolePage(Integer pageNum, Integer pageSize, String roleName, String roleCode);
/**
* 根据ID查询单个角色
* @param id 角色ID
* @return 角色实体
*/
Role selectById(Long id);
/**
* 新增角色(校验角色编码唯一性)
* @param role 角色实体
* @return 新增成功的角色ID
* @throws IllegalArgumentException 角色编码已存在时抛出
*/
Long insert(Role role);
/**
* 修改角色(校验角色编码唯一性+部分字段更新)
* @param role 角色实体需包含ID
* @return 是否修改成功
* @throws IllegalArgumentException 角色编码已存在或未传ID时抛出
*/
Boolean update(Role role);
/**
* 根据ID删除角色
* @param id 角色ID
* @return 是否删除成功
*/
Boolean deleteById(Long id);
}

View File

@@ -0,0 +1,16 @@
package com.rczn.system.service;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.UserRole;
import java.util.List;
public interface UserRoleService {
Long insert(UserRole userRole);
Boolean deleteById(Long id);
Boolean deleteByUserId(Integer userId);
Boolean deleteByRoleId(Integer roleId);
UserRole selectById(Long id);
List<UserRole> selectByUserId(Integer userId);
List<UserRole> selectByRoleId(Integer roleId);
PageBean<UserRole> selectPage(Integer pageNum, Integer pageSize, Integer userId, Integer roleId);
}

View File

@@ -0,0 +1,47 @@
package com.rczn.system.service;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.User;
/**
* User 业务逻辑层接口
*/
public interface UserService {
/**
* 1. 分页查询用户(支持用户名模糊查询)
* @param pageNum 页码从1开始
* @param pageSize 每页条数
* @param userName 用户名(模糊查询,可选)
* @return 分页结果PageBean
*/
PageBean<User> selectUserPage(Integer pageNum, Integer pageSize, String userName);
/**
* 2. 根据ID查询单个用户
* @param id 用户ID
* @return 单个用户实体
*/
User selectById(Long id);
/**
* 3. 新增用户
* @param user 用户实体
* @return 新增成功的用户ID
*/
Long insert(User user);
/**
* 4. 修改用户(部分字段更新)
* @param user 用户实体需包含ID仅更新非空字段
* @return 是否修改成功true/false
*/
Boolean update(User user);
/**
* 5. 根据ID删除用户
* @param id 用户ID
* @return 是否删除成功true/false
*/
Boolean deleteById(Long id);
}

View File

@@ -0,0 +1,186 @@
package com.rczn.system.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Department;
import com.rczn.system.mapper.DepartmentMapper;
import com.rczn.system.service.DepartmentService;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentMapper departmentMapper;
@Override
public Long insert(Department department) {
// 校验必填字段
Assert.notNull(department.getDeptName(), "部门名称不能为空");
Assert.notNull(department.getDeptCode(), "部门编码不能为空");
// 补充创建时间字段
// department.setCreateId(getCurrentUserId());
if (department.getCreateTime() == null) {
department.setCreateTime(LocalDateTime.now());
}
int rows = departmentMapper.insert(department);
return rows > 0 ? department.getId() : null;
}
@Override
public Boolean deleteById(Long id) {
Assert.notNull(id, "部门ID不能为空");
int rows = departmentMapper.deleteById(id);
return rows > 0;
}
@Override
public Boolean update(Department department) {
Assert.notNull(department.getId(), "部门ID不能为空");
// department.setUpdateId(null);
if (department.getUpdateTime() == null) {
department.setUpdateTime(LocalDateTime.now());
}
int rows = departmentMapper.updateById(department);
return rows > 0;
}
@Override
public Department selectById(Long id) {
Assert.notNull(id, "部门ID不能为空");
return departmentMapper.selectById(id);
}
@Override
public PageBean<Department> selectPage(Integer pageNum, Integer pageSize, String deptName, String deptCode, Integer parentId) {
// 校验分页参数
Assert.notNull(pageNum, "页码不能为空");
Assert.notNull(pageSize, "每页条数不能为空");
Assert.isTrue(pageNum > 0, "页码必须大于0");
Assert.isTrue(pageSize > 0 && pageSize <= 100000, "每页条数必须在1-10000之间");
// 1. 设置分页参数PageHelper 自动拦截后续的 SQL 进行分页)
PageHelper.startPage(pageNum, pageSize);
// 查询分页数据和总数
List<Department> items = departmentMapper.selectPage(deptName, deptCode, parentId);
Page<Department> page = (Page<Department>) items;
PageBean<Department> pageBean = new PageBean<>();
pageBean.setTotal(page.getTotal());
pageBean.setItems(page.getResult());
// 封装PageBean返回
return pageBean;
}
/**
* 核心:获取完整部门树(包含所有字段和层级关系)
*/
@Override
public List<Department> getDeptTree() {
// 1. 查询所有未删除的部门(一次性查询,减少数据库交互)
List<Department> allDept = departmentMapper.selectAllDept();
// 2. 递归组装树形结构(从顶级部门开始)
return buildDeptTree(allDept, null);
}
/**
* 核心获取简化版部门树仅ID、名称、子部门用于下拉选择框等场景
*/
@Override
public List<Department> getSimpleDeptTree() {
List<Department> allDept = departmentMapper.selectAllDept();
List<Department> deptTree = buildDeptTree(allDept, null);
// 简化部门树字段(仅保留必要字段,减少返回数据量)
return simplifyDeptTree(deptTree);
}
/**
* 递归组装部门树
* @param allDept 所有部门列表
* @param parentId 父部门IDnull 表示查询顶级部门)
* @return 组装后的子部门列表
*/
private List<Department> buildDeptTree(List<Department> allDept, Integer parentId) {
// 筛选当前父部门的所有子部门
List<Department> childrenDept = allDept.stream()
.filter(dept -> {
// 父部门ID为null时筛选parent_id IS NULL的顶级部门否则筛选parent_id等于当前parentId的部门
if (parentId == null) {
return dept.getParentId() == null;
} else {
return parentId.equals(dept.getParentId());
}
})
.collect(Collectors.toList());
// 递归为每个子部门设置下属子部门
for (Department dept : childrenDept) {
List<Department> children = buildDeptTree(allDept, dept.getId().intValue()); // dept.id是Long转Integer匹配parentId类型
dept.setLeader(null); // 简化场景可清空负责人,如需保留可删除此句
dept.setChildren(children); // 给当前部门设置子部门
}
return childrenDept;
}
/**
* 简化部门树字段仅保留ID、名称、子部门
* @param deptTree 完整部门树
* @return 简化后的部门树
*/
private List<Department> simplifyDeptTree(List<Department> deptTree) {
List<Department> simpleTree = new ArrayList<>();
for (Department dept : deptTree) {
Department simpleDept = new Department();
simpleDept.setId(dept.getId());
simpleDept.setDeptName(dept.getDeptName());
simpleDept.setDeptCode(dept.getDeptCode());
// 递归简化子部门
if (dept.getChildren() != null && !dept.getChildren().isEmpty()) {
simpleDept.setChildren(simplifyDeptTree(dept.getChildren()));
}
simpleTree.add(simpleDept);
}
return simpleTree;
}
/**
* 辅助方法获取当前登录用户ID需替换为你的实际获取逻辑如从Token中解析
*/
private Long getCurrentUserId() {
// 示例临时返回1实际项目中需替换为真实的用户ID获取逻辑如SecurityContext、ThreadLocal等
return 1L;
}
// 为Department实体类添加children字段的setter因为原实体类没有需动态设置子部门
// 注意这里是通过反射或直接在实体类中添加children字段推荐在实体类中显式添加
// 下面是临时解决方案实际需修改Department实体类见步骤六
private void setChildren(Department dept, List<Department> children) {
try {
// 通过反射给Department设置children字段若实体类已添加可直接调用setChildren
java.lang.reflect.Field field = Department.class.getDeclaredField("children");
field.setAccessible(true);
field.set(dept, children);
} catch (Exception e) {
throw new RuntimeException("设置部门子节点失败", e);
}
}
}

View File

@@ -0,0 +1,86 @@
package com.rczn.system.service.impl;
import com.github.pagehelper.Page;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.ManageLog;
import com.github.pagehelper.PageHelper;
import com.rczn.system.domain.Position;
import com.rczn.system.mapper.ManageLogMapper;
import com.rczn.system.service.ManageLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class ManageLogServiceImpl implements ManageLogService {
@Autowired
private ManageLogMapper manageLogMapper;
@Override
public Long insert(ManageLog manageLog) {
// 校验必填字段(日志名称和类型为必填)
Assert.notNull(manageLog.getLogName(), "日志名称不能为空");
Assert.notNull(manageLog.getLogType(), "日志类型不能为空");
//补充日志时间
if (manageLog.getLogWritetime() == null) {
manageLog.setLogWritetime(LocalDateTime.now());
}
// TODO 补充日志创建人信息
// manageLog.setCreateId(null);
manageLog.setCreateTime(LocalDateTime.now());
int rows = manageLogMapper.insert(manageLog);
return rows > 0 ? manageLog.getId() : null;
}
@Override
public Boolean deleteById(Long id, Long updateId) {
Assert.notNull(id, "日志ID不能为空");
int rows = manageLogMapper.deleteById(id);
return rows > 0;
}
@Override
public Boolean update(ManageLog manageLog) {
Assert.notNull(manageLog.getId(), "日志ID不能为空");
//如果更新时间为空,则自动更新
if (manageLog.getUpdateTime() == null) {
manageLog.setUpdateTime(LocalDateTime.now());
}
// TODO 补充日志更新人信息
// manageLog.setUpdateId(null);
int rows = manageLogMapper.update(manageLog);
return rows > 0;
}
@Override
public ManageLog selectById(Long id) {
Assert.notNull(id, "日志ID不能为空");
return manageLogMapper.selectById(id);
}
@Override
public PageBean<ManageLog> selectPage(Integer pageNum, Integer pageSize, ManageLog manageLog) {
// 校验分页参数
Assert.notNull(pageNum, "页码不能为空");
Assert.notNull(pageSize, "每页条数不能为空");
Assert.isTrue(pageNum > 0, "页码必须大于0");
Assert.isTrue(pageSize > 0 && pageSize <= 100000, "每页条数必须在1-10000之间");
// PageHelper 分页(自动拦截查询,添加 LIMIT 条件)
PageHelper.startPage(pageNum, pageSize);
List<ManageLog> logList = manageLogMapper.selectPage(manageLog);
Page<ManageLog> page = (Page<ManageLog>) logList;
PageBean<ManageLog> pageBean = new PageBean<>();
pageBean.setTotal(page.getTotal());
pageBean.setItems(page.getResult());
// 封装PageBean返回
return pageBean;
}
}

View File

@@ -0,0 +1,83 @@
package com.rczn.system.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Department;
import com.rczn.system.domain.Position;
import com.rczn.system.mapper.PositionMapper;
import com.rczn.system.service.PositionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.List;
@Service
public class PositionServiceImpl implements PositionService {
@Autowired
private PositionMapper positionMapper;
@Override
public Long insert(Position position) {
Assert.notNull(position.getPosiName(), "职位名称不能为空");
Assert.notNull(position.getPosiCode(), "职位编码不能为空");
int rows = positionMapper.insert(position);
return rows > 0 ? position.getId() : null;
}
@Override
public Boolean deleteById(Long id) {
Assert.notNull(id, "职位ID不能为空");
int rows = positionMapper.deleteById(id);
return rows > 0;
}
@Override
public Boolean update(Position position) {
Assert.notNull(position.getId(), "职位ID不能为空");
int rows = positionMapper.updateById(position);
return rows > 0;
}
@Override
public Position selectById(Long id) {
Assert.notNull(id, "职位ID不能为空");
return positionMapper.selectById(id);
}
@Override
public PageBean<Position> selectPage(Integer pageNum, Integer pageSize, String posiName, String posiCode) {
Assert.notNull(pageNum, "页码不能为空");
Assert.notNull(pageSize, "每页条数不能为空");
Assert.isTrue(pageNum > 0, "页码必须大于0");
Assert.isTrue(pageSize > 0 && pageSize <= 100000, "每页条数必须在1-10000之间");
// 1. 设置分页参数PageHelper 自动拦截后续的 SQL 进行分页)
PageHelper.startPage(pageNum, pageSize);
// 查询分页数据和总数
List<Position> items = positionMapper.selectPage(posiName, posiCode);
Page<Position> page = (Page<Position>) items;
PageBean<Position> pageBean = new PageBean<>();
pageBean.setTotal(page.getTotal());
pageBean.setItems(page.getResult());
// 封装PageBean返回
return pageBean;
}
/**
* 条件查询职位列表
* @param posiName 职位名称
* @param posiCode 职位编码
* @return 职位列表
*/
@Override
public List<Position> selectList(String posiName, String posiCode) {
return positionMapper.selectList(posiName, posiCode);
}
}

View File

@@ -0,0 +1,98 @@
package com.rczn.system.service.impl;
import com.github.pagehelper.PageHelper;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Role;
import com.rczn.system.mapper.RoleMapper;
import com.rczn.system.service.RoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
/**
* Role 业务逻辑层实现
*/
@Service
@Transactional
public class RoleServiceImpl implements RoleService {
@Autowired
RoleMapper roleMapper;
@Override
public PageBean<Role> selectRolePage(Integer pageNum, Integer pageSize, String roleName, String roleCode) {
// 1. PageHelper 设置分页参数
PageHelper.startPage(pageNum, pageSize);
// 2. 执行查询
List<Role> roleList = roleMapper.selectRolePage(roleName, roleCode);
// 3. 查询总条数
Long total = roleMapper.selectTotal(roleName, roleCode);
// 4. 封装分页结果
return new PageBean<Role>() {{
setTotal(total);
setItems(roleList);
}};
}
@Override
public Role selectById(Long id) {
return roleMapper.selectById(id);
}
@Override
public Long insert(Role role) {
// 校验角色编码唯一性
Integer count = roleMapper.checkRoleCodeUnique(role.getRoleCode(), null);
if (count != null && count > 0) {
throw new IllegalArgumentException("角色编码:" + role.getRoleCode() + " 已存在");
}
// 更新创建时间、创建者
// TODO 待实现
// role.setCreateId(1L);
if (role.getCreateTime() == null) {
role.setCreateTime(LocalDateTime.now());
}
// 执行新增自动回填ID
roleMapper.insert(role);
return role.getId();
}
@Override
public Boolean update(Role role) {
// 校验ID是否存在
if (role.getId() == null) {
throw new IllegalArgumentException("修改角色必须传入ID");
}
// 校验角色编码唯一性(排除自身)
Integer count = roleMapper.checkRoleCodeUnique(role.getRoleCode(), role.getId());
if (count != null && count > 0) {
throw new IllegalArgumentException("角色编码:" + role.getRoleCode() + " 已存在");
}
// 更新更新时间、更新者
// TODO 待实现
// role.setUpdateId(1L);
if (role.getUpdateTime() == null) {
role.setUpdateTime(LocalDateTime.now());
}
// 执行修改
int rows = roleMapper.update(role);
return rows > 0;
}
@Override
public Boolean deleteById(Long id) {
// 先校验角色是否存在
Role role = roleMapper.selectById(id);
if (role == null) {
return false;
}
// 执行删除
int rows = roleMapper.deleteById(id);
return rows > 0;
}
}

View File

@@ -0,0 +1,86 @@
package com.rczn.system.service.impl;
import com.github.pagehelper.Page;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.Position;
import com.rczn.system.domain.UserRole;
import com.rczn.system.mapper.UserRoleMapper;
import com.rczn.system.service.UserRoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.List;
@Service
public class UserRoleServiceImpl implements UserRoleService {
@Autowired
private UserRoleMapper userRoleMapper;
@Override
public Long insert(UserRole userRole) {
Assert.notNull(userRole.getUserId(), "用户ID不能为空");
Assert.notNull(userRole.getRoleId(), "角色ID不能为空");
int rows = userRoleMapper.insert(userRole);
return rows > 0 ? userRole.getId() : null;
}
@Override
public Boolean deleteById(Long id) {
Assert.notNull(id, "关联ID不能为空");
int rows = userRoleMapper.deleteById(id);
return rows > 0;
}
@Override
public Boolean deleteByUserId(Integer userId) {
Assert.notNull(userId, "用户ID不能为空");
int rows = userRoleMapper.deleteByUserId(userId);
return rows > 0;
}
@Override
public Boolean deleteByRoleId(Integer roleId) {
Assert.notNull(roleId, "角色ID不能为空");
int rows = userRoleMapper.deleteByRoleId(roleId);
return rows > 0;
}
@Override
public UserRole selectById(Long id) {
Assert.notNull(id, "关联ID不能为空");
return userRoleMapper.selectById(id);
}
@Override
public List<UserRole> selectByUserId(Integer userId) {
Assert.notNull(userId, "用户ID不能为空");
return userRoleMapper.selectByUserId(userId);
}
@Override
public List<UserRole> selectByRoleId(Integer roleId) {
Assert.notNull(roleId, "角色ID不能为空");
return userRoleMapper.selectByRoleId(roleId);
}
@Override
public PageBean<UserRole> selectPage(Integer pageNum, Integer pageSize, Integer userId, Integer roleId) {
Assert.notNull(pageNum, "页码不能为空");
Assert.notNull(pageSize, "每页条数不能为空");
Assert.isTrue(pageNum > 0, "页码必须大于0");
Assert.isTrue(pageSize > 0 && pageSize <= 100000, "每页条数必须在1-10000之间");
int start = (pageNum - 1) * pageSize;
List<UserRole> items = userRoleMapper.selectPage(userId, roleId, start, pageSize);
Page<UserRole> page = (Page<UserRole>) items;
PageBean<UserRole> pageBean = new PageBean<>();
pageBean.setTotal(page.getTotal());
pageBean.setItems(page.getResult());
// 封装PageBean返回
return pageBean;
}
}

View File

@@ -0,0 +1,77 @@
package com.rczn.system.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.rczn.domain.PageBean;
import com.rczn.system.domain.User;
import com.rczn.system.mapper.UserMapper;
import com.rczn.system.service.UserService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* User 业务逻辑层实现
*/
@Service
@Transactional // 事务管理(增删改操作需事务)
public class UserServiceImpl implements UserService {
// 注入 MapperLombok @RequiredArgsConstructor 自动生成构造器)
@Autowired
UserMapper userMapper;
@Override
public PageBean<User> selectUserPage(Integer pageNum, Integer pageSize, String userName) {
// 1. 设置分页参数PageHelper 自动拦截后续的 SQL 进行分页)
PageHelper.startPage(pageNum, pageSize);
// 2. 执行查询MyBatis 会自动添加 LIMIT 分页)
User user = new User();
user.setUserName(userName);
List<User> userList = userMapper.selectUserPage(user);
Page<User> userPage = (Page<User>) userList;
// 3. 查询总条数(支持模糊查询条件)
PageBean<User> pageBean = new PageBean<>();
pageBean.setTotal(userPage.getTotal());
pageBean.setItems(userPage);
// 4. 封装分页结果(使用你的自定义 PageBean
return pageBean;
}
@Override
public User selectById(Long id) {
// 查询不到返回 null后续 Controller 处理)
return userMapper.selectById(id, false);
}
@Override
public Long insert(User user) {
// 执行新增XML 中已配置 useGeneratedKeys会自动回填 ID 到 user 对象)
userMapper.insert(user);
return user.getId(); // 返回新增用户的 ID
}
@Override
public Boolean update(User user) {
if (user.getId() == null) {
throw new IllegalArgumentException("修改用户必须传入 ID");
}
// 执行修改(返回影响行数,>0 表示修改成功)
int rows = userMapper.update(user);
return rows > 0;
}
@Override
public Boolean deleteById(Long id) {
// 执行删除(返回影响行数,>0 表示删除成功)
int rows = userMapper.deleteById(id,null);
return rows > 0;
}
}

View File

@@ -0,0 +1,97 @@
# 服务器配置
server:
port: 9090 # 项目端口
servlet:
encoding:
charset: UTF-8 # 解决中文乱码(含接口文档/响应)
enabled: true
force: true
# Spring核心配置
spring:
application:
name: rczn-admin # 应用名称
# 数据源配置MySQL 8.x
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.116.126.33:3306/rc_autoplc_program?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: nianke
password: Jy@.niankeCrm2025
# 解决跨域可选配合之前的CorsConfig
web:
cors:
allowed-origins: false # 禁用默认CORS使用自定义CorsConfig
# 关键Jackson 序列化配置(替代 JacksonConfig
jackson:
# 允许空对象序列化(解决 HttpMediaTypeNotAcceptableException 核心)
serialization:
fail-on-empty-beans: false
# 格式化 JSON 输出(可选,便于调试)
indent-output: true
# 忽略未知字段(避免前端传多余字段报错)
deserialization:
fail-on-unknown-properties: false
# 支持 Java 8 日期类型LocalDateTime
modules:
- com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
# 日期格式化(可选,统一日期返回格式)
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
# MyBatis配置
mybatis:
configuration:
map-underscore-to-camel-case: true # 下划线转驼峰
mapper-locations: classpath:mapper/**/*.xml # 补充指定Mapper.xml文件路径必加
type-aliases-package: com.rczn.**.domain # 补充:实体类别名包(可选)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 关键SQL 打印到控制台
log-prefix: "[MyBatis] " # 可选:日志前缀,便于区分 SQL 日志
default-statement-timeout: 30 # 可选SQL 执行超时时间(秒)
# HikariCP 连接池配置(关键)
hikari:
max-lifetime: 1800000 # 连接最大生命周期30 分钟,必须小于 MySQL wait_timeout默认 8 小时)
idle-timeout: 600000 # 连接空闲超时时间10 分钟)
connection-timeout: 30000 # 连接超时时间30 秒)
minimum-idle: 5 # 最小空闲连接数
maximum-pool-size: 10 # 最大连接池大小
test-while-idle: true # 空闲时检测连接有效性
validation-timeout: 5000 # 连接校验超时时间5 秒)
connection-test-query: SELECT 1 # 连接校验 SQLMySQL 可用此简单查询)
# PageHelper 分页插件配置
pagehelper:
helper-dialect: mysql # 数据库方言(适配 MySQL
reasonable: true # 合理化分页页码≤0时查第1页页码超出总页数时查最后1页
support-methods-arguments: true # 支持通过 Mapper 接口参数传递分页参数
params: count=countSql # 分页参数名映射
# SpringDoc OpenAPI 3 核心配置适配Spring Boot 3.x
springdoc:
packages-to-scan: com.rczn # 扫描的基础包Controller所在包
api-docs:
enabled: true # 启用/v3/api-docs接口
path: /v3/api-docs # OpenAPI JSON数据路径默认
swagger-ui:
path: /swagger-ui.html # 自定义Swagger UI访问路径兼容Spring Boot 2.x习惯
tags-sorter: alpha # 标签字母排序
operations-sorter: alpha # 接口字母排序
disable-swagger-default-url: true # 禁用默认PetStore示例
default-flat-param-object: false # 禁用扁平参数对象
paths-to-exclude: /error, /actuator/** # 排除错误接口/监控接口(可选)
# OpenAPI文档基础信息中文正常显示
openapi:
info:
title: XX自动化编程系统API文档
description: SpringBoot 3.x + SpringDoc OpenAPI 3 接口文档
version: 1.0.0
contact:
name: 研发组
email: xxx@xxx.com
servers:
- url: http://localhost:9090 # 开发环境地址
description: 本地开发环境
- url: http://47.116.126.33:9090 # 测试环境地址
description: 测试环境

View File

@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rczn.system.mapper.DepartmentMapper">
<!-- 通用字段BaseBean继承的字段 -->
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<!-- Department专属字段 -->
<sql id="deptColumn">
dept_name, dept_code, parent_id, leader_id
</sql>
<!-- 新增部门(修复多余逗号问题,支持空字段忽略) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_department (
<!-- 用 trim 标签prefix="(" suffix=")" suffixOverrides="," 去除末尾多余逗号 -->
<trim prefix="" suffix="" suffixOverrides=",">
<!-- 通用字段:非空才添加字段 -->
<if test="createId != null">create_id,</if>
<if test="createTime != null">create_time,</if>
<if test="remark != null and remark != ''">remark,</if>
<!-- 部门专属字段:非空才添加字段 -->
<if test="deptName != null and deptName != ''">dept_name,</if>
<if test="deptCode != null and deptCode != ''">dept_code,</if>
<if test="parentId != null">parent_id,</if>
<if test="leaderId != null">leader_id,</if>
</trim>
) VALUES (
<!-- 用 trim 标签去除值列表末尾多余逗号 -->
<trim prefix="" suffix="" suffixOverrides=",">
<!-- 通用字段:非空才添加值 -->
<if test="createId != null">#{createId},</if>
<if test="createTime != null">#{createTime},</if>
<if test="remark != null and remark != ''">#{remark},</if>
<!-- 部门专属字段:非空才添加值 -->
<if test="deptName != null and deptName != ''">#{deptName},</if>
<if test="deptCode != null and deptCode != ''">#{deptCode},</if>
<if test="parentId != null">#{parentId},</if>
<if test="leaderId != null">#{leaderId},</if>
</trim>
)
</insert>
<!-- 逻辑删除部门 -->
<update id="deleteById">
UPDATE sys_department
SET del_sign = 1, update_time = NOW()
WHERE id = #{id} AND del_sign = 0
</update>
<!-- 更新部门 -->
<update id="updateById">
UPDATE sys_department
<set>
<if test="deptName != null and deptName != ''">dept_name = #{deptName},</if>
<if test="deptCode != null and deptCode != ''">dept_code = #{deptCode},</if>
<if test="parentId != null">parent_id = #{parentId},</if>
<if test="leaderId != null">leader_id = #{leaderId},</if>
<if test="updateId != null">update_id = #{updateId},</if>
<if test="remark != null">remark = #{remark},</if>
update_time = NOW()
</set>
WHERE id = #{id} AND del_sign = 0
</update>
<!-- 根据ID查询部门 -->
<select id="selectById" resultType="com.rczn.system.domain.Department">
SELECT
<include refid="baseColumn"/>, <include refid="deptColumn"/>
FROM sys_department
WHERE id = #{id} AND del_sign = 0
</select>
<!-- 分页查询部门 -->
<select id="selectPage" resultType="com.rczn.system.domain.Department">
SELECT
<include refid="baseColumn"/>, <include refid="deptColumn"/>
FROM sys_department
WHERE del_sign = 0
<if test="deptName != null and deptName != ''">
AND dept_name LIKE CONCAT('%', #{deptName}, '%')
</if>
<if test="deptCode != null and deptCode != ''">
AND dept_code LIKE CONCAT('%', #{deptCode}, '%')
</if>
<if test="parentId != null">
AND parent_id = #{parentId}
</if>
ORDER BY id DESC
</select>
<!-- 查询分页总数 -->
<select id="selectTotal" resultType="java.lang.Integer">
SELECT COUNT(id)
FROM sys_department
WHERE del_sign = 0
<if test="deptName != null and deptName != ''">
AND dept_name LIKE CONCAT('%', #{deptName}, '%')
</if>
<if test="deptCode != null and deptCode != ''">
AND dept_code LIKE CONCAT('%', #{deptCode}, '%')
</if>
<if test="parentId != null">
AND parent_id = #{parentId}
</if>
</select>
<!-- 公共字段映射复用原有resultMap新增parent/leader关联 -->
<resultMap id="DeptResultMap" type="com.rczn.system.domain.Department">
<!-- 基础字段继承BaseBean -->
<id column="id" property="id"/>
<result column="create_id" property="createId"/>
<result column="create_time" property="createTime"/>
<result column="update_id" property="updateId"/>
<result column="update_time" property="updateTime"/>
<result column="del_sign" property="delSign"/>
<result column="remark" property="remark"/>
<!-- 部门专属字段 -->
<result column="dept_name" property="deptName"/>
<result column="dept_code" property="deptCode"/>
<result column="parent_id" property="parentId"/>
<result column="leader_id" property="leaderId"/>
<!-- &lt;!&ndash; 关联父部门(可选,用于显示父部门名称) &ndash;&gt;-->
<!-- <association property="parent" javaType="com.rczn.system.domain.Department">-->
<!-- <id column="parent_id" property="id"/>-->
<!-- <result column="parent_dept_name" property="deptName"/>-->
<!-- </association>-->
<!-- &lt;!&ndash; 关联部门负责人(可选,用于显示负责人名称) &ndash;&gt;-->
<!-- <association property="leader" javaType="com.rczn.system.domain.User">-->
<!-- <id column="leader_id" property="id"/>-->
<!-- <result column="leader_name" property="userName"/>-->
<!-- </association>-->
</resultMap>
<!-- 1. 查询所有未删除的部门(用于递归组装树) -->
<select id="selectAllDept" resultMap="DeptResultMap">
SELECT
d.id, d.dept_name, d.dept_code, d.parent_id, d.leader_id,
d.create_id, d.create_time, d.update_id, d.update_time, d.del_sign, d.remark
-- p.dept_name AS parent_dept_name, -- 父部门名称(关联查询)
-- u.user_name AS leader_name -- 负责人名称(关联查询)
FROM sys_department d
-- LEFT JOIN sys_department p ON d.parent_id = p.id AND p.del_sign = 0 -- 关联父部门(未删除)
-- LEFT JOIN sys_user u ON d.leader_id = u.id AND u.del_sign = 0 -- 关联负责人(未删除)
WHERE d.del_sign = 0 -- 仅查询未删除的部门
ORDER BY d.id ASC
</select>
<!-- 2. 按父部门ID查询子部门用于递归查询 -->
<select id="selectChildrenByParentId" resultMap="DeptResultMap" parameterType="java.lang.Integer">
SELECT
d.id, d.dept_name, d.dept_code, d.parent_id, d.leader_id,
d.create_id, d.create_time, d.update_id, d.update_time, d.del_sign, d.remark
-- p.dept_name AS parent_dept_name,
-- u.user_name AS leader_name
FROM sys_department d
-- LEFT JOIN sys_department p ON d.parent_id = p.id AND p.del_sign = 0
-- LEFT JOIN sys_user u ON d.leader_id = u.id AND u.del_sign = 0
WHERE d.del_sign = 0
AND d.parent_id = #{parentId} -- 按父部门ID筛选
ORDER BY d.id ASC
</select>
<!-- 3. 查询顶级部门parent_id IS NULL -->
<select id="selectTopDept" resultMap="DeptResultMap">
SELECT
d.id, d.dept_name, d.dept_code, d.parent_id, d.leader_id,
d.create_id, d.create_time, d.update_id, d.update_time, d.del_sign, d.remark
-- p.dept_name AS parent_dept_name,
-- u.user_name AS leader_name
FROM sys_department d
-- LEFT JOIN sys_department p ON d.parent_id = p.id AND p.del_sign = 0
-- LEFT JOIN sys_user u ON d.leader_id = u.id AND u.del_sign = 0
WHERE d.del_sign = 0
AND d.parent_id IS NULL -- 顶级部门(无父部门)
ORDER BY d.id ASC
</select>
</mapper>

View File

@@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rczn.system.mapper.ManageLogMapper">
<!-- 公共字段BaseBean 继承的字段) -->
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<!-- ManageLog 专属字段 -->
<sql id="logColumn">
log_name, log_type, log_writetime, log_content
</sql>
<!-- 结果集映射(关联数据库列与实体类字段) -->
<resultMap id="LogResultMap" type="com.rczn.system.domain.ManageLog">
<!-- 公共字段映射 -->
<id column="id" property="id"/>
<result column="create_id" property="createId"/>
<result column="create_time" property="createTime"/>
<result column="update_id" property="updateId"/>
<result column="update_time" property="updateTime"/>
<result column="del_sign" property="delSign"/>
<result column="remark" property="remark"/>
<!-- 专属字段映射 -->
<result column="log_name" property="logName"/>
<result column="log_type" property="logType"/>
<result column="log_writetime" property="logWritetime"/>
<result column="log_content" property="logContent"/>
</resultMap>
<!-- 1. 新增日志(空字段忽略,用数据库默认值) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_manage_log (
<trim suffixOverrides=",">
<!-- 专属字段 -->
<if test="logName != null and logName != ''"> log_name,</if>
<if test="logType != null and logType != ''"> log_type,</if>
<if test="logWritetime != null"> log_writetime,</if>
<if test="logContent != null and logContent != ''"> log_content,</if>
<!-- 公共字段 -->
<if test="createId != null"> create_id,</if>
<if test="createTime != null"> create_time,</if>
<if test="updateId != null"> update_id,</if>
<if test="updateTime != null"> update_time,</if>
<if test="delSign != null"> del_sign,</if>
<if test="remark != null and remark != ''"> remark,</if>
</trim>
) VALUES (
<trim suffixOverrides=",">
<!-- 专属字段:空字段传递 null数据库设默认值 -->
<if test="logName != null and logName != ''">#{logName},</if>
<if test="logType != null and logType != ''">#{logType},</if>
<if test="logWritetime != null">#{logWritetime},</if>
<if test="logContent != null and logContent != ''">#{logContent},</if>
<!-- 公共字段:空字段传递 null数据库设默认值 -->
<if test="createId != null">#{createId},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateId != null">#{updateId},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="delSign != null">#{delSign},</if>
<if test="remark != null and remark != ''">#{remark},</if>
</trim>
)
</insert>
<!-- 2. 更新日志(仅更新非空字段) -->
<update id="update">
UPDATE sys_manage_log
<set>
<!-- 专属字段:非空才更新 -->
<if test="logName != null and logName != ''">log_name = #{logName},</if>
<if test="logType != null and logType != ''">log_type = #{logType},</if>
<if test="logWritetime != null">log_writetime = #{logWritetime},</if>
<if test="logContent != null and logContent != ''">log_content = #{logContent},</if>
<!-- 公共字段:非空才更新 -->
<if test="updateId != null">update_id = #{updateId},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="delSign != null">del_sign = #{delSign},</if>
<!-- 强制更新时间为当前时间 -->
update_time = NOW()
</set>
WHERE id = #{id}
AND del_sign = 0 <!-- 仅更新未删除的数据 -->
</update>
<!-- 3. 逻辑删除日志 -->
<delete id="deleteById">
UPDATE sys_manage_log
SET
del_sign = 1,
update_time = NOW(),
<if test="updateId != null">update_id = #{updateId}</if>
WHERE id = #{id}
AND del_sign = 0 <!-- 避免重复删除 -->
</delete>
<!-- 4. 按 ID 查询日志 -->
<select id="selectById" resultMap="LogResultMap">
SELECT
<include refid="baseColumn"/>,
<include refid="logColumn"/>
FROM sys_manage_log
WHERE id = #{id}
AND del_sign = 0 <!-- 仅查未删除数据 -->
</select>
<!-- 5. 分页查询日志(空字段忽略条件) -->
<select id="selectPage" resultMap="LogResultMap" parameterType="com.rczn.system.domain.ManageLog">
SELECT
<include refid="baseColumn"/>,
<include refid="logColumn"/>
FROM sys_manage_log
<where>
<!-- 默认查未删除数据,传 delSign=1 可查已删除 -->
<if test="delSign == null">
AND del_sign = 0
</if>
<if test="delSign != null">
AND del_sign = #{delSign}
</if>
<!-- 日志名称:模糊查询,空字段忽略 -->
<if test="logName != null and logName != ''">
AND log_name LIKE CONCAT('%', #{logName}, '%')
</if>
<!-- 日志类型:精准查询,空字段忽略 -->
<if test="logType != null and logType != ''">
AND log_type = #{logType}
</if>
<!-- 日志写入时间:范围查询(可选,空字段忽略) -->
<if test="startTime != null">
AND log_writetime >= #{startTime}
</if>
<if test="endTime != null">
AND log_writetime &lt;= #{endTime}
</if>
<!-- 创建人ID精准查询空字段忽略 -->
<if test="createId != null">
AND create_id = #{createId}
</if>
</where>
ORDER BY log_writetime DESC <!-- 按日志写入时间倒序 -->
</select>
<!-- 6. 查询分页总数(与分页查询条件一致) -->
<select id="selectTotal" resultType="java.lang.Long" parameterType="com.rczn.system.domain.ManageLog">
SELECT COUNT(*)
FROM sys_manage_log
<where>
<if test="delSign == null">
AND del_sign = 0
</if>
<if test="delSign != null">
AND del_sign = #{delSign}
</if>
<if test="logName != null and logName != ''">
AND log_name LIKE CONCAT('%', #{logName}, '%')
</if>
<if test="logType != null and logType != ''">
AND log_type = #{logType}
</if>
<if test="logWritetimeStart != null">
AND log_writetime >= #{logWritetimeStart}
</if>
<if test="logWritetimeEnd != null">
AND log_writetime &lt;= #{logWritetimeEnd}
</if>
<if test="createId != null">
AND create_id = #{createId}
</if>
</where>
</select>
</mapper>

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rczn.system.mapper.PositionMapper">
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<sql id="posiColumn">
posi_name, posi_code
</sql>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_position (
<include refid="posiColumn"/>, create_time, update_time, del_sign
) VALUES (
#{posiName}, #{posiCode}, NOW(), NOW(), 0
)
</insert>
<update id="deleteById">
UPDATE sys_position
SET del_sign = 1, update_time = NOW()
WHERE id = #{id} AND del_sign = 0
</update>
<update id="updateById">
UPDATE sys_position
<set>
<if test="posiName != null and posiName != ''">posi_name = #{posiName},</if>
<if test="posiCode != null and posiCode != ''">posi_code = #{posiCode},</if>
<if test="updateId != null">update_id = #{updateId},</if>
<if test="remark != null">remark = #{remark},</if>
update_time = NOW()
</set>
WHERE id = #{id} AND del_sign = 0
</update>
<select id="selectById" resultType="com.rczn.system.domain.Position">
SELECT
<include refid="baseColumn"/>, <include refid="posiColumn"/>
FROM sys_position
WHERE id = #{id} AND del_sign = 0
</select>
<select id="selectPage" resultType="com.rczn.system.domain.Position">
SELECT
<include refid="baseColumn"/>, <include refid="posiColumn"/>
FROM sys_position
WHERE del_sign = 0
<if test="posiName != null and posiName != ''">
AND posi_name LIKE CONCAT('%', #{posiName}, '%')
</if>
<if test="posiCode != null and posiCode != ''">
AND posi_code LIKE CONCAT('%', #{posiCode}, '%')
</if>
ORDER BY id DESC
</select>
<select id="selectTotal" resultType="java.lang.Integer">
SELECT COUNT(id)
FROM sys_position
WHERE del_sign = 0
<if test="posiName != null and posiName != ''">
AND posi_name LIKE CONCAT('%', #{posiName}, '%')
</if>
<if test="posiCode != null and posiCode != ''">
AND posi_code LIKE CONCAT('%', #{posiCode}, '%')
</if>
</select>
<select id="selectList" resultType="com.rczn.system.domain.Position">
SELECT
<include refid="baseColumn"/>, <include refid="posiColumn"/>
FROM sys_position
WHERE del_sign = 0
<if test="posiName != null and posiName != ''">
AND posi_name LIKE CONCAT('%', #{posiName}, '%')
</if>
<if test="posiCode != null and posiCode != ''">
AND posi_code LIKE CONCAT('%', #{posiCode}, '%')
</if>
ORDER BY id DESC
</select>
</mapper>

View File

@@ -0,0 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rczn.system.mapper.RoleMapper">
<!-- 通用结果集映射 -->
<resultMap id="RoleResultMap" type="com.rczn.system.domain.Role">
<id column="id" property="id"/>
<result column="role_name" property="roleName"/>
<result column="role_code" property="roleCode"/>
</resultMap>
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<!-- 1. 分页查询角色(支持多条件模糊查询) -->
<select id="selectRolePage" resultMap="RoleResultMap">
SELECT id, role_name, role_code
FROM sys_role
<where>
<if test="roleName != null and roleName != ''">
AND role_name LIKE CONCAT('%', #{roleName}, '%')
</if>
<if test="roleCode != null and roleCode != ''">
AND role_code LIKE CONCAT('%', #{roleCode}, '%')
</if>
</where>
ORDER BY id DESC
</select>
<!-- 2. 根据ID查询角色 -->
<select id="selectById" resultMap="RoleResultMap">
SELECT <include refid="baseColumn"></include>, role_name, role_code
FROM sys_role
WHERE id = #{id}
</select>
<!-- 3. 新增角色 -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_role (
<trim suffixOverrides=",">
<if test="roleName != null ">role_name,</if>
<if test="roleCode != null ">role_code,</if>
<if test="createId != null ">create_id,</if>
<if test="createTime != null ">create_time,</if>
<if test="updateId != null ">update_id,</if>
<if test="updateTime != null ">update_time,</if>
<if test="delSign != null ">del_sign,</if>
<if test="remark != null ">remark,</if>
</trim>
)
VALUES (
<trim suffixOverrides=",">
<if test="roleName != null ">#{roleName},</if>
<if test="roleCode != null ">#{roleCode},</if>
<if test="createId != null ">#{createId},</if>
<if test="createTime != null ">#{createTime},</if>
<if test="updateId != null ">#{updateId},</if>
<if test="updateTime != null ">#{updateTime},</if>
<if test="delSign != null ">#{delSign},</if>
<if test="remark != null ">#{remark},</if>
</trim>
)
</insert>
<!-- 4. 修改角色(仅更新非空字段) -->
<update id="update">
UPDATE sys_role
<set>
<if test="roleName != null ">role_name = #{roleName},</if>
<if test="roleCode != null ">role_code = #{roleCode}</if>
<if test="updateId != null ">updateId = NULL,</if>
<if test="updateTime != null ">updateTime = now(),</if>
<if test="remark != null ">remark = NULL,</if>
</set>
WHERE id = #{id}
</update>
<!-- 5. 根据ID删除角色 -->
<delete id="deleteById">
DELETE FROM sys_role WHERE id = #{id}
</delete>
<!-- 6. 查询总条数(支持多条件模糊查询) -->
<select id="selectTotal" resultType="java.lang.Long">
SELECT COUNT(*) FROM sys_role
<where>
<if test="roleName != null and roleName != ''">
AND role_name LIKE CONCAT('%', #{roleName}, '%')
</if>
<if test="roleCode != null and roleCode != ''">
AND role_code LIKE CONCAT('%', #{roleCode}, '%')
</if>
</where>
</select>
<!-- 7. 校验角色编码唯一性 -->
<select id="checkRoleCodeUnique" resultType="java.lang.Integer">
SELECT COUNT(*) FROM sys_role
WHERE role_code = #{roleCode}
<if test="id != null">
AND id != #{id} <!-- 修改时排除自身ID -->
</if>
</select>
</mapper>

View File

@@ -0,0 +1,202 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- 对应 Mapper 接口全路径 -->
<mapper namespace="com.rczn.system.mapper.UserMapper">
<!-- 通用结果集映射(复用,避免重复编写) -->
<resultMap id="UserResultMap" type="com.rczn.system.domain.User">
<id column="id" property="id"/>
<result column="create_id" property="createId"/>
<result column="create_time" property="createTime"/>
<result column="update_id" property="updateId"/>
<result column="update_time" property="updateTime"/>
<result column="del_sign" property="delSign"/>
<result column="remark" property="remark"/>
<result column="user_name" property="userName"/>
<result column="password" property="password"/>
<result column="salt" property="salt"/>
<result column="nicke" property="nicke"/>
<result column="sex" property="sex"/>
<result column="email_addr" property="emailAddr"/>
<result column="address" property="address"/>
<result column="telephone" property="telephone"/>
<result column="dep_id" property="depId"/>
<result column="pos_id" property="posId"/>
</resultMap>
<!-- 公共字段BaseBean 继承的字段) -->
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<!-- 用户专属字段 -->
<sql id="userColumn">
user_name, password, salt, nicke, sex, email_addr, address, telephone, dep_id, pos_id
</sql>
<!-- 1. 分页查询用户(所有传参为空时忽略该条件) -->
<select id="selectUserPage" resultMap="UserResultMap" parameterType="com.rczn.system.domain.User">
SELECT
<include refid="baseColumn"/>,
<include refid="userColumn"/>
FROM sys_user
<where>
<!-- 逻辑删除标识默认查未删除del_sign=0传参不为空时按传参筛选 -->
<if test="delSign == null">
AND del_sign = 0
</if>
<if test="delSign != null">
AND del_sign = #{delSign}
</if>
<!-- 用户名:为空时忽略模糊查询 -->
<if test="userName != null and userName != ''">
AND user_name LIKE CONCAT('%', #{userName}, '%')
</if>
<!-- 部门ID为空时忽略 -->
<if test="depId != null">
AND dep_id = #{depId}
</if>
<!-- 职位ID为空时忽略 -->
<if test="posId != null">
AND pos_id = #{posId}
</if>
<!-- 创建人ID为空时忽略 -->
<if test="createId != null">
AND create_id = #{createId}
</if>
<!-- 性别:为空时忽略 -->
<if test="sex != null">
AND sex = #{sex}
</if>
</where>
ORDER BY id DESC
</select>
<!-- 2. 根据ID查询用户支持查询已删除数据传参为空时返回null -->
<select id="selectById" resultMap="UserResultMap">
SELECT
<include refid="baseColumn"/>,
<include refid="userColumn"/>
FROM sys_user
WHERE id = #{id}
<!-- 可选:添加删除标识筛选(为空时查所有状态,不为空时按状态筛选) -->
<if test="delSign != null">
AND del_sign = #{delSign}
</if>
</select>
<!-- 3. 新增用户(传参为空时用默认值,非空时用传参值) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_user (
<trim suffixOverrides=",">
<if test="userName != null and userName != ''"> user_name,</if>
<if test="password != null and password != ''"> password,</if>
<if test="salt != null and salt != ''"> salt,</if>
<if test="nicke != null and nicke != ''"> nicke,</if>
<if test="sex != null"> sex,</if>
<if test="emailAddr != null and emailAddr != ''"> email_addr,</if>
<if test="address != null and address != ''"> address,</if>
<if test="telephone != null and telephone != ''"> telephone,</if>
<if test="depId != null"> dep_id,</if>
<if test="posId != null"> pos_id,</if>
<!-- 公共字段:为空时用默认值,非空时用传参 -->
<if test="createId != null"> create_id,</if>
<if test="createTime != null"> create_time,</if>
<if test="updateId != null"> update_id,</if>
<if test="updateTime != null"> update_time,</if>
<!-- 方案1delSign 为空时设为 0 -->
<if test="delSign != null"> del_sign,</if>
<if test="remark != null and remark != ''"> remark,</if>
</trim>
) VALUES (
<trim suffixOverrides=",">
<if test="userName != null and userName != ''"> #{userName},</if>
<if test="password != null and password != ''"> #{password},</if>
<if test="salt != null and salt != ''"> #{salt},</if>
<if test="nicke != null and nicke != ''"> #{nicke},</if>
<if test="sex != null"> #{sex},</if>
<if test="emailAddr != null and emailAddr != ''"> #{emailAddr},</if>
<if test="address != null and address != ''"> #{address},</if>
<if test="telephone != null and telephone != ''"> #{telephone},</if>
<if test="depId != null"> #{depId},</if>
<if test="posId != null"> #{posId},</if>
<!-- 公共字段:为空时用默认值,非空时用传参 -->
<if test="createId != null"> #{createId},</if>
<if test="createTime != null"> #{createTime},</if>
<if test="updateId != null"> #{updateId},</if>
<if test="updateTime != null"> #{updateTime},</if>
<!-- 方案1delSign 为空时设为 0 -->
<if test="delSign != null"> #{delSign},</if>
<if test="remark != null and remark != ''"> #{remark},</if>
</trim>
)
</insert>
<!-- 4. 修改用户(仅更新非空字段,空字段不更新) -->
<update id="update">
UPDATE sys_user
<set>
<!-- 用户专属字段:非空才更新 -->
<if test="userName != null and userName != ''">user_name = #{userName},</if>
<if test="password != null and password != ''">password = #{password},</if>
<if test="salt != null and salt != ''">salt = #{salt},</if>
<if test="nicke != null and nicke != ''">nicke = #{nicke},</if>
<if test="sex != null">sex = #{sex},</if>
<if test="emailAddr != null and emailAddr != ''">email_addr = #{emailAddr},</if>
<if test="address != null and address != ''">address = #{address},</if>
<if test="telephone != null and telephone != ''">telephone = #{telephone},</if>
<if test="depId != null">dep_id = #{depId},</if>
<if test="posId != null">pos_id = #{posId},</if>
<!-- 公共字段:非空才更新 -->
<if test="updateId != null">update_id = #{updateId},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
<if test="delSign != null">del_sign = #{delSign},</if>
<!-- 更新时间:强制更新为当前时间(无论是否传参) -->
update_time = NOW()
</set>
WHERE id = #{id}
</update>
<!-- 5. 根据ID删除用户逻辑删除替代物理删除传参为空时不执行 -->
<delete id="deleteById">
UPDATE sys_user
SET
del_sign = 1,
update_time = NOW()
<if test="updateId != null">, update_id = #{updateId}</if>
WHERE id = #{id}
AND del_sign = 0 <!-- 避免重复删除 -->
</delete>
<!-- 6. 查询总条数(与分页查询条件一致,传参为空时忽略) -->
<select id="selectTotal" resultType="java.lang.Long">
SELECT COUNT(*)
FROM sys_user
<where>
<if test="delSign == null">
AND del_sign = 0
</if>
<if test="delSign != null">
AND del_sign = #{delSign}
</if>
<if test="userName != null and userName != ''">
AND user_name LIKE CONCAT('%', #{userName}, '%')
</if>
<if test="depId != null">
AND dep_id = #{depId}
</if>
<if test="posId != null">
AND pos_id = #{posId}
</if>
<if test="createId != null">
AND create_id = #{createId}
</if>
<if test="sex != null">
AND sex = #{sex}
</if>
</where>
</select>
</mapper>

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rczn.system.mapper.UserRoleMapper">
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<sql id="userRoleColumn">
user_id, role_id
</sql>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO sys_user_role (
<include refid="userRoleColumn"/>, create_time, update_time, del_sign
) VALUES (
#{userId}, #{roleId}, NOW(), NOW(), 0
)
</insert>
<delete id="deleteById">
DELETE FROM sys_user_role WHERE id = #{id}
</delete>
<delete id="deleteByUserId">
DELETE FROM sys_user_role WHERE user_id = #{userId}
</delete>
<delete id="deleteByRoleId">
DELETE FROM sys_user_role WHERE role_id = #{roleId}
</delete>
<select id="selectById" resultType="com.rczn.system.domain.UserRole">
SELECT
<include refid="baseColumn"/>, <include refid="userRoleColumn"/>
FROM sys_user_role
WHERE id = #{id}
</select>
<select id="selectByUserId" resultType="com.rczn.system.domain.UserRole">
SELECT
<include refid="baseColumn"/>, <include refid="userRoleColumn"/>
FROM sys_user_role
WHERE user_id = #{userId}
</select>
<select id="selectByRoleId" resultType="com.rczn.system.domain.UserRole">
SELECT
<include refid="baseColumn"/>, <include refid="userRoleColumn"/>
FROM sys_user_role
WHERE role_id = #{roleId}
</select>
<select id="selectPage" resultType="com.rczn.system.domain.UserRole">
SELECT
<include refid="baseColumn"/>, <include refid="userRoleColumn"/>
FROM sys_user_role
WHERE 1=1
<if test="userId != null">AND user_id = #{userId}</if>
<if test="roleId != null">AND role_id = #{roleId}</if>
ORDER BY id DESC
LIMIT #{start}, #{pageSize}
</select>
<select id="selectTotal" resultType="java.lang.Integer">
SELECT COUNT(id)
FROM sys_user_role
WHERE 1=1
<if test="userId != null">AND user_id = #{userId}</if>
<if test="roleId != null">AND role_id = #{roleId}</if>
</select>
</mapper>

View File

@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.rczn</groupId>
<artifactId>Rc-autoplc-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>rczn-autoplc</artifactId>
<name>rczn-autoplc</name>
<description>rczn-autoplcPLC业务模块</description>
<packaging>jar</packaging>
<dependencies>
<!-- 依赖公共模块 -->
<dependency>
<groupId>com.rczn</groupId>
<artifactId>rczn-common</artifactId>
</dependency>
<!-- Spring Boot 基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 如果需要Web功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<!-- 工具类 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.3.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations-jakarta</artifactId>
<version>2.2.21</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.14</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.11.0</version>
<scope>test</scope>
</dependency>
<!-- 这里可以添加PLC通信相关的依赖 -->
<!-- 例如:
<dependency>
<groupId>com.github.s7connector</groupId>
<artifactId>s7connector</artifactId>
<version>2.1</version>
</dependency>
-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip> <!-- 不作为可执行模块 -->
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,187 @@
package com.rczn.rcznautoplc.controller;
import com.rczn.rcznautoplc.domain.DevInfo;
import com.rczn.rcznautoplc.service.DevInfoService;
import com.github.pagehelper.PageInfo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
/**
* 设备信息 ControllerRESTful API
*/
@RestController
@RequestMapping("/devInfo")
@Tag(name = "设备管理", description = "设备增删改查+分页查询+全量查询接口")
public class DevInfoController {
@Autowired
private DevInfoService devInfoService;
/**
* 新增设备
*/
@PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "新增设备", description = "设备名称为必填项,其他字段可选(非空则入库)")
public ResponseEntity<Map<String, Object>> addDevInfo(
@Parameter(name = "设备信息", description = "设备新增请求参数", required = true)
@RequestBody DevInfo devInfo) {
Map<String, Object> result = new HashMap<>();
try {
boolean success = devInfoService.addDevInfo(devInfo);
result.put("success", success);
result.put("message", success ? "设备新增成功" : "设备新增失败");
return ResponseEntity.ok(result);
} catch (IllegalArgumentException e) {
result.put("success", false);
result.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器异常:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 根据ID删除设备逻辑删除
*/
@DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "删除设备", description = "逻辑删除设置delSign=1不物理删除数据")
public ResponseEntity<Map<String, Object>> removeDevInfoById(
@Parameter(name = "id", description = "设备ID", required = true, example = "1")
@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
boolean success = devInfoService.removeDevInfoById(id);
result.put("success", success);
result.put("message", success ? "设备删除成功" : "设备不存在或已删除");
return ResponseEntity.ok(result);
} catch (IllegalArgumentException e) {
result.put("success", false);
result.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器异常:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 更新设备
*/
@PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "修改设备", description = "需传入设备ID其他字段可选非空则更新")
public ResponseEntity<Map<String, Object>> updateDevInfo(
@Parameter(name = "设备信息", description = "设备修改请求参数含ID", required = true)
@RequestBody DevInfo devInfo) {
Map<String, Object> result = new HashMap<>();
try {
boolean success = devInfoService.updateDevInfo(devInfo);
result.put("success", success);
result.put("message", success ? "设备更新成功" : "设备不存在或已删除");
return ResponseEntity.ok(result);
} catch (IllegalArgumentException e) {
result.put("success", false);
result.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器异常:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 根据ID查询设备
*/
@GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "查询单个设备", description = "根据设备ID查询设备完整信息")
public ResponseEntity<Map<String, Object>> getDevInfoById(
@Parameter(name = "id", description = "设备ID", required = true, example = "1")
@PathVariable Long id) {
Map<String, Object> result = new HashMap<>();
try {
DevInfo devInfo = devInfoService.getDevInfoById(id);
if (devInfo != null) {
result.put("success", true);
result.put("data", devInfo);
} else {
result.put("success", false);
result.put("message", "设备不存在或已删除");
}
return ResponseEntity.ok(result);
} catch (IllegalArgumentException e) {
result.put("success", false);
result.put("message", e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器异常:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 分页查询设备
* 示例:/devInfo/listPage?pageNum=1&pageSize=10&devName=设备1&status=0
*/
@GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "分页查询设备", description = "支持设备名称、型号、IP、状态等多条件过滤默认查询未删除设备")
@Parameters({
@Parameter(name = "pageNum", description = "页码(必填)", required = true, example = "1", in = ParameterIn.QUERY),
@Parameter(name = "pageSize", description = "每页条数(必填)", required = true, example = "10", in = ParameterIn.QUERY),
@Parameter(name = "devName", description = "设备名称(可选,模糊查询)", required = false, example = "PLC设备", in = ParameterIn.QUERY),
@Parameter(name = "devModel", description = "设备型号(可选,模糊查询)", required = false, example = "S7-1200", in = ParameterIn.QUERY),
@Parameter(name = "ipAddr", description = "IP地址可选精准查询", required = false, example = "192.168.1.100", in = ParameterIn.QUERY),
@Parameter(name = "status", description = "设备状态可选精准查询0-空闲1-运行4-故障)", required = false, example = "0", in = ParameterIn.QUERY),
@Parameter(name = "protocolType", description = "协议类型(可选,精准查询)", required = false, example = "Modbus", in = ParameterIn.QUERY)
})
public ResponseEntity<Map<String, Object>> getDevInfoPage(
DevInfo devInfo, // 接收查询条件devName、status等
@RequestParam Integer pageNum,
@RequestParam Integer pageSize) {
Map<String, Object> result = new HashMap<>();
try {
PageInfo<DevInfo> pageInfo = devInfoService.getDevInfoPage(devInfo, pageNum, pageSize);
result.put("success", true);
result.put("data", pageInfo);
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器异常:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
/**
* 查询所有设备(不分页)
*/
@GetMapping(value = "/all", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "查询所有设备", description = "返回所有未删除的设备完整信息(不分页,适用于设备数量较少场景)")
public ResponseEntity<Map<String, Object>> getAllDevInfo() {
Map<String, Object> result = new HashMap<>();
try {
List<DevInfo> devInfoList = devInfoService.getAllDevInfo();
result.put("success", true);
result.put("data", devInfoList);
return ResponseEntity.ok(result);
} catch (Exception e) {
result.put("success", false);
result.put("message", "服务器异常:" + e.getMessage());
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(result);
}
}
}

View File

@@ -0,0 +1,94 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class DevInfo extends BaseBean {
private String devName;
private String devModel;
private String ipAddr;
private Integer port;
private String protocolType;
private String company;
private Integer status; // 0-空闲1-运行4-故障
private String desc;
public DevInfo() {
}
public DevInfo(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
public String getDevName() {
return devName;
}
public void setDevName(String devName) {
this.devName = devName;
}
public String getDevModel() {
return devModel;
}
public void setDevModel(String devModel) {
this.devModel = devModel;
}
public String getIpAddr() {
return ipAddr;
}
public void setIpAddr(String ipAddr) {
this.ipAddr = ipAddr;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public String getProtocolType() {
return protocolType;
}
public void setProtocolType(String protocolType) {
this.protocolType = protocolType;
}
public String getCompany() {
return company;
}
public void setCompany(String company) {
this.company = company;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}

View File

@@ -0,0 +1,64 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class DevParam extends BaseBean {
private Integer devId;
private String paramName;
private String paramValue;
private String desc;
private DevInfo devInfo;
public DevParam() {
}
public DevParam(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
public Integer getDevId() {
return devId;
}
public void setDevId(Integer devId) {
this.devId = devId;
}
public String getParamName() {
return paramName;
}
public void setParamName(String paramName) {
this.paramName = paramName;
}
public String getParamValue() {
return paramValue;
}
public void setParamValue(String paramValue) {
this.paramValue = paramValue;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public DevInfo getDevInfo() {
return devInfo;
}
public void setDevInfo(DevInfo devInfo) {
this.devInfo = devInfo;
}
}

View File

@@ -0,0 +1,44 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class FlowInfo extends BaseBean {
private Integer flowIndex;
private String flowName;
private String islandIdList;
public FlowInfo() {
}
public FlowInfo(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
public Integer getFlowIndex() {
return flowIndex;
}
public void setFlowIndex(Integer flowIndex) {
this.flowIndex = flowIndex;
}
public String getFlowName() {
return flowName;
}
public void setFlowName(String flowName) {
this.flowName = flowName;
}
public String getIslandIdList() {
return islandIdList;
}
public void setIslandIdList(String islandIdList) {
this.islandIdList = islandIdList;
}
}

View File

@@ -0,0 +1,94 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import java.time.LocalDateTime;
public class GoodsFlowStatus extends BaseBean {
private Integer goodsId;
private Integer flowId;
private Integer islandId;
private Integer flowSort;
private Integer status; // 0-未执行1-执行10-通过11-失败
private GoodsInfo goodsInfo;
private FlowInfo flowInfo;
private IslandInfo islandInfo;
public GoodsFlowStatus() {
}
public GoodsFlowStatus(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
super(id, createId, createTime, updateId, updateTime, delSign, remark);
}
public Integer getGoodsId() {
return goodsId;
}
public void setGoodsId(Integer goodsId) {
this.goodsId = goodsId;
}
public Integer getFlowId() {
return flowId;
}
public void setFlowId(Integer flowId) {
this.flowId = flowId;
}
public Integer getIslandId() {
return islandId;
}
public void setIslandId(Integer islandId) {
this.islandId = islandId;
}
public Integer getFlowSort() {
return flowSort;
}
public void setFlowSort(Integer flowSort) {
this.flowSort = flowSort;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public GoodsInfo getGoodsInfo() {
return goodsInfo;
}
public void setGoodsInfo(GoodsInfo goodsInfo) {
this.goodsInfo = goodsInfo;
}
public FlowInfo getFlowInfo() {
return flowInfo;
}
public void setFlowInfo(FlowInfo flowInfo) {
this.flowInfo = flowInfo;
}
public IslandInfo getIslandInfo() {
return islandInfo;
}
public void setIslandInfo(IslandInfo islandInfo) {
this.islandInfo = islandInfo;
}
}

View File

@@ -0,0 +1,28 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.time.LocalDateTime;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class GoodsInfo extends BaseBean {
private String goodsName;
private String goodsType;
private LocalDateTime incomeTime;
private String goodFrom;
private Integer goodBatch;
private String desc;
}

View File

@@ -0,0 +1,21 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class IslandInfo extends BaseBean {
private String islandName;
private String islandCode;
private String islandLogo;
private String desc;
}

View File

@@ -0,0 +1,32 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class IslandParam extends BaseBean {
private Integer islandId;
private Integer stepId;
private String paramName;
private String paramType;
private String paramUnit;
private String paramValue;
private String formType;
private IslandInfo islandInfo;
private StepInfo stepInfo;
}

View File

@@ -0,0 +1,22 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class RecordInfo extends BaseBean {
private String recordName;
private Integer recordType; // 1-设备异常2-样品异常3-操作异常
private Boolean recordStatus; // 0-未处理1-已处理
private String recordContent;
}

View File

@@ -0,0 +1,22 @@
package com.rczn.rcznautoplc.domain;
import com.rczn.domain.BaseBean;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class StepInfo extends BaseBean {
private Integer islandId;
private String stepName;
private String stepDesc;
private IslandInfo islandInfo;
}

View File

@@ -0,0 +1,34 @@
package com.rczn.rcznautoplc.mapper;
import com.rczn.rcznautoplc.domain.DevInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 设备信息 Mapper 接口
*/
@Mapper
public interface DevInfoMapper {
// 新增设备
int insert(DevInfo devInfo);
// 逻辑删除设备根据ID
int deleteById(@Param("id") Long id);
// 根据ID更新设备非空字段才更新
int updateById(DevInfo devInfo);
// 根据ID查询设备未删除
DevInfo selectById(@Param("id") Long id);
// 分页查询设备(支持多条件过滤)
List<DevInfo> selectPage(DevInfo devInfo);
// 查询符合条件的设备总数(用于分页)
int selectTotal(DevInfo devInfo);
// 查询所有未删除的设备(用于下拉选择等场景)
List<DevInfo> selectAll();
}

View File

@@ -0,0 +1,29 @@
package com.rczn.rcznautoplc.service;
import com.rczn.rcznautoplc.domain.DevInfo;
import com.github.pagehelper.PageInfo;
import java.util.List;
/**
* 设备信息 Service 接口
*/
public interface DevInfoService {
// 新增设备
boolean addDevInfo(DevInfo devInfo);
// 逻辑删除设备
boolean removeDevInfoById(Long id);
// 更新设备
boolean updateDevInfo(DevInfo devInfo);
// 根据ID查询设备
DevInfo getDevInfoById(Long id);
// 分页查询设备
PageInfo<DevInfo> getDevInfoPage(DevInfo devInfo, Integer pageNum, Integer pageSize);
// 查询所有设备
List<DevInfo> getAllDevInfo();
}

View File

@@ -0,0 +1,81 @@
package com.rczn.rcznautoplc.service.impl;
import com.rczn.rcznautoplc.domain.DevInfo;
import com.rczn.rcznautoplc.mapper.DevInfoMapper;
import com.rczn.rcznautoplc.service.DevInfoService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import java.util.List;
/**
* 设备信息 Service 实现类
*/
@Service
public class DevInfoServiceImpl implements DevInfoService {
@Autowired
private DevInfoMapper devInfoMapper;
@Override
public boolean addDevInfo(DevInfo devInfo) {
// 业务校验:设备名称不能为空
Assert.notNull(devInfo.getDevName(), "设备名称不能为空");
// 填充默认值也可通过AOP统一填充
// devInfo.setCreateId(null);
if (devInfo.getCreateTime() == null) {
devInfo.setCreateTime(java.time.LocalDateTime.now());
}
// 调用Mapper新增
return devInfoMapper.insert(devInfo) > 0;
}
@Override
public boolean removeDevInfoById(Long id) {
// 校验ID非空
Assert.notNull(id, "设备ID不能为空");
// 调用Mapper逻辑删除
return devInfoMapper.deleteById(id) > 0;
}
@Override
public boolean updateDevInfo(DevInfo devInfo) {
// 校验ID和设备名称非空
Assert.notNull(devInfo.getId(), "设备ID不能为空");
Assert.notNull(devInfo.getDevName(), "设备名称不能为空");
// 填充默认值也可通过AOP统一填充
// devInfo.setUpdateId(null);
if (devInfo.getUpdateTime() == null) {
devInfo.setUpdateTime(java.time.LocalDateTime.now());
}
// 调用Mapper更新
return devInfoMapper.updateById(devInfo) > 0;
}
@Override
public DevInfo getDevInfoById(Long id) {
Assert.notNull(id, "设备ID不能为空");
return devInfoMapper.selectById(id);
}
@Override
public PageInfo<DevInfo> getDevInfoPage(DevInfo devInfo, Integer pageNum, Integer pageSize) {
// 分页参数默认值
if (pageNum == null) pageNum = 1;
if (pageSize == null) pageSize = 10;
// PageHelper开启分页
PageHelper.startPage(pageNum, pageSize);
// 查询数据
List<DevInfo> devInfoList = devInfoMapper.selectPage(devInfo);
// 封装分页结果
return new PageInfo<>(devInfoList);
}
@Override
public List<DevInfo> getAllDevInfo() {
return devInfoMapper.selectAll();
}
}

View File

@@ -0,0 +1 @@
##spring.application.name=rczn-autoplc

View File

@@ -0,0 +1,172 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rczn.rcznautoplc.mapper.DevInfoMapper">
<!-- 通用字段BaseBean继承 -->
<sql id="baseColumn">
id, create_id, create_time, update_id, update_time, del_sign, remark
</sql>
<!-- 设备专属字段 -->
<sql id="devColumn">
dev_name, dev_model, ip_addr, port, protocol_type, company, status, `desc`
</sql>
<!-- 结果集映射(下划线转驼峰已开启,可简化) -->
<resultMap id="DevResultMap" type="com.rczn.rcznautoplc.domain.DevInfo">
<id column="id" property="id"/>
<!-- 通用字段 -->
<result column="create_id" property="createId"/>
<result column="create_time" property="createTime"/>
<result column="update_id" property="updateId"/>
<result column="update_time" property="updateTime"/>
<result column="del_sign" property="delSign"/>
<result column="remark" property="remark"/>
<!-- 设备专属字段 -->
<result column="dev_name" property="devName"/>
<result column="dev_model" property="devModel"/>
<result column="ip_addr" property="ipAddr"/>
<result column="port" property="port"/>
<result column="protocol_type" property="protocolType"/>
<result column="company" property="company"/>
<result column="status" property="status"/>
<result column="`desc`" property="desc"/> <!-- desc是MySQL关键字需用反引号包裹 -->
</resultMap>
<!-- 新增设备(空字段忽略) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO tb_dev_info (
<trim prefix="" suffix="" suffixOverrides=",">
<!-- 专属字段 -->
<if test="devName != null and devName != ''">dev_name,</if>
<if test="devModel != null and devModel != ''">dev_model,</if>
<if test="ipAddr != null and ipAddr != ''">ip_addr,</if>
<if test="port != null">port,</if>
<if test="protocolType != null and protocolType != ''">protocol_type,</if>
<if test="company != null and company != ''">company,</if>
<if test="status != null">status,</if>
<if test="desc != null and desc != ''">`desc`,</if>
<!-- 通用字段 -->
<if test="createId != null">create_id,</if>
<if test="createTime != null">create_time,</if>
<if test="updateId != null">update_id,</if>
<if test="updateTime != null">update_time,</if>
<if test="remark != null and remark != ''">remark,</if>
</trim>
) VALUES (
<trim prefix="" suffix="" suffixOverrides=",">
<!-- 专属字段 -->
<if test="devName != null and devName != ''">#{devName},</if>
<if test="devModel != null and devModel != ''">#{devModel},</if>
<if test="ipAddr != null and ipAddr != ''">#{ipAddr},</if>
<if test="port != null">#{port},</if>
<if test="protocolType != null and protocolType != ''">#{protocolType},</if>
<if test="company != null and company != ''">#{company},</if>
<if test="status != null">#{status},</if>
<if test="desc != null and desc != ''">#{desc},</if>
<!-- 通用字段 -->
<if test="createId != null">#{createId},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateId != null">#{updateId},</if>
<if test="updateTime != null">#{updateTime},</if>
<if test="remark != null and remark != ''">#{remark},</if>
</trim>
)
</insert>
<!-- 逻辑删除设备 -->
<update id="deleteById">
UPDATE sys_dev_info
SET del_sign = 1, update_time = NOW()
WHERE id = #{id} AND del_sign = 0
</update>
<!-- 根据ID更新设备非空字段才更新 -->
<update id="updateById">
UPDATE sys_dev_info
<set>
<if test="devName != null and devName != ''">dev_name = #{devName},</if>
<if test="devModel != null and devModel != ''">dev_model = #{devModel},</if>
<if test="ipAddr != null and ipAddr != ''">ip_addr = #{ipAddr},</if>
<if test="port != null">port = #{port},</if>
<if test="protocolType != null and protocolType != ''">protocol_type = #{protocolType},</if>
<if test="company != null and company != ''">company = #{company},</if>
<if test="status != null">status = #{status},</if>
<if test="desc != null and desc != ''">`desc` = #{desc},</if>
<if test="updateId != null">update_id = #{updateId},</if>
<if test="remark != null and remark != ''">remark = #{remark},</if>
update_time = NOW()
</set>
WHERE id = #{id} AND del_sign = 0
</update>
<!-- 根据ID查询设备 -->
<select id="selectById" resultMap="DevResultMap">
SELECT
<include refid="baseColumn"/>,
<include refid="devColumn"/>
FROM sys_dev_info
WHERE id = #{id} AND del_sign = 0
</select>
<!-- 分页查询设备(多条件过滤) -->
<select id="selectPage" resultMap="DevResultMap">
SELECT
<include refid="baseColumn"/>,
<include refid="devColumn"/>
FROM sys_dev_info
WHERE del_sign = 0
<!-- 设备名称模糊查询 -->
<if test="devName != null and devName != ''">
AND dev_name LIKE CONCAT('%', #{devName}, '%')
</if>
<!-- 设备型号模糊查询 -->
<if test="devModel != null and devModel != ''">
AND dev_model LIKE CONCAT('%', #{devModel}, '%')
</if>
<!-- IP地址精准查询 -->
<if test="ipAddr != null and ipAddr != ''">
AND ip_addr = #{ipAddr}
</if>
<!-- 设备状态精准查询 -->
<if test="status != null">
AND status = #{status}
</if>
<!-- 协议类型精准查询 -->
<if test="protocolType != null and protocolType != ''">
AND protocol_type = #{protocolType}
</if>
ORDER BY update_time DESC
</select>
<!-- 查询符合条件的设备总数 -->
<select id="selectTotal" resultType="java.lang.Integer">
SELECT COUNT(id)
FROM sys_dev_info
WHERE del_sign = 0
<if test="devName != null and devName != ''">
AND dev_name LIKE CONCAT('%', #{devName}, '%')
</if>
<if test="devModel != null and devModel != ''">
AND dev_model LIKE CONCAT('%', #{devModel}, '%')
</if>
<if test="ipAddr != null and ipAddr != ''">
AND ip_addr = #{ipAddr}
</if>
<if test="status != null">
AND status = #{status}
</if>
<if test="protocolType != null and protocolType != ''">
AND protocol_type = #{protocolType}
</if>
</select>
<!-- 查询所有未删除的设备 -->
<select id="selectAll" resultMap="DevResultMap">
SELECT
<include refid="baseColumn"/>,
<include refid="devColumn"/>
FROM sys_dev_info
WHERE del_sign = 0
ORDER BY id ASC
</select>
</mapper>

View File

@@ -0,0 +1,3 @@
wrapperVersion=3.3.4
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.11/apache-maven-3.9.11-bin.zip

View File

@@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.rczn</groupId>
<artifactId>Rc-autoplc-backend</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>rczn-common</artifactId>
<name>rczn-common</name>
<description>rczn-common公共模块实体类、工具类、统一响应</description>
<packaging>jar</packaging>
<dependencies>
<!-- 核心依赖 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Jackson JSON 支持 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<!-- 验证API -->
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<!-- Apache Commons 工具 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- 如果需要 Web 相关类(拦截器等) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>provided</scope>
</dependency>
<!-- Servlet API -->
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- Spring Context如果需要 @Component 等注解) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,66 @@
package com.rczn.domain;
import java.time.LocalDateTime;
public class BaseBean {
private Long id;
private Long createId;
private LocalDateTime createTime;
private Long updateId;
private LocalDateTime updateTime;
// 关键修改Boolean → boolean基本类型默认值 false无 null 问题)
private boolean delSign = false;
private String remark;
private LocalDateTime startTime;
private LocalDateTime endTime;
// 无参构造器、全参构造器(同步修改 delSign 类型)
public BaseBean() { }
public BaseBean(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) {
this.id = id;
this.createId = createId;
this.createTime = createTime;
this.updateId = updateId;
this.updateTime = updateTime;
this.delSign = delSign; // 类型同步为 boolean
this.remark = remark;
}
// getter/setter同步修改 delSign 类型)
public boolean isDelSign() { return delSign; } // boolean 类型 getter 是 isXXX而非 getXXX
public void setDelSign(boolean delSign) { this.delSign = delSign; }
// 其他字段 getter/setter 保持不变
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public Long getCreateId() { return createId; }
public void setCreateId(Long createId) { this.createId = createId; }
public LocalDateTime getCreateTime() { return createTime; }
public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }
public Long getUpdateId() { return updateId; }
public void setUpdateId(Long updateId) { this.updateId = updateId; }
public LocalDateTime getUpdateTime() { return updateTime; }
public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }
public String getRemark() { return remark; }
public void setRemark(String remark) { this.remark = remark; }
public LocalDateTime getStartTime() {
return startTime;
}
public void setStartTime(LocalDateTime startTime) {
this.startTime = startTime;
}
public LocalDateTime getEndTime() {
return endTime;
}
public void setEndTime(LocalDateTime endTime) {
this.endTime = endTime;
}
}

View File

@@ -0,0 +1,28 @@
package com.rczn.domain;
import java.util.List;
//分页返回结果对象
public class PageBean <T>{
private Long total;//总条数
private List<T> items;//当前页数据集合
public PageBean() {
}
public Long getTotal() {
return total;
}
public void setTotal(Long total) {
this.total = total;
}
public List<T> getItems() {
return items;
}
public void setItems(List<T> items) {
this.items = items;
}
}

View File

@@ -0,0 +1,55 @@
package com.rczn.domain;
//统一响应结果
public class Result<T> {
private Integer code;//业务状态码 0-成功 1-失败
private String message;//提示信息
private T data;//响应数据
//快速返回操作成功响应结果(带响应数据)
public static <E> Result<E> success(E data) {
return new Result<>(0, "操作成功", data);
}
public Result() {
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
//快速返回操作成功响应结果
public static Result<Void> success() {
return new Result<Void>(0, "操作成功", null);
}
public static Result<Void> error(String message) {
return new Result<Void>(1, message, null);
}
public Result(Integer code, String message, T data) {
this.code = code;
this.message = message;
this.data = data;
}
}

View File

@@ -0,0 +1,37 @@
package com.rczn.interceptors;
import com.rczn.utils.JwtUtil;
import com.rczn.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import java.util.Map;
//@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
try {
String token = request.getHeader("Authorization");
Map<String, Object> claims = JwtUtil.parseToken(token);
//保存用户数据到ThreadLocalUtil
ThreadLocalUtil.set(claims);
//放行
return true;
}catch (Exception e){
//登录失败,抛异常,状态码401
response.setStatus(401);
//不放行
return false;
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
//清除ThreadLocalUtil
ThreadLocalUtil.remove();
}
}

View File

@@ -0,0 +1,30 @@
package com.rczn.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import java.util.Date;
import java.util.Map;
public class JwtUtil {
private static final String KEY = "itheima";
//接收业务数据,生成token并返回
public static String genToken(Map<String, Object> claims) {
return JWT.create()
.withClaim("claims", claims)
.withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12))
.sign(Algorithm.HMAC256(KEY));
}
//接收token,验证token,并返回业务数据
public static Map<String, Object> parseToken(String token) {
return JWT.require(Algorithm.HMAC256(KEY))
.build()
.verify(token)
.getClaim("claims")
.asMap();
}
}

View File

@@ -0,0 +1,73 @@
package com.rczn.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Md5Util {
/**
* 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合
*/
protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
protected static MessageDigest messagedigest = null;
static {
try {
messagedigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsaex) {
System.err.println(Md5Util.class.getName() + "初始化失败MessageDigest不支持MD5Util。");
nsaex.printStackTrace();
}
}
/**
* 生成字符串的md5校验值
*
* @param s
* @return
*/
public static String getMD5String(String s) {
return getMD5String(s.getBytes());
}
/**
* 判断字符串的md5校验码是否与一个已知的md5码相匹配
*
* @param password 要校验的字符串
* @param md5PwdStr 已知的md5校验码
* @return
*/
public static boolean checkPassword(String password, String md5PwdStr) {
String s = getMD5String(password);
return s.equals(md5PwdStr);
}
public static String getMD5String(byte[] bytes) {
messagedigest.update(bytes);
return bufferToHex(messagedigest.digest());
}
private static String bufferToHex(byte bytes[]) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte bytes[], int m, int n) {
StringBuffer stringbuffer = new StringBuffer(2 * n);
int k = m + n;
for (int l = m; l < k; l++) {
appendHexPair(bytes[l], stringbuffer);
}
return stringbuffer.toString();
}
private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>>
// 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同
char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换
stringbuffer.append(c0);
stringbuffer.append(c1);
}
}

View File

@@ -0,0 +1,26 @@
package com.rczn.utils;
/**
* ThreadLocal 工具类
*/
@SuppressWarnings("all")
public class ThreadLocalUtil {
//提供ThreadLocal对象,
private static final ThreadLocal THREAD_LOCAL = new ThreadLocal();
//根据键获取值
public static <T> T get(){
return (T) THREAD_LOCAL.get();
}
//存储键值对
public static void set(Object value){
THREAD_LOCAL.set(value);
}
//清除ThreadLocal 防止内存泄漏
public static void remove(){
THREAD_LOCAL.remove();
}
}

View File

@@ -0,0 +1 @@
##spring.application.name=rczn-common