diff --git a/rc_autoplc_backend/.gitattributes b/rc_autoplc_backend/.gitattributes new file mode 100644 index 0000000..3b41682 --- /dev/null +++ b/rc_autoplc_backend/.gitattributes @@ -0,0 +1,2 @@ +/mvnw text eol=lf +*.cmd text eol=crlf diff --git a/rc_autoplc_backend/.gitignore b/rc_autoplc_backend/.gitignore new file mode 100644 index 0000000..60c0efc --- /dev/null +++ b/rc_autoplc_backend/.gitignore @@ -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* diff --git a/rc_autoplc_backend/.idea/.gitignore b/rc_autoplc_backend/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/rc_autoplc_backend/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/rc_autoplc_backend/.idea/compiler.xml b/rc_autoplc_backend/.idea/compiler.xml new file mode 100644 index 0000000..c858a1e --- /dev/null +++ b/rc_autoplc_backend/.idea/compiler.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/encodings.xml b/rc_autoplc_backend/.idea/encodings.xml new file mode 100644 index 0000000..e768916 --- /dev/null +++ b/rc_autoplc_backend/.idea/encodings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/jarRepositories.xml b/rc_autoplc_backend/.idea/jarRepositories.xml new file mode 100644 index 0000000..082f15f --- /dev/null +++ b/rc_autoplc_backend/.idea/jarRepositories.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/misc.xml b/rc_autoplc_backend/.idea/misc.xml new file mode 100644 index 0000000..67e1e61 --- /dev/null +++ b/rc_autoplc_backend/.idea/misc.xml @@ -0,0 +1,12 @@ + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/uiDesigner.xml b/rc_autoplc_backend/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/rc_autoplc_backend/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/.idea/vcs.xml b/rc_autoplc_backend/.idea/vcs.xml new file mode 100644 index 0000000..6c0b863 --- /dev/null +++ b/rc_autoplc_backend/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/HELP.md b/rc_autoplc_backend/HELP.md new file mode 100644 index 0000000..5731530 --- /dev/null +++ b/rc_autoplc_backend/HELP.md @@ -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 `` and `` 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. + diff --git a/rc_autoplc_backend/LICENSE b/rc_autoplc_backend/LICENSE new file mode 100644 index 0000000..e5cbdd7 --- /dev/null +++ b/rc_autoplc_backend/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU 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 userBusy through +a computer network, with no transfer of a copy, is not conveying. + + An interactive userBusy 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 userBusy 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 userBusy 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 userBusy 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 userBusy, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular userBusy or of the way in which the particular userBusy +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. + + + Copyright (C) + + 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 . + +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 +. diff --git a/rc_autoplc_backend/README.en.md b/rc_autoplc_backend/README.en.md new file mode 100644 index 0000000..e34317d --- /dev/null +++ b/rc_autoplc_backend/README.en.md @@ -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/) diff --git a/rc_autoplc_backend/README.md b/rc_autoplc_backend/README.md new file mode 100644 index 0000000..252cc97 --- /dev/null +++ b/rc_autoplc_backend/README.md @@ -0,0 +1,42 @@ +# 融创智能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/) + +#### 增加日志生成: +1. 2026-4-3:用户登录日志信息 +2. 2026-4-3:SOP用户操作日志信息 +3. 2026-4-3:基础数据(功能岛、SOP序列)用户操作(增-删-改)日志 \ No newline at end of file diff --git a/rc_autoplc_backend/mvnw b/rc_autoplc_backend/mvnw new file mode 100644 index 0000000..bd8896b --- /dev/null +++ b/rc_autoplc_backend/mvnw @@ -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-,maven-mvnd--}/ +[ -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 "$@" diff --git a/rc_autoplc_backend/mvnw.cmd b/rc_autoplc_backend/mvnw.cmd new file mode 100644 index 0000000..1acdbea --- /dev/null +++ b/rc_autoplc_backend/mvnw.cmd @@ -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 - userBusy 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-,maven-mvnd--}/ +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" diff --git a/rc_autoplc_backend/pom.xml b/rc_autoplc_backend/pom.xml new file mode 100644 index 0000000..ff6d1b4 --- /dev/null +++ b/rc_autoplc_backend/pom.xml @@ -0,0 +1,133 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.2.12 + + + + com.rczn + Rc-autoplc-backend + 0.0.1-SNAPSHOT + Rc-autoplc-backend + Rc-autoplc-backend 聚合父模块 + pom + + + rczn-common + rczn-autoplc + rczn-admin + + + + 17 + + 3.0.3 + 2.1.0 + 4.4.0 + 4.5.0 + 6.0.0 + 1.18.30 + + + + + + + + com.rczn + rczn-common + ${project.version} + + + com.rczn + rczn-autoplc + ${project.version} + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + ${mybatis.version} + + + com.github.pagehelper + pagehelper-spring-boot-starter + ${pagehelper.version} + + + com.auth0 + java-jwt + ${jwt.version} + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + ${knife4j.version} + + + + jakarta.servlet + jakarta.servlet-api + ${jakarta.servlet-api.version} + provided + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + 2.15.4 + + + org.apache.commons + commons-lang3 + 3.14.0 + + + jakarta.validation + jakarta.validation-api + 3.0.2 + + + + com.github.s7connector + s7connector + 2.1 + + + + org.apache.commons + commons-pool2 + 2.12.0 + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${java.version} + ${java.version} + UTF-8 + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/.mvn/wrapper/maven-wrapper.properties b/rc_autoplc_backend/rczn-admin/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..c0bcafe --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/rc_autoplc_backend/rczn-admin/pom.xml b/rc_autoplc_backend/rczn-admin/pom.xml new file mode 100644 index 0000000..cef4882 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/pom.xml @@ -0,0 +1,123 @@ + + + 4.0.0 + + com.rczn + Rc-autoplc-backend + 0.0.1-SNAPSHOT + ../pom.xml + + + rczn-admin + rczn-admin + rczn-admin(后台管理模块) + jar + + + + + com.rczn + rczn-common + + + + + com.rczn + rczn-autoplc + + + + + org.springframework.boot + spring-boot-starter-web + + + + + jakarta.servlet + jakarta.servlet-api + provided + + + + + org.springframework.boot + spring-boot-starter-validation + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-devtools + runtime + true + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + + + com.mysql + mysql-connector-j + runtime + + + + + + + + + + + org.projectlombok + lombok + true + + + + + com.auth0 + java-jwt + + + + com.github.pagehelper + pagehelper-spring-boot-starter + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + + + + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + com.rczn.RcznAdminApplication + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/RcznAdminApplication.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/RcznAdminApplication.java new file mode 100644 index 0000000..088abe0 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/RcznAdminApplication.java @@ -0,0 +1,17 @@ +package com.rczn; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.scheduling.annotation.EnableScheduling; + +@SpringBootApplication +@ComponentScan(value = "com.rczn.*") +@EnableScheduling +public class RcznAdminApplication { + + public static void main(String[] args) { + SpringApplication.run(RcznAdminApplication.class, args); + } + +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/CorsConfig.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/CorsConfig.java new file mode 100644 index 0000000..89628bc --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/CorsConfig.java @@ -0,0 +1,45 @@ +package com.rczn.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +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小时 + } + + @Bean + public CorsFilter corsFilter() { + CorsConfiguration config = new CorsConfiguration(); + // 1. 允许前端源(不要用*,和withCredentials=true配合需指定具体源,或用allowedOriginPatterns) + config.addAllowedOriginPattern("*"); + // 2. 允许携带凭证(和前端withCredentials=true对应) + config.setAllowCredentials(true); + // 3. 允许所有请求方法(包含OPTIONS) + config.addAllowedMethod("*"); + // 4. 允许所有请求头(包含Authorization) + config.addAllowedHeader("*"); + // 5. 预检请求缓存时间(减少OPTIONS请求次数) + config.setMaxAge(3600L); + + // 配置生效路径 + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + + return new CorsFilter(source); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java new file mode 100644 index 0000000..052ebcc --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/Knife4jConfig.java @@ -0,0 +1,38 @@ +package com.rczn.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class Knife4jConfig { + + @Bean + public OpenAPI customOpenAPI() { + // 1. 声明JWT认证规则 + String securitySchemeName = "Authorization"; + return new OpenAPI() + // 2. 文档基础信息(可选) + .info(new Info() + .title("XX自动化编程系统API") + .version("1.0.0") + .description("集成JWT认证的Knife4j接口文档")) + // 3. 配置全局认证规则(所有接口默认需要Token) + .addSecurityItem(new SecurityRequirement().addList(securitySchemeName)) + // 4. 定义Token的传递方式(请求头+Bearer格式) + .components(new Components() + .addSecuritySchemes(securitySchemeName, + new SecurityScheme() + .name(securitySchemeName) + .type(SecurityScheme.Type.HTTP) // HTTP认证 + .scheme("bearer") // Bearer格式 + .bearerFormat("JWT") // Token类型为JWT + .in(SecurityScheme.In.HEADER) // 放在请求头 + ) + ); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java new file mode 100644 index 0000000..076da1a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/config/WebConfig.java @@ -0,0 +1,55 @@ +package com.rczn.config; + +import com.rczn.interceptors.LoginInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +// 必须启用@Configuration,让Spring扫描到 +@Configuration +public class WebConfig implements WebMvcConfigurer { + + // 必须注入拦截器(取消注释) + @Autowired + LoginInterceptor loginInterceptor; + + // 注册拦截器 + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(loginInterceptor) + // 拦截所有请求 + .addPathPatterns("/**") + // 放行Swagger/Knife4j所有相关路径(关键补充/doc.html) + .excludePathPatterns( + // Knife4j自定义UI路径(核心!) + "/doc.html", + // Swagger UI页面相关 + "/swagger-ui/**", + "/webjars/**", + // SpringDoc接口文档数据相关 + "/v3/api-docs/**", + "/v3/api-docs.yaml", + // 旧版Swagger兼容 + "/swagger-resources/**", + "/swagger-ui.html" + ) + // 放行登录/注册接口 + .excludePathPatterns("/user/login", "/user/register"); + } + + // 静态资源映射(适配Knife4j+SpringDoc) + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + // Knife4j静态资源(核心补充) + registry.addResourceHandler("/doc.html") + .addResourceLocations("classpath:/META-INF/resources/"); + // Swagger UI静态资源 + registry.addResourceHandler("/swagger-ui/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/springdoc-openapi-ui/"); + // Webjars通用资源 + registry.addResourceHandler("/webjars/**") + .addResourceLocations("classpath:/META-INF/resources/webjars/"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/DepartmentController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/DepartmentController.java new file mode 100644 index 0000000..c5d16ed --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/DepartmentController.java @@ -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> getDeptPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String deptName, + @RequestParam(required = false) String deptCode, + @RequestParam(required = false) Integer parentId) { + PageBean 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 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 simpleDeptTree = departmentService.getSimpleDeptTree(); + return Result.success(simpleDeptTree); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/HellowAdminController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/HellowAdminController.java new file mode 100644 index 0000000..d0cdffd --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/HellowAdminController.java @@ -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!!!"; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/PositionController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/PositionController.java new file mode 100644 index 0000000..96596a1 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/PositionController.java @@ -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> getPosiPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String posiName, + @RequestParam(required = false) String posiCode) { + PageBean 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 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()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RoleController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RoleController.java new file mode 100644 index 0000000..21873ca --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RoleController.java @@ -0,0 +1,145 @@ +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.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 角色管理 CRUD API(MyBatis+PageHelper 实现) + */ +@RestController +@RequestMapping("/role") // RESTful 规范:复数形式 +@Tag(name = "角色管理", description = "角色增删改查接口(支持分页+多条件查询+编码唯一性校验)") +public class RoleController { + + @Autowired + 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> getRolePage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String roleName, + @RequestParam(required = false) String roleCode) { + + PageBean pageBean = roleService.selectRolePage(pageNum, pageSize, roleName, roleCode); + return Result.success(pageBean); + } + + /** + * 1. 分页查询角色(多条件模糊查询) + */ + @GetMapping("/list") + @Operation(summary = "查询角色列表", description = "支持角色名、角色编码模糊查询") + @Parameters({ + @Parameter(name = "roleName", description = "角色名(模糊查询,可选)", required = false, example = "管理员", in = ParameterIn.QUERY), + @Parameter(name = "roleCode", description = "角色编码(模糊查询,可选)", required = false, example = "ADMIN", in = ParameterIn.QUERY) + }) + public Result getRoleList( + @RequestParam(required = false) String roleName, + @RequestParam(required = false) String roleCode) { + + List list = roleService.selectRoleList( roleName, roleCode); + return Result.success(list); + } + + /** + * 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("删除失败(角色不存在)"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java new file mode 100644 index 0000000..3930764 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/RolePermissionController.java @@ -0,0 +1,65 @@ +package com.rczn.controller; + +import com.rczn.domain.Result; +import com.rczn.system.domain.RolePermission; +import com.rczn.system.domain.query.RolePermissionQuery; +import com.rczn.system.service.RolePermissionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.*; + +import java.util.List; + +@RestController +@RequestMapping("/rolePermission") +@Tag(name = "角色权限管理", description = "角色权限关联接口") +public class RolePermissionController { + + @Autowired + RolePermissionService rolePermissionService; + + @GetMapping("/listByRoleId/{roleId}") + @Operation(summary = "根据角色ID查询权限ID列表") + public Result getListByRoleId( + @Parameter(name = "roleId", required = true) @PathVariable Integer roleId) { + List list = rolePermissionService.selectListByRoleId(roleId); + return Result.success(list); + } + + @PostMapping("/add") + @Operation(summary = "给角色添加权限") + public Result add(@RequestBody RolePermissionQuery rolePermission) { + if (rolePermission.getRoleId() == null || rolePermission.getPermissionId() == null) { + return Result.error("角色ID和权限ID不能为空"); + } + try { + RolePermission rolePermissionEntity = new RolePermission(); + rolePermissionEntity.setRoleId(rolePermission.getRoleId()); + rolePermissionEntity.setPermissionId(rolePermission.getPermissionId()); + rolePermissionService.insert(rolePermissionEntity); + return Result.success("添加成功"); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + @DeleteMapping("/del") + @Operation(summary = "删除角色权限关联") + public Result delete( + @RequestParam Integer roleId, + @RequestParam(required = false) Integer permissionId) { + boolean success = rolePermissionService.delete(roleId, permissionId); + return success ? Result.success("删除成功") : Result.error("删除失败"); + } + + @DeleteMapping("/clearByRoleId/{roleId}") + @Operation(summary = "清空某个角色的所有权限") + public Result clearByRoleId( + @Parameter(name = "roleId", required = true) @PathVariable Integer roleId) { + rolePermissionService.deleteByRoleId(roleId); + return Result.success("清空成功"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java new file mode 100644 index 0000000..da28134 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicDataController.java @@ -0,0 +1,109 @@ +package com.rczn.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.Result; +import com.rczn.system.domain.SysDicData; +import com.rczn.system.service.SysDicDataService; +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("/sysDicData") +@Tag(name = "字典数据管理", description = "字典数据增删改查+分页查询+按类型查询接口") +public class SysDicDataController { + + @Autowired + private SysDicDataService sysDicDataService; + + @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 = "dicId", description = "字典类型ID(可选)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "dicLabel", description = "数据标签(可选,模糊查询)", required = false, example = "运行", in = ParameterIn.QUERY), + @Parameter(name = "dicValue", description = "数据值(可选,模糊查询)", required = false, example = "1", in = ParameterIn.QUERY) + }) + public Result getDicDataPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer dicId, + @RequestParam(required = false) String dicLabel, + @RequestParam(required = false) String dicValue) { + PageInfo pageBean = sysDicDataService.selectPage(pageNum, pageSize, dicId, dicLabel, dicValue); + return Result.success(pageBean); + } + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询字典数据", description = "支持字典类型ID、标签、值查询") + @Parameters({ + @Parameter(name = "dicId", description = "字典类型ID(可选)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "dicLabel", description = "数据标签(可选,模糊查询)", required = false, example = "运行", in = ParameterIn.QUERY), + @Parameter(name = "dicValue", description = "数据值(可选,模糊查询)", required = false, example = "1", in = ParameterIn.QUERY) + }) + public Result getList( + @RequestParam(required = false) Integer dicId, + @RequestParam(required = false) String dicLabel, + @RequestParam(required = false) String dicValue) { + List list = sysDicDataService.selectList( dicId, dicLabel, dicValue); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个字典数据", description = "根据字典数据ID查询详情") + public Result getDicDataById(@PathVariable Long id) { + SysDicData sysDicData = sysDicDataService.selectById(id); + return sysDicData != null ? Result.success(sysDicData) : Result.error("字典数据不存在"); + } + + @GetMapping(value = "/listByDicId/{dicId}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "按字典类型ID查询数据列表", description = "查询指定字典类型下的所有有效数据") + public Result getDicDataByDicId(@PathVariable Integer dicId) { + try { + List list = sysDicDataService.selectByDicId(dicId); + return Result.success(list); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增字典数据", description = "字典类型ID、数据标签为必填项") + public Result addDicData(@RequestBody SysDicData sysDicData) { + try { + Long dicDataId = sysDicDataService.insert(sysDicData); + return Result.success(dicDataId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改字典数据", description = "需传入字典数据ID,其他字段可选(非空则更新)") + public Result updateDicData(@RequestBody SysDicData sysDicData) { + try { + Boolean success = sysDicDataService.update(sysDicData); + 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 deleteDicData(@PathVariable Long id) { + try { + Boolean success = sysDicDataService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(字典数据不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java new file mode 100644 index 0000000..36a814b --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysDicTypeController.java @@ -0,0 +1,95 @@ +package com.rczn.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.Result; +import com.rczn.system.domain.SysDicType; +import com.rczn.system.service.SysDicTypeService; +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("/sysDicType") +@Tag(name = "字典类型管理", description = "字典类型增删改查+分页查询接口") +public class SysDicTypeController { + + @Autowired + private SysDicTypeService sysDicTypeService; + + @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 = "dicName", description = "字典名称(可选,模糊查询)", required = false, example = "设备状态", in = ParameterIn.QUERY), + @Parameter(name = "dicCode", description = "字典编码(可选,模糊查询)", required = false, example = "DEV_STATUS", in = ParameterIn.QUERY) + }) + public Result getDicTypePage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String dicName, + @RequestParam(required = false) String dicCode) { + PageInfo pageBean = sysDicTypeService.selectPage(pageNum, pageSize, dicName, dicCode); + return Result.success(pageBean); + } + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询字典类型列表", description = "支持字典名称、编码模糊查询") + @Parameters({ + @Parameter(name = "dicName", description = "字典名称(可选,模糊查询)", required = false, example = "设备状态", in = ParameterIn.QUERY), + @Parameter(name = "dicCode", description = "字典编码(可选,模糊查询)", required = false, example = "DEV_STATUS", in = ParameterIn.QUERY) + }) + public Result getList( + @RequestParam(required = false) String dicName, + @RequestParam(required = false) String dicCode) { + List list = sysDicTypeService.selectList( dicName, dicCode); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个字典类型", description = "根据字典类型ID查询详情") + public Result getDicTypeById(@PathVariable Long id) { + SysDicType sysDicType = sysDicTypeService.selectById(id); + return sysDicType != null ? Result.success(sysDicType) : Result.error("字典类型不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增字典类型", description = "字典名称为必填项") + public Result addDicType(@RequestBody SysDicType sysDicType) { + try { + Long dicTypeId = sysDicTypeService.insert(sysDicType); + return Result.success(dicTypeId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改字典类型", description = "需传入字典类型ID,其他字段可选(非空则更新)") + public Result updateDicType(@RequestBody SysDicType sysDicType) { + try { + Boolean success = sysDicTypeService.update(sysDicType); + 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 deleteDicType(@PathVariable Long id) { + try { + Boolean success = sysDicTypeService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(字典类型不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java new file mode 100644 index 0000000..4f7f2bb --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/SysPermissionController.java @@ -0,0 +1,128 @@ +package com.rczn.controller; + +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; +import com.rczn.system.service.SysPermissionService; +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.*; + +import java.util.List; + +/** + * 权限管理 API(MyBatis 树形结构实现) + */ +@RestController +@RequestMapping("/permission") +@Tag(name = "权限管理", description = "权限增删改查接口(树形结构)") +public class SysPermissionController { + + @Autowired + private SysPermissionService sysPermissionService; + + /** + * 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 = "parentId", description = "父级ID(可选)", required = false, example = "0", in = ParameterIn.QUERY), + @Parameter(name = "permissionName", description = "权限名称(模糊查询,可选)", required = false, example = "用户添加", in = ParameterIn.QUERY) + }) + public Result> getRolePage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer parentId, + @RequestParam(required = false) String permissionName) { + + PageBean pageBean = sysPermissionService.selectRolePage(pageNum, pageSize, parentId,permissionName); + return Result.success(pageBean); + } + + /** + * 1. 查询权限树形结构列表 + */ + @GetMapping("/list") + @Operation(summary = "查询权限树形列表", description = "返回权限树形结构(parentId为0或null为顶级)") + public Result> getPermissionList() { + List treeList = sysPermissionService.getPermissionList(); + return Result.success(treeList); + } + + /** + * 1. 查询权限树形结构列表 + */ +// @GetMapping("/listByParentId/{parentId}") +// @Operation(summary = "查询权限树形列表", description = "返回权限树形结构(parentId为0或null为顶级)") +// public Result> getPermissionListByParentId(@PathVariable Integer parentId) { +// List treeList = sysPermissionService.getPermissionListByParentId(parentId); +// return Result.success(treeList); +// } + + /** + * 2. 根据ID查询单个权限 + */ + @GetMapping("/getById/{id}") + @Operation(summary = "查询单个权限", description = "根据权限ID查询详情") + public Result getPermissionById( + @Parameter(name = "id", description = "权限ID", required = true, example = "1", in = ParameterIn.PATH) + @PathVariable Integer id) { + + Permission permission = sysPermissionService.getPermissionById(id); + if (permission == null) { + return Result.error("权限ID:" + id + " 不存在"); + } + return Result.success(permission); + } + + /** + * 3. 新增权限 + */ + @PostMapping("/add") + @Operation(summary = "新增权限", description = "提交权限信息创建新权限") + public Result addPermission( + @Parameter(name = "permission", description = "权限信息", required = true) + @RequestBody Permission permission) { + + boolean success = sysPermissionService.addPermission(permission); + return success ? Result.success("新增权限成功") : Result.error("新增失败"); + } + + /** + * 4. 修改权限 + */ + @PutMapping("/update") + @Operation(summary = "修改权限", description = "传入权限ID和需要修改的字段") + public Result updatePermission( + @Parameter(name = "permission", description = "权限信息(必须包含ID)", required = true) + @RequestBody Permission permission) { + + try { + boolean success = sysPermissionService.updatePermission(permission); + return success ? Result.success("修改权限成功") : Result.error("修改失败(权限不存在)"); + } catch (Exception e) { + return Result.error(e.getMessage()); + } + } + + /** + * 5. 根据ID删除权限(逻辑删除) + */ + @DeleteMapping("/del/{id}") + @Operation(summary = "删除权限", description = "根据权限ID逻辑删除") + public Result deletePermission( + @Parameter(name = "id", description = "权限ID", required = true, example = "1", in = ParameterIn.PATH) + @PathVariable Integer id) { + + boolean success = sysPermissionService.deletePermission(id); + return success ? Result.success("删除权限成功") : Result.error("删除失败(权限不存在)"); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserController.java new file mode 100644 index 0000000..126a663 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserController.java @@ -0,0 +1,239 @@ +package com.rczn.controller; + +import com.fasterxml.jackson.databind.annotation.JsonAppend; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.ManageLog; +import com.rczn.rcznautoplc.domain.RecordInfo; +import com.rczn.rcznautoplc.service.ManageLogService; +import com.rczn.rcznautoplc.service.RecordInfoService; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.User; +import com.rczn.system.service.UserService; +import com.rczn.utils.JwtUtil; +import com.rczn.utils.Md5Util; +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 jakarta.validation.constraints.Pattern; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 用户管理 CRUD API(MyBatis+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> getUserPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String userName) { + + // 调用 Service 分页查询 + PageBean pageBean = userService.selectUserPage(pageNum, pageSize, userName); + return Result.success(pageBean); + } + + @GetMapping("/list") + @Operation(summary = "查询用户列表", description = "用户名模糊查询,查询全部") + @Parameters({ + @Parameter(name = "userName", description = "用户名(模糊查询,可选)", required = false, example = "张三", in = ParameterIn.QUERY) + }) + public Result> getUserList( + @RequestParam(required = false) String userName) { + + // 调用 Service 查询列表 + List userList = userService.selectUserList(userName); + return Result.success(userList); + } + + /** + * 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("删除失败(用户不存在)"); + } + + + @PostMapping("/register") + @Operation(summary = "注册", description = "用户名必须是2-16位的字母、数字、下划线或减号") + public Result register(@Pattern(regexp = "^[a-zA-Z0-9_-]{2,16}$", message = "用户名必须是2-16位的字母、数字、下划线或减号") + @Parameter( + name = "username", + description = "用户名" + ) + @RequestParam + String username, + @Parameter( + name = "password", + description = "密码..." + ) + @RequestParam + String password) { + //查询数据库是否有该用户 + User user = userService.findeUserByUsername(username); + //注册 + if (user == null) { + //如果用户不存在,则注册 + int result = userService.register(username, password); + return Result.success("用户注册成功"); + } else { + //用户存在,返回错误信息 + return Result.error("该用户名已存在!"); + } + } + + @GetMapping("/getUserByUsername") + public Result getUserByUsername(String username) { + User user = userService.findeUserByUsername(username); + if (user == null) { + return Result.error("该用户不存在!"); + } else { + return Result.success(user); + } + } + + @Autowired + ManageLogService manageLogService; + + @PostMapping("/login") + @Operation(summary = "用户登录接口",description = "根据用户名和密码登录,返回JWT Token") + public Result login( + @Parameter( + name = "username", + description = "登录用户名(2-16位的字母、数字、下划线或减号)", + required = true, // 标记为必填参数 + example = "string" + ) + @RequestParam + String username, + @Parameter( + name = "password", + description = "登录密码", + required = true + ) + @RequestParam + String password) { + + //TODO 登录逻辑 + //查询数据库是否有该用户 + User user = userService.findeUserByUsername(username); + //登录 + if (user == null) { + //如果用户不存在,返回错误信息 + return Result.error("该用户不存在!"); + } else { + //校验密码: + String encryptPassword = user.getPassword(); + if (encryptPassword.equals(password)) { + //登录成功,增加登录日志: + LocalDateTime loginTime = LocalDateTime.now(); + ManageLog info = new ManageLog(); + info.setCreateId(user.getId()); + info.setLogName("登录日志"); + info.setLogType("登录日志");//1:登录日志、2:SOP操作日志、3:基础数据操作日志 + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("用户名:").append(user.getUserName()).append(",登录操作时间:").append(loginTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setLogContent(stringBuilder.toString()); + info.setCreateTime(loginTime); + manageLogService.insert(info); + +// if (Md5Util.checkPassword(password, encryptPassword)) { + //生产token + Map claims = new HashMap<>(); + claims.put("id", user.getId()); + claims.put("username", user.getUserName()); + //获取权限列表: + List permissions = userService.findUserPermissions(user.getId()); + List permissionList = permissions.stream().map(Permission::getPermissionCode).collect(Collectors.toList()); + claims.put("permissions", permissionList); + String jwtToken = JwtUtil.genToken(claims); + //密码正确,返回成功信息 + return Result.success(jwtToken); + } else { + //密码错误,返回错误信息 + return Result.error("密码错误!"); + } + } + } + +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserRoleController.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserRoleController.java new file mode 100644 index 0000000..dab6e94 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/controller/UserRoleController.java @@ -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> getUserRolePage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer userId, + @RequestParam(required = false) Integer roleId) { + PageBean 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> getByUserId(@PathVariable Integer userId) { + List userRoles = userRoleService.selectByUserId(userId); + return Result.success(userRoles); + } + + @GetMapping(value = "/role/{roleId}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "根据角色ID查询关联用户", description = "查询指定角色的所有关联用户") + public Result> getByRoleId(@PathVariable Integer roleId) { + List 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()); + } + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Department.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Department.java new file mode 100644 index 0000000..342af1d --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Department.java @@ -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 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 getChildren() { + return children; + } + + public void setChildren(List children) { + this.children = children; + } + + @Override + public String toString() { + return "Department{" + + "deptName='" + deptName + '\'' + + ", deptCode='" + deptCode + '\'' + + ", parentId=" + parentId + + ", leaderId=" + leaderId + + ", leader=" + leader + + ", children=" + children + + '}'; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Permission.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Permission.java new file mode 100644 index 0000000..dfc2554 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Permission.java @@ -0,0 +1,31 @@ +package com.rczn.system.domain; + +import com.rczn.domain.BaseBean; + +import java.util.List; + +public class Permission extends BaseBean{ + + private Integer parentId; + private String permissionName; + private String permissionCode; + + // 树形结构子节点 ✅ + private List children; + + // getter & setter + public Integer getParentId() { return parentId; } + public void setParentId(Integer parentId) { this.parentId = parentId; } + public String getPermissionName() { return permissionName; } + public void setPermissionName(String permissionName) { this.permissionName = permissionName; } + public String getPermissionCode() { return permissionCode; } + public void setPermissionCode(String permissionCode) { this.permissionCode = permissionCode; } + + // children + public List getChildren() { + return children; + } + public void setChildren(List children) { + this.children = children; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Position.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Position.java new file mode 100644 index 0000000..50fd71d --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Position.java @@ -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; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Role.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Role.java new file mode 100644 index 0000000..ced36aa --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/Role.java @@ -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; } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/RolePermission.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/RolePermission.java new file mode 100644 index 0000000..7e55f16 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/RolePermission.java @@ -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; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java new file mode 100644 index 0000000..a64751c --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicData.java @@ -0,0 +1,52 @@ +package com.rczn.system.domain; + +import com.rczn.domain.BaseBean; +import java.time.LocalDateTime; + +/** + * 字典数据实体类 + * 对应表:sys_dic_data + */ +public class SysDicData extends BaseBean { + + // 字典类型id(外键) + private Integer dicId; + + // 数据标签 + private String dicLabel; + + // 数据字典值 + private String dicValue; + + public SysDicData() { + } + + public SysDicData(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + // getter/setter + public Integer getDicId() { + return dicId; + } + + public void setDicId(Integer dicId) { + this.dicId = dicId; + } + + public String getDicLabel() { + return dicLabel; + } + + public void setDicLabel(String dicLabel) { + this.dicLabel = dicLabel; + } + + public String getDicValue() { + return dicValue; + } + + public void setDicValue(String dicValue) { + this.dicValue = dicValue; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java new file mode 100644 index 0000000..827bdce --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/SysDicType.java @@ -0,0 +1,41 @@ +package com.rczn.system.domain; + +import com.rczn.domain.BaseBean; +import java.time.LocalDateTime; + +/** + * 字典类型实体类 + * 对应表:sys_dic_type + */ +public class SysDicType extends BaseBean { + + // 字典名称(必填) + private String dicName; + + // 字典编码 + private String dicCode; + + public SysDicType() { + } + + public SysDicType(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + // getter/setter + public String getDicName() { + return dicName; + } + + public void setDicName(String dicName) { + this.dicName = dicName; + } + + public String getDicCode() { + return dicCode; + } + + public void setDicCode(String dicCode) { + this.dicCode = dicCode; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/User.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/User.java new file mode 100644 index 0000000..2af76cf --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/User.java @@ -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; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/UserRole.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/UserRole.java new file mode 100644 index 0000000..4163de1 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/UserRole.java @@ -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 + + '}'; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/UserTest.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/UserTest.java new file mode 100644 index 0000000..55a85f3 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/UserTest.java @@ -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; +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java new file mode 100644 index 0000000..f17fa3a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/domain/query/RolePermissionQuery.java @@ -0,0 +1,34 @@ +package com.rczn.system.domain.query; + +public class RolePermissionQuery { + + //角色id + private Integer roleId; + + //权限id + private Integer permissionId; + + public RolePermissionQuery(Integer roleId, Integer permissionId) { + this.roleId = roleId; + this.permissionId = permissionId; + } + + public RolePermissionQuery() { + } + + 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; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/DepartmentMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/DepartmentMapper.java new file mode 100644 index 0000000..23cbd68 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/DepartmentMapper.java @@ -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 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 selectAllDept(); + + // 新增:按父部门ID查询子部门(用于递归查询) + List selectChildrenByParentId(@Param("parentId") Integer parentId); + + // 新增:查询顶级部门(parent_id IS NULL) + List selectTopDept(); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/PositionMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/PositionMapper.java new file mode 100644 index 0000000..43b33e2 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/PositionMapper.java @@ -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 selectPage( + @Param("posiName") String posiName, + @Param("posiCode") String posiCode + ); + int selectTotal( + @Param("posiName") String posiName, + @Param("posiCode") String posiCode + ); + List selectList( + @Param("posiName") String posiName, + @Param("posiCode") String posiCode + ); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RoleMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RoleMapper.java new file mode 100644 index 0000000..eac1efd --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RoleMapper.java @@ -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 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); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java new file mode 100644 index 0000000..93f27f9 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/RolePermissionMapper.java @@ -0,0 +1,18 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.RolePermission; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import java.util.List; + +@Mapper +public interface RolePermissionMapper { + + List selectListByRoleId(@Param("roleId") Integer roleId); + + int insert(RolePermission rolePermission); + + int delete(@Param("roleId") Integer roleId, @Param("permissionId") Integer permissionId); + + int deleteByRoleId(@Param("roleId") Integer roleId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java new file mode 100644 index 0000000..52cea18 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicDataMapper.java @@ -0,0 +1,39 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.SysDicData; +import org.apache.ibatis.annotations.Mapper; +import java.util.List; + +@Mapper +public interface SysDicDataMapper { + + /** + * 新增字典数据 + */ + int insert(SysDicData sysDicData); + + /** + * 修改字典数据 + */ + int update(SysDicData sysDicData); + + /** + * 逻辑删除字典数据 + */ + int deleteById(Long id); + + /** + * 根据ID查询字典数据 + */ + SysDicData selectById(Long id); + + /** + * 分页查询字典数据(参数可选) + */ + List selectPage(SysDicData sysDicData); + + /** + * 根据字典类型ID查询字典数据列表 + */ + List selectByDicId(Integer dicId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java new file mode 100644 index 0000000..ec25b7a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysDicTypeMapper.java @@ -0,0 +1,34 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.SysDicType; +import org.apache.ibatis.annotations.Mapper; +import java.util.List; + +@Mapper +public interface SysDicTypeMapper { + + /** + * 新增字典类型 + */ + int insert(SysDicType sysDicType); + + /** + * 修改字典类型 + */ + int update(SysDicType sysDicType); + + /** + * 逻辑删除字典类型 + */ + int deleteById(Long id); + + /** + * 根据ID查询字典类型 + */ + SysDicType selectById(Long id); + + /** + * 分页查询字典类型(参数可选) + */ + List selectPage(SysDicType sysDicType); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java new file mode 100644 index 0000000..4b67f65 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/SysPermissionMapper.java @@ -0,0 +1,52 @@ +package com.rczn.system.mapper; + + +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface SysPermissionMapper { + + /** + * 分页查询角色(支持角色名/角色编码模糊查询) + */ + List selectPermissionPage( + @Param("parentId") Integer parentId, + @Param("permissionName") String permissionName); + + /** + * 查询总条数(支持模糊查询条件) + */ + Long selectTotal( + @Param("parentId") Integer parentId, + @Param("permissionName") String permissionName); + + /** + * 查询所有权限(未删除) + */ + List selectPermissionList(); + + /** + * 根据ID查询 + */ + Permission selectPermissionById(Integer id); + + /** + * 新增 + */ + int insertPermission(Permission permission); + + /** + * 修改 + */ + int updatePermission(Permission permission); + + /** + * 逻辑删除 + */ + int deletePermissionById(Integer id); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/UserMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/UserMapper.java new file mode 100644 index 0000000..bd19442 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/UserMapper.java @@ -0,0 +1,43 @@ +package com.rczn.system.mapper; + +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.User; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.util.List; + +@Mapper +public interface UserMapper { + // 分页查询(参数支持空值,为空时忽略该条件) + List 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 + ); + + @Select("SELECT * FROM sys_user WHERE user_name = #{userName}") + User selectByUsername(String userName); + + //根据用户id,查询出对应的权限列表 + List findUserPermissions(Long userId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/UserRoleMapper.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/UserRoleMapper.java new file mode 100644 index 0000000..5d3ae10 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/mapper/UserRoleMapper.java @@ -0,0 +1,42 @@ +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 selectByUserId(Integer userId); + + // 根据角色ID查询关联的用户列表 + List selectByRoleId(Integer roleId); + + // 分页查询所有关联 + List selectPage( + @Param("userId") Integer userId, + @Param("roleId") Integer roleId + ); + + // 查询分页总数 + int selectTotal( + @Param("userId") Integer userId, + @Param("roleId") Integer roleId + ); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/DepartmentService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/DepartmentService.java new file mode 100644 index 0000000..a39f648 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/DepartmentService.java @@ -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 selectPage( + Integer pageNum, + Integer pageSize, + String deptName, + String deptCode, + Integer parentId + ); + + // 新增:获取完整部门树(递归组装) + List getDeptTree(); + + // 新增:获取简化版部门树(仅包含ID、名称、子部门,用于下拉选择) + List getSimpleDeptTree(); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/PositionService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/PositionService.java new file mode 100644 index 0000000..5c8af40 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/PositionService.java @@ -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 selectPage(Integer pageNum, Integer pageSize, String posiName, String posiCode); + List selectList(String posiName, String posiCode); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java new file mode 100644 index 0000000..6c175d6 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RolePermissionService.java @@ -0,0 +1,15 @@ +package com.rczn.system.service; + +import com.rczn.system.domain.RolePermission; +import java.util.List; + +public interface RolePermissionService { + + List selectListByRoleId(Integer roleId); + + void insert(RolePermission rolePermission); + + boolean delete(Integer roleId, Integer permissionId); + + void deleteByRoleId(Integer roleId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RoleService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RoleService.java new file mode 100644 index 0000000..6e6fa29 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/RoleService.java @@ -0,0 +1,60 @@ +package com.rczn.system.service; + +import com.rczn.domain.PageBean; +import com.rczn.system.domain.Role; + +import java.util.List; + +/** + * Role 业务逻辑层接口 + */ +public interface RoleService { + + /** + * 分页查询角色(支持多条件模糊查询) + * @param pageNum 页码(从1开始) + * @param pageSize 每页条数 + * @param roleName 角色名(可选) + * @param roleCode 角色编码(可选) + * @return 分页结果 + */ + PageBean 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); + + /** + * 根据角色名或角色编码模糊查询角色列表 + * @param roleName 角色名(可选) + * @param roleCode 角色编码(可选) + * @return 角色列表 + */ + List selectRoleList(String roleName, String roleCode); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java new file mode 100644 index 0000000..a590771 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicDataService.java @@ -0,0 +1,44 @@ +package com.rczn.system.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicData; + +import java.util.List; + +public interface SysDicDataService { + + /** + * 分页查询字典数据 + */ + PageInfo selectPage(Integer pageNum, Integer pageSize, Integer dicId, String dicLabel, String dicValue); + + /** + * 查询字典数据列表 + */ + List selectList(Integer dicId, String dicLabel, String dicValue); + + /** + * 根据ID查询字典数据 + */ + SysDicData selectById(Long id); + + /** + * 根据字典类型ID查询字典数据列表 + */ + List selectByDicId(Integer dicId); + + /** + * 新增字典数据 + */ + Long insert(SysDicData sysDicData); + + /** + * 修改字典数据 + */ + Boolean update(SysDicData sysDicData); + + /** + * 逻辑删除字典数据 + */ + Boolean deleteById(Long id); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java new file mode 100644 index 0000000..c04b731 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysDicTypeService.java @@ -0,0 +1,40 @@ +package com.rczn.system.service; + + +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicType; + +import java.util.List; + +public interface SysDicTypeService { + + /** + * 分页查询字典类型 + */ + PageInfo selectPage(Integer pageNum, Integer pageSize, String dicName, String dicCode); + + /** + * 查询字典类型列表 + */ + List selectList( String dicName, String dicCode); + + /** + * 根据ID查询字典类型 + */ + SysDicType selectById(Long id); + + /** + * 新增字典类型 + */ + Long insert(SysDicType sysDicType); + + /** + * 修改字典类型 + */ + Boolean update(SysDicType sysDicType); + + /** + * 逻辑删除字典类型 + */ + Boolean deleteById(Long id); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java new file mode 100644 index 0000000..8e5ee0a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/SysPermissionService.java @@ -0,0 +1,26 @@ +package com.rczn.system.service; + +import com.rczn.domain.PageBean; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; + +import java.util.List; + +public interface SysPermissionService { + List getPermissionList(); + //根据父ID查询权限列表: + List getPermissionListByParentId(Integer parentId); + Permission getPermissionById(Integer id); + boolean addPermission(Permission permission); + boolean updatePermission(Permission permission); + boolean deletePermission(Integer id); + + /** + * 1. 分页查询角色(多条件模糊查询) + * @param pageNum + * @param pageSize + * @param permissionName + * @return + */ + PageBean selectRolePage(Integer pageNum, Integer pageSize,Integer parentId, String permissionName); +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/UserRoleService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/UserRoleService.java new file mode 100644 index 0000000..f3897ad --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/UserRoleService.java @@ -0,0 +1,23 @@ +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 selectByUserId(Integer userId); + +/** + * Selects user roles by the given role ID + * + * @param roleId The ID of the role to search for + * @return List of UserRole objects associated with the given role ID + */ + List selectByRoleId(Integer roleId); + PageBean selectPage(Integer pageNum, Integer pageSize, Integer userId, Integer roleId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/UserService.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/UserService.java new file mode 100644 index 0000000..8a73a04 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/UserService.java @@ -0,0 +1,78 @@ +package com.rczn.system.service; + +import com.rczn.domain.PageBean; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.User; + +import java.util.List; + +/** + * User 业务逻辑层接口 + */ +public interface UserService { + + /** + * 1. 分页查询用户(支持用户名模糊查询) + * @param pageNum 页码(从1开始) + * @param pageSize 每页条数 + * @param userName 用户名(模糊查询,可选) + * @return 分页结果(PageBean) + */ + PageBean selectUserPage(Integer pageNum, Integer pageSize, String userName); + + /** + * 1. 查询用户列表(支持用户名模糊查询) + * @param userName 用户名(模糊查询,可选) + * @return 结果(listUser) + */ + List selectUserList(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); + + /** + * 6. 根据用户名查询用户 + * @param username 用户名 + * @return 用户实体 + */ + User findeUserByUsername(String username); + + /** + * 7. 注册用户 + * @param username 用户名 + * @param password 密码 + */ + int register(String username, String password); + + /** + * 根据用户id查询出关联的用户权限对象列表, + * 表直接的关系是: + * 用户表(user)--用户权限表(user_role)--权限表(role)-- 权限资源表(role_resource)--资源表(resource) + */ + List findUserPermissions(Long userId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/DepartmentServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/DepartmentServiceImpl.java new file mode 100644 index 0000000..e1bd1fa --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/DepartmentServiceImpl.java @@ -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 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 items = departmentMapper.selectPage(deptName, deptCode, parentId); + Page page = (Page) items; + + PageBean pageBean = new PageBean<>(); + pageBean.setTotal(page.getTotal()); + pageBean.setItems(page.getResult()); + + // 封装PageBean返回 + return pageBean; + } + + /** + * 核心:获取完整部门树(包含所有字段和层级关系) + */ + @Override + public List getDeptTree() { + // 1. 查询所有未删除的部门(一次性查询,减少数据库交互) + List allDept = departmentMapper.selectAllDept(); + + // 2. 递归组装树形结构(从顶级部门开始) + return buildDeptTree(allDept, null); + } + + /** + * 核心:获取简化版部门树(仅ID、名称、子部门,用于下拉选择框等场景) + */ + @Override + public List getSimpleDeptTree() { + List allDept = departmentMapper.selectAllDept(); + List deptTree = buildDeptTree(allDept, null); + + // 简化部门树字段(仅保留必要字段,减少返回数据量) + return simplifyDeptTree(deptTree); + } + + /** + * 递归组装部门树 + * @param allDept 所有部门列表 + * @param parentId 父部门ID(null 表示查询顶级部门) + * @return 组装后的子部门列表 + */ + private List buildDeptTree(List allDept, Integer parentId) { + // 筛选当前父部门的所有子部门 + List 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 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 simplifyDeptTree(List deptTree) { + List 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 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); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/PositionServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/PositionServiceImpl.java new file mode 100644 index 0000000..73e70ce --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/PositionServiceImpl.java @@ -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 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 items = positionMapper.selectPage(posiName, posiCode); + Page page = (Page) items; + + PageBean pageBean = new PageBean<>(); + pageBean.setTotal(page.getTotal()); + pageBean.setItems(page.getResult()); + + // 封装PageBean返回 + return pageBean; + } + + /** + * 条件查询职位列表 + * @param posiName 职位名称 + * @param posiCode 职位编码 + * @return 职位列表 + */ + @Override + public List selectList(String posiName, String posiCode) { + return positionMapper.selectList(posiName, posiCode); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java new file mode 100644 index 0000000..5a1fb45 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RolePermissionServiceImpl.java @@ -0,0 +1,42 @@ +package com.rczn.system.service.impl; + +import com.rczn.system.domain.RolePermission; +import com.rczn.system.mapper.RolePermissionMapper; +import com.rczn.system.service.RolePermissionService; +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; + +@Service +public class RolePermissionServiceImpl implements RolePermissionService { + + @Autowired + RolePermissionMapper rolePermissionMapper; + + @Override + public List selectListByRoleId(Integer roleId) { + return rolePermissionMapper.selectListByRoleId(roleId); + } + + @Override + @Transactional + public void insert(RolePermission rolePermission) { + rolePermission.setCreateTime(LocalDateTime.now()); + rolePermissionMapper.insert(rolePermission); + } + + @Override + @Transactional + public boolean delete(Integer roleId, Integer permissionId) { + return rolePermissionMapper.delete(roleId, permissionId) > 0; + } + + @Override + @Transactional + public void deleteByRoleId(Integer roleId) { + rolePermissionMapper.deleteByRoleId(roleId); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RoleServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..c3f47c9 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/RoleServiceImpl.java @@ -0,0 +1,110 @@ +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 selectRolePage(Integer pageNum, Integer pageSize, String roleName, String roleCode) { + // 1. PageHelper 设置分页参数 + PageHelper.startPage(pageNum, pageSize); + // 2. 执行查询 + List roleList = roleMapper.selectRolePage(roleName, roleCode); + // 3. 查询总条数 + Long total = roleMapper.selectTotal(roleName, roleCode); + // 4. 封装分页结果 + return new PageBean() {{ + 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; + } + + /** + * 根据角色名或角色编码模糊查询角色列表 + * + * @param roleName 角色名(可选) + * @param roleCode 角色编码(可选) + * @return 角色列表 + */ + @Override + public List selectRoleList(String roleName, String roleCode) { + return roleMapper.selectRolePage(roleName, roleCode); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java new file mode 100644 index 0000000..ff69849 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicDataServiceImpl.java @@ -0,0 +1,97 @@ +package com.rczn.system.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicData; +import com.rczn.system.mapper.SysDicDataMapper; +import com.rczn.system.service.SysDicDataService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.util.List; + +@Service +public class SysDicDataServiceImpl implements SysDicDataService { + + @Autowired + private SysDicDataMapper sysDicDataMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, Integer dicId, String dicLabel, String dicValue) { + PageHelper.startPage(pageNum, pageSize); + SysDicData query = new SysDicData(); + query.setDicId(dicId); + query.setDicLabel(dicLabel); + query.setDicValue(dicValue); + return new PageInfo<>(sysDicDataMapper.selectPage(query)); + } + + /** + * 查询字典数据列表 + * + * @param dicId + * @param dicLabel + * @param dicValue + */ + @Override + public List selectList(Integer dicId, String dicLabel, String dicValue) { + SysDicData query = new SysDicData(); + query.setDicId(dicId); + query.setDicLabel(dicLabel); + query.setDicValue(dicValue); + return sysDicDataMapper.selectPage(query); + } + + @Override + public SysDicData selectById(Long id) { + return sysDicDataMapper.selectById(id); + } + + @Override + public List selectByDicId(Integer dicId) { + if (dicId == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + return sysDicDataMapper.selectByDicId(dicId); + } + + @Override + public Long insert(SysDicData sysDicData) { + // 校验必填项 + if (sysDicData.getDicId() == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + if (sysDicData.getDicLabel() == null || sysDicData.getDicLabel().trim().isEmpty()) { + throw new IllegalArgumentException("数据标签不能为空"); + } + int count = sysDicDataMapper.insert(sysDicData); + return count > 0 ? sysDicData.getId() : null; + } + + @Override + public Boolean update(SysDicData sysDicData) { + if (sysDicData.getId() == null) { + throw new IllegalArgumentException("字典数据ID不能为空"); + } + // 校验是否存在 + SysDicData exist = sysDicDataMapper.selectById(sysDicData.getId()); + if (exist == null) { + return false; + } + int count = sysDicDataMapper.update(sysDicData); + return count > 0; + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) { + throw new IllegalArgumentException("字典数据ID不能为空"); + } + // 校验是否存在 + SysDicData exist = sysDicDataMapper.selectById(id); + if (exist == null) { + return false; + } + int count = sysDicDataMapper.deleteById(id); + return count > 0; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java new file mode 100644 index 0000000..f9b6625 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysDicTypeServiceImpl.java @@ -0,0 +1,84 @@ +package com.rczn.system.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.system.domain.SysDicType; +import com.rczn.system.mapper.SysDicTypeMapper; +import com.rczn.system.service.SysDicTypeService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class SysDicTypeServiceImpl implements SysDicTypeService { + + @Autowired + private SysDicTypeMapper sysDicTypeMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, String dicName, String dicCode) { + PageHelper.startPage(pageNum, pageSize); + SysDicType query = new SysDicType(); + query.setDicName(dicName); + query.setDicCode(dicCode); + return new PageInfo<>(sysDicTypeMapper.selectPage(query)); + } + + /** + * 查询字典类型列表 + * + * @param dicName + * @param dicCode + */ + @Override + public List selectList(String dicName, String dicCode) { + SysDicType query = new SysDicType(); + query.setDicName(dicName); + query.setDicCode(dicCode); + return sysDicTypeMapper.selectPage(query); + } + + @Override + public SysDicType selectById(Long id) { + return sysDicTypeMapper.selectById(id); + } + + @Override + public Long insert(SysDicType sysDicType) { + // 校验必填项 + if (sysDicType.getDicName() == null || sysDicType.getDicName().trim().isEmpty()) { + throw new IllegalArgumentException("字典名称不能为空"); + } + int count = sysDicTypeMapper.insert(sysDicType); + return count > 0 ? sysDicType.getId() : null; + } + + @Override + public Boolean update(SysDicType sysDicType) { + if (sysDicType.getId() == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + // 校验是否存在 + SysDicType exist = sysDicTypeMapper.selectById(sysDicType.getId()); + if (exist == null) { + return false; + } + int count = sysDicTypeMapper.update(sysDicType); + return count > 0; + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) { + throw new IllegalArgumentException("字典类型ID不能为空"); + } + // 校验是否存在 + SysDicType exist = sysDicTypeMapper.selectById(id); + if (exist == null) { + return false; + } + int count = sysDicTypeMapper.deleteById(id); + return count > 0; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java new file mode 100644 index 0000000..22fa1a3 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/SysPermissionServiceImpl.java @@ -0,0 +1,140 @@ +package com.rczn.system.service.impl; + +import com.github.pagehelper.PageHelper; +import com.rczn.domain.PageBean; +import com.rczn.system.domain.Permission; +import com.rczn.system.domain.Role; +import com.rczn.system.mapper.SysPermissionMapper; +import com.rczn.system.service.SysPermissionService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@Service +public class SysPermissionServiceImpl implements SysPermissionService { + + @Autowired + private SysPermissionMapper sysPermissionMapper; + + @Override + public Permission getPermissionById(Integer id) { + return sysPermissionMapper.selectPermissionById(id); + } + + @Override + public boolean addPermission(Permission permission) { + return sysPermissionMapper.insertPermission(permission) > 0; + } + + @Override + public boolean updatePermission(Permission permission) { + return sysPermissionMapper.updatePermission(permission) > 0; + } + + @Override + public boolean deletePermission(Integer id) { + return sysPermissionMapper.deletePermissionById(id) > 0; + } + + /** + * 1. 分页查询角色(多条件模糊查询) + * + * @param pageNum + * @param pageSize + * @param permissionName + * @return + */ + @Override + public PageBean selectRolePage(Integer pageNum, Integer pageSize,Integer parentId, String permissionName) { + // 1. PageHelper 设置分页参数 + PageHelper.startPage(pageNum, pageSize); + //加一层过滤: + if(parentId == 0){ + parentId = null; + } + // 2. 执行查询 + List permissionList = sysPermissionMapper.selectPermissionPage(parentId,permissionName); + // 3. 查询总条数 + Long total = sysPermissionMapper.selectTotal(parentId,permissionName); + // 4. 封装分页结果 + return new PageBean() {{ + setTotal(total); + setItems(permissionList); + }}; + } + + @Override + public List getPermissionList() { + // 1. 查询所有平级权限 + List allPermissions = sysPermissionMapper.selectPermissionList(); + + // 2. 找到顶层节点(parentId = null 或 0) + List topNodes = new ArrayList<>(); + for (Permission p : allPermissions) { + if (p.getParentId() == null || p.getParentId() == 0) { + topNodes.add(p); + } + } + + // 3. 循环给每个顶层节点设置子节点(递归) + for (Permission node : topNodes) { + node.setChildren(findChildren(node, allPermissions)); + } + + return topNodes; + } + + /*** + * 根据父ID查询权限列表 + * @param parentId + * @return + */ + @Override + public List getPermissionListByParentId(Integer parentId) { + // 1. 查询所有平级权限 + List allPermissions = sysPermissionMapper.selectPermissionList(); + + // 2. 找到顶层节点(parentId = null 或 0) + List topNodes = new ArrayList<>(); + for (Permission p : allPermissions) { + if(parentId == null || parentId == 0){ + if (p.getParentId() == null || p.getParentId() == 0) { + topNodes.add(p); + } + }else { + if (p.getParentId() == parentId) { + topNodes.add(p); + } + } + + } + + // 3. 循环给每个顶层节点设置子节点(递归) + for (Permission node : topNodes) { + node.setChildren(findChildren(node, allPermissions)); + } + + return topNodes; + } + + /** + * 递归查找子节点(最稳妥、最清晰、不会漏) + */ + private List findChildren(Permission parent, List allList) { + List children = new ArrayList<>(); + + for (Permission p : allList) { + // 子节点的 parentId == 父节点 id + if (parent.getId().equals(p.getParentId()==null?0:p.getParentId().longValue())) { + children.add(p); + // 递归给子节点设置孙子节点 + p.setChildren(findChildren(p, allList)); + } + } + + return children; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/UserRoleServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/UserRoleServiceImpl.java new file mode 100644 index 0000000..a56a513 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/UserRoleServiceImpl.java @@ -0,0 +1,88 @@ +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.Permission; +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 selectByUserId(Integer userId) { + Assert.notNull(userId, "用户ID不能为空"); + return userRoleMapper.selectByUserId(userId); + } + + @Override + public List selectByRoleId(Integer roleId) { + Assert.notNull(roleId, "角色ID不能为空"); + return userRoleMapper.selectByRoleId(roleId); + } + + @Override + public PageBean 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之间"); + + PageHelper.startPage(pageNum,pageSize); + List items = userRoleMapper.selectPage(userId, roleId); + Page page = (Page) items; + + PageBean pageBean = new PageBean<>(); + pageBean.setTotal(page.getTotal()); + pageBean.setItems(page.getResult()); + + // 封装PageBean返回 + return pageBean; + } +} diff --git a/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/UserServiceImpl.java b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..701d98a --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/java/com/rczn/system/service/impl/UserServiceImpl.java @@ -0,0 +1,131 @@ +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.Permission; +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 { + + // 注入 Mapper(Lombok @RequiredArgsConstructor 自动生成构造器) + + @Autowired + UserMapper userMapper; + + @Override + public PageBean 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 userList = userMapper.selectUserPage(user); + Page userPage = (Page) userList; + + // 3. 查询总条数(支持模糊查询条件) + PageBean pageBean = new PageBean<>(); + pageBean.setTotal(userPage.getTotal()); + pageBean.setItems(userPage); + + // 4. 封装分页结果(使用你的自定义 PageBean) + return pageBean; + } + + /** + * 1. 查询用户列表(支持用户名模糊查询) + * + * @param userName 用户名(模糊查询,可选) + * @return 结果(listUser) + */ + @Override + public List selectUserList(String userName) { + // 2. 执行查询(MyBatis 会自动添加 LIMIT 分页) + User user = new User(); + user.setUserName(userName); + List userList = userMapper.selectUserPage(user); + + return userList; + } + + @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; + } + + /** + * 6. 根据用户名查询用户 + * + * @param username 用户名 + * @return 用户实体 + */ + @Override + public User findeUserByUsername(String username) { + return userMapper.selectByUsername(username); + } + + /** + * 7. 注册用户 + * + * @param username 用户名 + * @param password 密码 + */ + @Override + public int register(String username, String password) { + User user = new User(); + user.setUserName(username); + user.setPassword(password); + return userMapper.insert(user); + } + + /** + * 根据用户id查询出关联的用户权限对象列表, + * 表直接的关系是: + * 用户表(user)--用户权限表(user_role)--权限表(role)-- 权限资源表(role_resource)--资源表(resource) + * + * @param userId + */ + @Override + public List findUserPermissions(Long userId) { + return userMapper.findUserPermissions(userId); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/application.yml b/rc_autoplc_backend/rczn-admin/src/main/resources/application.yml new file mode 100644 index 0000000..720422e --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/application.yml @@ -0,0 +1,163 @@ +# 服务器配置 +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&allowMultiQueries=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 # 下划线转驼峰 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 关键:SQL 打印到控制台 + log-prefix: "[MyBatis] " # 可选:日志前缀,便于区分 SQL 日志 + default-statement-timeout: 30 # 可选:SQL 执行超时时间(秒) + mapper-locations: classpath:mapper/**/*.xml # 补充:指定Mapper.xml文件路径(必加) + type-aliases-package: com.rczn.**.domain # 补充:实体类别名包(可选) + + + # 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 # 连接校验 SQL(MySQL 可用此简单查询) + +# 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: 测试环境 + + +# SpringDoc + Knife4j 核心配置 +springdoc: + packages-to-scan: com.rczn # 扫描Controller所在包 + api-docs: + enabled: true + path: /v3/api-docs + swagger-ui: + tags-sorter: alpha + operations-sorter: alpha + paths-to-exclude: /error, /actuator/** + +# Knife4j增强配置(可选,开启中文UI) +knife4j: + enable: true + setting: + language: zh_cn # 中文界面 + enable-swagger-models: true # 显示模型 + enable-document-manage: false # 关闭文档管理(开发环境) + +# OpenAPI文档信息 +#openapi: +# info: +# title: XX自动化编程系统API文档 +# description: SpringBoot 3.x + Knife4j + 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: 测试环境 +# Spring Boot 日志核心配置 +logging: + # 1. 全局日志级别(可细化到包/类) + level: + root: INFO # 根日志级别(默认) + com.rczn.rcznautoplc: DEBUG # 自定义包级别(调试业务代码) + org.springframework: INFO # Spring 框架日志级别(减少冗余) + com.zaxxer.hikari: ERROR # 数据库连接池日志级别(仅输出错误) + mybatis: DEBUG # MyBatis SQL 日志级别(输出执行的 SQL) + + # 2. 日志输出配置(控制台 + 文件) + pattern: +# console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" # 控制台格式 + file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n" # 文件格式 + + # 3. 文件输出配置 + file: + name: ./logs/rczn-autoplc.log # 日志文件路径(相对路径/绝对路径) + max-size: 10MB # 单个日志文件大小上限(超过则分割) + max-history: 30 # 日志文件保留天数 + total-size-cap: 1GB # 日志文件总大小上限 + clean-history-on-start: false # 启动时是否清理历史日志 + + # 4. 日志分割(按大小/时间,Logback 原生支持) + logback: + rollingpolicy: + file-name-pattern: ./logs/rczn-autoplc-%d{yyyy-MM-dd}.%i.log # 分割后的文件名(%i 是序号,处理同天多文件) + max-file-size: 100MB # 单个文件大小(覆盖上面的 max-size) + max-history: 30 # 保留天数 + total-size-cap: 1GB # 总大小 \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/DepartmentMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/DepartmentMapper.xml new file mode 100644 index 0000000..e83d1cb --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/DepartmentMapper.xml @@ -0,0 +1,179 @@ + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + dept_name, dept_code, parent_id, leader_id + + + + + INSERT INTO sys_department ( + + + + create_id, + create_time, + remark, + + dept_name, + dept_code, + parent_id, + leader_id, + + ) VALUES ( + + + + #{createId}, + #{createTime}, + #{remark}, + + #{deptName}, + #{deptCode}, + #{parentId}, + #{leaderId}, + + ) + + + + + UPDATE sys_department + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE sys_department + + dept_name = #{deptName}, + dept_code = #{deptCode}, + parent_id = #{parentId}, + leader_id = #{leaderId}, + update_id = #{updateId}, + remark = #{remark}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/PositionMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/PositionMapper.xml new file mode 100644 index 0000000..e3a475f --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/PositionMapper.xml @@ -0,0 +1,82 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + posi_name, posi_code + + + + INSERT INTO sys_position ( + , create_time, update_time, del_sign + ) VALUES ( + #{posiName}, #{posiCode}, NOW(), NOW(), 0 + ) + + + + UPDATE sys_position + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE sys_position + + posi_name = #{posiName}, + posi_code = #{posiCode}, + update_id = #{updateId}, + remark = #{remark}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RoleMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RoleMapper.xml new file mode 100644 index 0000000..e1e7648 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RoleMapper.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + + + + + + + INSERT INTO sys_role ( + + role_name, + role_code, + create_id, + create_time, + update_id, + update_time, + del_sign, + remark, + + ) + VALUES ( + + #{roleName}, + #{roleCode}, + #{createId}, + #{createTime}, + #{updateId}, + #{updateTime}, + #{delSign}, + #{remark}, + + ) + + + + + UPDATE sys_role + + role_name = #{roleName}, + role_code = #{roleCode}, + update_id = #{updateId}, + update_time = now(), + remark = #{remark}, + + WHERE id = #{id} + + + + + DELETE FROM sys_role WHERE id = #{id} + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml new file mode 100644 index 0000000..ba72578 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/RolePermissionMapper.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + id, role_id, permission_id + + + + + + INSERT INTO sys_role_permission (role_id, permission_id) + VALUES (#{roleId}, #{permissionId}) + + + + DELETE FROM sys_role_permission + + + role_id = #{roleId} + + + AND permission_id = #{permissionId} + + + + + + DELETE FROM sys_role_permission + WHERE role_id = #{roleId} + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml new file mode 100644 index 0000000..2ab76dc --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicDataMapper.xml @@ -0,0 +1,74 @@ + + + + + id, create_by, create_time, update_by, update_time, del_sign, remark + + + + dic_id, dic_label, dic_value + + + + + INSERT INTO sys_dic_data ( + , + create_by, create_time, update_by, update_time, del_sign + ) VALUES ( + #{dicId}, #{dicLabel}, #{dicValue}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + + UPDATE sys_dic_data + + dic_id = #{dicId}, + dic_label = #{dicLabel}, + dic_value = #{dicValue}, + update_by = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE sys_dic_data + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml new file mode 100644 index 0000000..29f9613 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysDicTypeMapper.xml @@ -0,0 +1,62 @@ + + + + + id, create_by, create_time, update_by, update_time, del_sign, remark + + + + dic_name, dic_code + + + + + INSERT INTO sys_dic_type ( + , + create_by, create_time, update_by, update_time, del_sign + ) VALUES ( + #{dicName}, #{dicCode}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + + UPDATE sys_dic_type + + dic_name = #{dicName}, + dic_code = #{dicCode}, + update_by = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE sys_dic_type + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml new file mode 100644 index 0000000..dfba1f9 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/SysPermissionMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO sys_permission + (parent_id, permission_name, permission_code, create_id, remark, del_sign) + VALUES + (#{parentId}, #{permissionName}, #{permissionCode}, #{createId}, #{remark}, 0) + + + + + UPDATE sys_permission + SET + parent_id = #{parentId}, + permission_name = #{permissionName}, + permission_code = #{permissionCode}, + update_id = #{updateId}, + remark = #{remark} + WHERE id = #{id} + + + + + UPDATE sys_permission SET del_sign = 1 WHERE id = #{id} + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/UserMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..27907f9 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + user_name, password, salt, nicke, sex, email_addr, address, telephone, dep_id, pos_id + + + + + + + + + + + INSERT INTO sys_user ( + + user_name, + password, + salt, + nicke, + sex, + email_addr, + address, + telephone, + dep_id, + pos_id, + + create_id, + create_time, + update_id, + update_time, + + del_sign, + remark, + + ) VALUES ( + + #{userName}, + #{password}, + #{salt}, + #{nicke}, + #{sex}, + #{emailAddr}, + #{address}, + #{telephone}, + #{depId}, + #{posId}, + + #{createId}, + #{createTime}, + #{updateId}, + #{updateTime}, + + #{delSign}, + #{remark}, + + ) + + + + + UPDATE sys_user + + + user_name = #{userName}, + password = #{password}, + salt = #{salt}, + nicke = #{nicke}, + sex = #{sex}, + email_addr = #{emailAddr}, + address = #{address}, + telephone = #{telephone}, + dep_id = #{depId}, + pos_id = #{posId}, + + update_id = #{updateId}, + remark = #{remark}, + del_sign = #{delSign}, + + update_time = NOW() + + WHERE id = #{id} + + + + + UPDATE sys_user + SET + del_sign = 1, + update_time = NOW() + , update_id = #{updateId} + WHERE id = #{id} + AND del_sign = 0 + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/UserRoleMapper.xml b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/UserRoleMapper.xml new file mode 100644 index 0000000..b53de42 --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/main/resources/mapper/UserRoleMapper.xml @@ -0,0 +1,69 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + user_id, role_id + + + + INSERT INTO sys_user_role ( + ,remark, create_time, del_sign + ) VALUES ( + #{userId}, #{roleId}, #{remark},NOW(), 0 + ) + + + + DELETE FROM sys_user_role WHERE id = #{id} + + + + DELETE FROM sys_user_role WHERE user_id = #{userId} + + + + DELETE FROM sys_user_role WHERE role_id = #{roleId} + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java b/rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java new file mode 100644 index 0000000..aadd54c --- /dev/null +++ b/rc_autoplc_backend/rczn-admin/src/test/java/com/rczn/RcznAdminApplicationTests.java @@ -0,0 +1,13 @@ +package com.rczn; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RcznAdminApplicationTests { + +// @Test + void contextLoads() { + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/.mvn/wrapper/maven-wrapper.properties b/rc_autoplc_backend/rczn-autoplc/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..c0bcafe --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/rc_autoplc_backend/rczn-autoplc/pom.xml b/rc_autoplc_backend/rczn-autoplc/pom.xml new file mode 100644 index 0000000..8eb981a --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/pom.xml @@ -0,0 +1,100 @@ + + + 4.0.0 + + com.rczn + Rc-autoplc-backend + 0.0.1-SNAPSHOT + ../pom.xml + + + rczn-autoplc + rczn-autoplc + rczn-autoplc(PLC业务模块) + jar + + + + + com.rczn + rczn-common + + + + + org.springframework.boot + spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-web + true + + + + + org.projectlombok + lombok + ${lombok.version} + true + + + com.github.pagehelper + pagehelper + 5.3.3 + compile + + + + org.mybatis + mybatis + 3.5.14 + compile + + + org.springframework.boot + spring-boot-test + test + + + org.testng + testng + 7.11.0 + test + + + io.swagger.core.v3 + swagger-models-jakarta + 2.2.19 + compile + + + org.junit.jupiter + junit-jupiter-api + + + + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java new file mode 100644 index 0000000..cea8853 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/IsLandActionParamToPlc.java @@ -0,0 +1,28 @@ +package com.rczn.rcznautoplc.cache; + +import java.util.HashMap; +import java.util.Map; + +/** + * 1-功能岛>plc地址 + * 2-动作单元>plc地址 + * 3-参数名字>plc地址 + * 三个映射关系Map表 + */ +public class IsLandActionParamToPlc { + // 1-功能岛>plc地址:key-功能岛id,value-功能岛plc地址 + public static final Map islandToPlc = new HashMap<>(); + + // 2-动作单元>plc地址:key-动作单元id,value-动作单元plc地址 + public static final Map actionToPlc = new HashMap<>(); + + // 3-参数名字>plc地址:key-参数名字,value-参数plc地址 + public static final Map paramToPlc = new HashMap<>(); + + //4-参数id>plc地址:key-参数id,value-参数plc地址 + public static final Map paramIdToPlc = new HashMap<>(); + //更新三种数据的方法 + //获取spring里面bean + //1-功能岛>plc地址 + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java new file mode 100644 index 0000000..8478c95 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/PlcRunStatus.java @@ -0,0 +1,110 @@ +package com.rczn.rcznautoplc.cache; + +//样品准备状态 +public class PlcRunStatus { + //定容岛:状态属性: + public static int goodsScanStatus = 0; //货物扫描:0-准备,1-扫描完毕 + + //plc系统运行状态: + public static int systemPlcRunStatus = 0; //系统准备:0-未准备,1-空闲,2-忙,4异常 + + public static int goodsCount = 0;//样品处理数量 + + public static int goodsCurrentIndex = 0;//当前样品处理索引 + + //404内照射项目默认样品:尿液,液体: + public static String defaultGoodsName = "尿液"; + + public static String defaultGoodsType = "液体"; + + //目标监测物 + public static String defaultGoalDetect = "总氮"; + + public static class PlcRunStatusResponse{ + private int goodsScanStatus = 0; //货物扫描:0-准备,1-扫描完毕 + + private int systemPlcRunStatus = 0; //系统准备:0-未准备,1-空闲,2-忙,4异常 + + private int goodsCount = 0;//样品处理数量 + + private int goodsCurrentIndex = 0;//当前样品处理索引 + + private String defaultGoodsName = "尿液";//默认样品名称 + + private String defaultGoodsType = "液体";//默认样品类型 + + private String defaultGoalDetect = "总氮";//默认目标监测物 + + public PlcRunStatusResponse() { + + } + + public PlcRunStatusResponse(int goodsScanStatus, int systemPlcRunStatus, int goodsCount, int goodsCurrentIndex, String defaultGoodsName, String defaultGoodsType, String defaultGoalDetect) { + this.goodsScanStatus = goodsScanStatus; + this.systemPlcRunStatus = systemPlcRunStatus; + this.goodsCount = goodsCount; + this.goodsCurrentIndex = goodsCurrentIndex; + this.defaultGoodsName = defaultGoodsName; + this.defaultGoodsType = defaultGoodsType; + this.defaultGoalDetect = defaultGoalDetect; + } + + public int getGoodsScanStatus() { + return goodsScanStatus; + } + + public void setGoodsScanStatus(int goodsScanStatus) { + this.goodsScanStatus = goodsScanStatus; + } + + public int getSystemPlcRunStatus() { + return systemPlcRunStatus; + } + + public void setSystemPlcRunStatus(int systemPlcRunStatus) { + this.systemPlcRunStatus = systemPlcRunStatus; + } + + public int getGoodsCount() { + return goodsCount; + } + + public void setGoodsCount(int goodsCount) { + this.goodsCount = goodsCount; + } + + public int getGoodsCurrentIndex() { + return goodsCurrentIndex; + } + + public void setGoodsCurrentIndex(int goodsCurrentIndex) { + this.goodsCurrentIndex = goodsCurrentIndex; + } + + public String getDefaultGoodsName() { + return defaultGoodsName; + } + + public void setDefaultGoodsName(String defaultGoodsName) { + this.defaultGoodsName = defaultGoodsName; + } + + public String getDefaultGoodsType() { + return defaultGoodsType; + } + + public void setDefaultGoodsType(String defaultGoodsType) { + this.defaultGoodsType = defaultGoodsType; + } + + public String getDefaultGoalDetect() { + return defaultGoalDetect; + } + + public void setDefaultGoalDetect(String defaultGoalDetect) { + this.defaultGoalDetect = defaultGoalDetect; + } + } +} + + diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java new file mode 100644 index 0000000..d2425b5 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/cache/RegisterAddrDic.java @@ -0,0 +1,17 @@ +package com.rczn.rcznautoplc.cache; + +public class RegisterAddrDic { + + //主PLC:寄存器地址: + public final static int goodsScanRegisterArr = 5000;//样品扫描状态寄存器地址: + + //整体运转状态: + public final static int wholeRunStatusRegisterArr = 1100;//整体运转状态寄存器地址: + + //协议存储地址: + //1-下发plc:样品sop指令协议寄存器地址: + public final static int downProtcolRegisterArr = 2000;//协议存储寄存器地址: + //2-接收plc:处理样品状态数据协议寄存器地址 + public final static int upProtcolRegisterArr = 3000;//协议存储寄存器地址: + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/DevInfoController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/DevInfoController.java new file mode 100644 index 0000000..b2bcb38 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/DevInfoController.java @@ -0,0 +1,185 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.domain.Result; +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.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +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; + +/** + * 设备信息 Controller(RESTful 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> addDevInfo( + @Parameter(name = "动作单元信息", description = "动作单元新增请求参数", required = true) + @RequestBody DevInfo devInfo) { + Map 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> removeDevInfoById( + @Parameter(name = "id", description = "动作单元ID", required = true, example = "1") + @PathVariable Long id) { + Map 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> updateDevInfo( + @Parameter(name = "动作单元信息", description = "动作单元修改请求参数(含ID)", required = true) + @RequestBody DevInfo devInfo) { + Map 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> getDevInfoById( + @Parameter(name = "id", description = "动作单元ID", required = true, example = "1") + @PathVariable Long id) { + Map 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) + }) + public Result getDevInfoPage( + @ParameterObject // 核心注解:标记该实体类从查询参数取值 + @Schema(description = "设备查询条件(可选)") // 补充描述 + DevInfo devInfo, // 接收查询条件(devName、status等) + @RequestParam Integer pageNum, + @RequestParam Integer pageSize) { + try { + PageInfo pageInfo = devInfoService.getDevInfoPage(devInfo, pageNum, pageSize); + Result> success = Result.success(pageInfo); + return success; + } catch (Exception e) { + return Result.error("数据库异常!"); + } + } + + /** + * 查询所有设备(不分页) + */ + @GetMapping(value = "/all", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询所有设备", description = "返回所有未删除的设备完整信息(不分页,适用于设备数量较少场景)") + public ResponseEntity> getAllDevInfo() { + Map result = new HashMap<>(); + try { + List 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); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/DevParamController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/DevParamController.java new file mode 100644 index 0000000..e21d6c1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/DevParamController.java @@ -0,0 +1,161 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.DevParam; +import com.rczn.rcznautoplc.domain.query.DevParamQuery; +import com.rczn.rcznautoplc.service.DevParamService; +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("/devParam") +@Tag(name = "设备参数管理", description = "设备参数增删改查+分页查询接口") +public class DevParamController { + + @Autowired + DevParamService devParamService; + + /** + * 分页查询设备参数 + */ + @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 = "devId", description = "设备ID(可选,精准查询)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "paramTypeData", description = "参数类型(可选,模糊查询)", required = false, example = "耗材,通用", in = ParameterIn.QUERY), + @Parameter(name = "paramName", description = "参数名称(可选,模糊查询)", required = false, example = "温度", in = ParameterIn.QUERY), + @Parameter(name = "paramValue", description = "参数值(可选,模糊查询)", required = false, example = "25", in = ParameterIn.QUERY) + }) + public Result getDevParamPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer devId, + @RequestParam(required = false) String paramTypeData, + @RequestParam(required = false) String paramName, + @RequestParam(required = false) String paramValue) { + PageInfo pageBean = devParamService.selectPage(pageNum, pageSize, devId,paramTypeData, paramName, paramValue); + return Result.success(pageBean); + } + + /** + * 根据条件,查询设备参数 + */ + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询设备参数", description = "支持设备ID精准查询、参数名称/值模糊查询") + @Parameters({ + @Parameter(name = "devId", description = "设备ID(可选,精准查询)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "paramTypeData", description = "参数类型(可选,模糊查询)", required = false, example = "耗材,通用", in = ParameterIn.QUERY), + @Parameter(name = "paramName", description = "参数名称(可选,模糊查询)", required = false, example = "温度", in = ParameterIn.QUERY), + @Parameter(name = "paramValue", description = "参数值(可选,模糊查询)", required = false, example = "25", in = ParameterIn.QUERY) + }) + public Result getDevParamPage( + @RequestParam(required = false) Integer devId, + @RequestParam(required = false) String paramTypeData, + @RequestParam(required = false) String paramName, + @RequestParam(required = false) String paramValue) { + + DevParamQuery query = new DevParamQuery(); + query.setDevId(devId); + query.setParamTypeData(paramTypeData); + query.setParamName(paramName); + query.setParamValue(paramValue); + List pageBean = devParamService.selectList( query); + return Result.success(pageBean); + } + + /** + * 根据条件,查询设备参数 + */ + @PostMapping(value = "/addDevId", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "为参数增加设备的devId", description = "为参数增加设备的devId") + @Parameters({ + @Parameter(name = "devId", description = "设备ID", required = true, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "paramId", description = "参数Id", required = true, example = "1", in = ParameterIn.QUERY) + }) + public Result addDevId( + @RequestParam(required = true) Integer devId, + @RequestParam(required = true) Integer paramId) { + Boolean result = devParamService.addDevId( devId, paramId ); + return Result.success(result); + } + + /** + * 根据条件,查询设备参数 + */ + @PostMapping(value = "/delDevId", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "为参数减少设备的devId", description = "为参数减少设备的devId") + @Parameters({ + @Parameter(name = "devId", description = "设备ID", required = true, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "paramId", description = "参数Id", required = true, example = "1", in = ParameterIn.QUERY) + }) + public Result delDevId( + @RequestParam(required = true) Integer devId, + @RequestParam(required = true) Integer paramId) { + Boolean result = devParamService.reduceDevId( devId, paramId ); + return Result.success(result); + } + + /** + * 根据ID查询设备参数 + */ + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个设备参数", description = "根据设备参数ID查询详情") + public Result getDevParamById(@PathVariable Long id) { + DevParam devParam = devParamService.selectById(id); + return devParam != null ? Result.success(devParam) : Result.error("设备参数不存在"); + } + + /** + * 新增设备参数 + */ + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增设备参数", description = "设备ID、参数名称为必填项") + public Result addDevParam(@RequestBody DevParam devParam) { + try { + Long devParamId = devParamService.insert(devParam); + return Result.success(devParamId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + /** + * 修改设备参数 + */ + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改设备参数", description = "需传入设备参数ID,其他字段可选(非空则更新)") + public Result updateDevParam(@RequestBody DevParam devParam) { + try { + Boolean success = devParamService.update(devParam); + 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 deleteDevParam(@PathVariable Long id) { + try { + Boolean success = devParamService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(设备参数不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/FlowInfoController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/FlowInfoController.java new file mode 100644 index 0000000..90b11b3 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/FlowInfoController.java @@ -0,0 +1,143 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.FlowInfo; +import com.rczn.rcznautoplc.domain.ManageLog; +import com.rczn.rcznautoplc.domain.UserBusy; +import com.rczn.rcznautoplc.service.FlowInfoService; +import com.rczn.rcznautoplc.service.ManageLogService; +import com.rczn.utils.ThreadLocalUtil; +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; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; + +@RestController +@RequestMapping("/flowInfo") +@Tag(name = "标准流程管理", description = "流程信息增删改查+分页查询接口") +public class FlowInfoController { + + @Autowired + FlowInfoService flowInfoService; + + @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 = "flowIndex", description = "流程排序(可选,精准查询)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "flowName", description = "流程名称(可选,模糊查询)", required = false, example = "检测流程", in = ParameterIn.QUERY), + @Parameter(name = "islandIdList", description = "岛屿ID列表(可选,模糊查询)", required = false, example = "1,2,3", in = ParameterIn.QUERY) + }) + public Result getFlowInfoPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer flowIndex, + @RequestParam(required = false) String flowName, + @RequestParam(required = false) String islandIdList) { + PageInfo pageBean = flowInfoService.selectPage(pageNum, pageSize, flowIndex, flowName, islandIdList); + return Result.success(pageBean); + } + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询流程信息", description = "支持流程排序精准查询、流程名称/岛屿ID列表模糊查询") + @Parameters({ + @Parameter(name = "flowIndex", description = "流程排序(可选,精准查询)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "flowName", description = "流程名称(可选,模糊查询)", required = false, example = "检测流程", in = ParameterIn.QUERY), + @Parameter(name = "islandIdList", description = "岛屿ID列表(可选,模糊查询)", required = false, example = "1,2,3", in = ParameterIn.QUERY) + }) + public Result getFlowInfoList( + @RequestParam(required = false) Integer flowIndex, + @RequestParam(required = false) String flowName, + @RequestParam(required = false) String islandIdList) { + List list = flowInfoService.selectList( flowIndex, flowName, islandIdList); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个流程信息", description = "根据流程信息ID查询详情") + public Result getFlowInfoById(@PathVariable Long id) { + FlowInfo flowInfo = flowInfoService.selectById(id); + return flowInfo != null ? Result.success(flowInfo) : Result.error("流程信息不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增流程信息", description = "流程名称、流程排序为必填项") + public Result addFlowInfo(@RequestBody FlowInfo flowInfo) { + try { + Long flowInfoId = flowInfoService.insert(flowInfo); + //记录操作样品执行SOP操作日志: + LocalDateTime loginTime = LocalDateTime.now(); + ManageLog info = new ManageLog(); + // ========== 修复开始 ========== + Map mapClaims = ThreadLocalUtil.get(); + UserBusy userBusy = new UserBusy(); + userBusy.setId(Long.valueOf( mapClaims.get("id").toString())); + userBusy.setUserName((String) mapClaims.get("username")); + // ========== 修复结束 ========== + info.setCreateId(userBusy.getId()); + info.setLogName("基础数据操作日志"); + info.setLogType("基础数据操作日志");//1:登录日志、2:SOP操作日志、3:基础数据操作日志 + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("用户名:").append(userBusy.getUserName()).append(",SOP配置添加操作时间:").append(loginTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setLogContent(stringBuilder.toString()); + info.setCreateTime(loginTime); + manageLogService.insert(info); + return Result.success(flowInfoId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改流程信息", description = "需传入流程信息ID,其他字段可选(非空则更新)") + public Result updateFlowInfo(@RequestBody FlowInfo flowInfo) { + try { + Boolean success = flowInfoService.update(flowInfo); + return success ? Result.success(true) : Result.error("修改失败(流程信息不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @Autowired + ManageLogService manageLogService; + + @DeleteMapping(value = "/del/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "删除流程信息", description = "逻辑删除(设置delSign=1,不物理删除数据)") + public Result deleteFlowInfo(@PathVariable Long id) { + try { + Boolean success = flowInfoService.deleteById(id); + //记录操作样品执行SOP操作日志: + LocalDateTime loginTime = LocalDateTime.now(); + ManageLog info = new ManageLog(); + // ========== 修复开始 ========== + Map mapClaims = ThreadLocalUtil.get(); + UserBusy userBusy = new UserBusy(); + userBusy.setId(Long.valueOf( mapClaims.get("id").toString())); + userBusy.setUserName((String) mapClaims.get("username")); + // ========== 修复结束 ========== + info.setCreateId(userBusy.getId()); + info.setLogName("基础数据操作日志"); + info.setLogType("基础数据操作日志");//1:登录日志、2:SOP操作日志、3:基础数据操作日志 + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("用户名:").append(userBusy.getUserName()).append(",SOP配置删除操作时间:").append(loginTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setLogContent(stringBuilder.toString()); + info.setCreateTime(loginTime); + manageLogService.insert(info); + return success ? Result.success(true) : Result.error("删除失败(流程信息不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/GoodsFlowStatusController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/GoodsFlowStatusController.java new file mode 100644 index 0000000..47adab5 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/GoodsFlowStatusController.java @@ -0,0 +1,98 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.query.GoodsFlowStatusQuery; +import com.rczn.rcznautoplc.service.GoodsFlowStatusService; +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.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/goodsFlowStatus") +@Tag(name = "样品流程信息管理", description = "样品流程状态增删改查+分页查询接口") +public class GoodsFlowStatusController { + + @Autowired + GoodsFlowStatusService goodsFlowStatusService; + + + @GetMapping(value = "/listPage", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "分页查询样品流程状态", description = "支持样品ID、流程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), + }) + public Result getGoodsFlowStatusPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @ParameterObject + @Schema(description = "样品ID、流程ID、岛屿ID、状态精准查询条件") + GoodsFlowStatusQuery goodsFlowStatus) { + PageInfo pageBean = goodsFlowStatusService.selectPage(pageNum, pageSize, goodsFlowStatus); + return Result.success(pageBean); + } + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询样品流程状态", description = "支持样品ID、流程ID、岛屿ID、状态等精准查询") + @Parameters({ + }) + public Result getList( + @ParameterObject + @Schema(description = "样品ID、流程ID、岛屿ID、状态等精准查询条件") + GoodsFlowStatusQuery goodsFlowStatus) { + List list = goodsFlowStatusService.selectList( goodsFlowStatus); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个样品流程状态", description = "根据样品流程状态ID查询详情") + public Result getGoodsFlowStatusById(@PathVariable Long id) { + GoodsFlowStatus goodsFlowStatus = goodsFlowStatusService.selectById(id); + return goodsFlowStatus != null ? Result.success(goodsFlowStatus) : Result.error("样品流程状态不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增样品流程状态", description = "样品ID、流程ID、状态为必填项(状态:0-未执行,1-执行,10-通过,11-失败)") + public Result addGoodsFlowStatus(@RequestBody GoodsFlowStatus goodsFlowStatus) { + try { + Long goodsFlowStatusId = goodsFlowStatusService.insert(goodsFlowStatus); + return Result.success(goodsFlowStatusId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改样品流程状态", description = "需传入样品流程状态ID,其他字段可选(非空则更新)") + public Result updateGoodsFlowStatus(@RequestBody GoodsFlowStatus goodsFlowStatus) { + try { + Boolean success = goodsFlowStatusService.update(goodsFlowStatus); + 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 deleteGoodsFlowStatus(@PathVariable Long id) { + try { + Boolean success = goodsFlowStatusService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(样品流程状态不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/GoodsInfoController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/GoodsInfoController.java new file mode 100644 index 0000000..b347383 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/GoodsInfoController.java @@ -0,0 +1,134 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; +import com.rczn.rcznautoplc.service.GoodsInfoService; +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.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/goodsInfo") +@Tag(name = "样品信息管理", description = "样品信息增删改查+分页查询接口") +public class GoodsInfoController { + + @Autowired + GoodsInfoService goodsInfoService; + + /** + * 分页查询样品信息 + */ + @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 = "goodsName", description = "样品名称(可选,模糊查询)", required = false, example = "手机", in = ParameterIn.QUERY), +// @Parameter(name = "goodsType", description = "样品类型(可选,模糊查询)", required = false, example = "电子产品", in = ParameterIn.QUERY), +// @Parameter(name = "goodFrom", description = "样品来源(可选,模糊查询)", required = false, example = "深圳", in = ParameterIn.QUERY), +// @Parameter(name = "goodBatch", description = "样品批次(可选,精准查询)", required = false, example = "202501", in = ParameterIn.QUERY) + }) + public Result getGoodsInfoPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @ParameterObject + @Schema(description = "样品信息查询条件(可选)", name = "goodsInfo", required = false) + GoodsInfoQuery goodsInfo) { + PageInfo pageBean = goodsInfoService.selectPage(pageNum, pageSize, goodsInfo); + return Result.success(pageBean); + } + + /** + * 查询样品信息 + */ + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询样品信息", description = "支持样品名称/类型/来源模糊查询、批次精准查询") + @Parameters({ + }) + public Result getList( + @ParameterObject + @Schema(description = "样品信息查询条件(可选)", name = "goodsInfo", required = false) + GoodsInfoQuery goodsInfo) { + List list = goodsInfoService.selectList( goodsInfo); + return Result.success(list); + } + + /** + * 根据ID查询样品信息 + */ + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个样品信息", description = "根据样品信息ID查询详情") + public Result getGoodsInfoById(@PathVariable Long id) { + GoodsInfo goodsInfo = goodsInfoService.selectById(id); + return goodsInfo != null ? Result.success(goodsInfo) : Result.error("样品信息不存在"); + } + + /** + * 新增样品信息 + */ + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增样品信息", description = "样品名称、类型、入库时间为必填项") + public Result addGoodsInfo(@RequestBody GoodsInfo goodsInfo) { + try { + Long goodsInfoId = goodsInfoService.insert(goodsInfo); + return Result.success(goodsInfoId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + /** + * 扫码新增样品信息 + * 扫码信息:样品类型、样品编码、样品名称、样品点位 + */ + @PostMapping(value = "/scanAdd", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "扫描新增样品", description = "样品名称、类型、编码、点位为必填项") + public Result scanAdd(@RequestBody GoodsInfo goodsInfo) { + try { + GoodsInfo goodInfoResult = goodsInfoService.insertByScan(goodsInfo); + return Result.success(goodInfoResult); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + /** + * 修改样品信息 + */ + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改样品信息", description = "需传入样品信息ID,其他字段可选(非空则更新)") + public Result updateGoodsInfo(@RequestBody GoodsInfo goodsInfo) { + try { + Boolean success = goodsInfoService.update(goodsInfo); + 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 deleteGoodsInfo(@PathVariable Long id) { + try { + Boolean success = goodsInfoService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(样品信息不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/IslandInfoController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/IslandInfoController.java new file mode 100644 index 0000000..5452dd7 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/IslandInfoController.java @@ -0,0 +1,81 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.IslandInfo; +import com.rczn.rcznautoplc.service.IslandInfoService; +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.*; + +@RestController +@RequestMapping("/islandInfo") +@Tag(name = "功能岛信息管理", description = "功能岛信息增删改查+分页查询接口") +public class IslandInfoController { + + @Autowired + IslandInfoService islandInfoService; + + @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 = "islandName", description = "功能岛名称(可选,模糊查询)", required = false, example = "一号岛", in = ParameterIn.QUERY), + @Parameter(name = "islandCode", description = "功能岛编码(可选,模糊查询)", required = false, example = "ISLAND001", in = ParameterIn.QUERY) + }) + public Result getIslandInfoPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String islandName, + @RequestParam(required = false) String islandCode) { + PageInfo pageBean = islandInfoService.selectPage(pageNum, pageSize, islandName, islandCode); + return Result.success(pageBean); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个功能岛信息", description = "根据功能岛信息ID查询详情") + public Result getIslandInfoById(@PathVariable Long id) { + IslandInfo islandInfo = islandInfoService.selectById(id); + return islandInfo != null ? Result.success(islandInfo) : Result.error("功能岛信息不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增功能岛信息", description = "功能岛名称、编码为必填项") + public Result addIslandInfo(@RequestBody IslandInfo islandInfo) { + try { + Long islandInfoId = islandInfoService.insert(islandInfo); + return Result.success(islandInfoId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改功能岛信息", description = "需传入功能岛信息ID,其他字段可选(非空则更新)") + public Result updateIslandInfo(@RequestBody IslandInfo islandInfo) { + try { + Boolean success = islandInfoService.update(islandInfo); + 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 deleteIslandInfo(@PathVariable Long id) { + try { + Boolean success = islandInfoService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(功能岛信息不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/IslandParamController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/IslandParamController.java new file mode 100644 index 0000000..851258a --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/IslandParamController.java @@ -0,0 +1,86 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.IslandParam; +import com.rczn.rcznautoplc.service.IslandParamService; +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.*; + +@RestController +@RequestMapping("/islandParam") +@Tag(name = "功能岛参数管理", description = "功能岛参数增删改查+分页查询接口") +public class IslandParamController { + + @Autowired + IslandParamService islandParamService; + + + @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 = "islandId", description = "功能岛ID(可选,精准查询)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "stepId", description = "步骤ID(可选,精准查询)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "paramName", description = "参数名称(可选,模糊查询)", required = false, example = "温度", in = ParameterIn.QUERY), + @Parameter(name = "paramType", description = "参数类型(可选,精准查询)", required = false, example = "数值", in = ParameterIn.QUERY) + }) + public Result getIslandParamPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) Integer islandId, + @RequestParam(required = false) Integer stepId, + @RequestParam(required = false) String paramName, + @RequestParam(required = false) String paramType) { + PageInfo pageBean = islandParamService.selectPage(pageNum, pageSize, islandId, stepId, paramName, paramType); + return Result.success(pageBean); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个功能岛参数", description = "根据功能岛参数ID查询详情") + public Result getIslandParamById(@PathVariable Long id) { + IslandParam islandParam = islandParamService.selectById(id); + return islandParam != null ? Result.success(islandParam) : Result.error("功能岛参数不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增功能岛参数", description = "功能岛ID、步骤ID、参数名称为必填项") + public Result addIslandParam(@RequestBody IslandParam islandParam) { + try { + Long islandParamId = islandParamService.insert(islandParam); + return Result.success(islandParamId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改功能岛参数", description = "需传入功能岛参数ID,其他字段可选(非空则更新)") + public Result updateIslandParam(@RequestBody IslandParam islandParam) { + try { + Boolean success = islandParamService.update(islandParam); + 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 deleteIslandParam(@PathVariable Long id) { + try { + Boolean success = islandParamService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(功能岛参数不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java new file mode 100644 index 0000000..06238d6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/ManageLogController.java @@ -0,0 +1,120 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.ManageLog; +import com.rczn.rcznautoplc.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.format.annotation.DateTimeFormat; +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> 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) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime logWritetimeStart, + @RequestParam(required = false) + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") + LocalDateTime logWritetimeEnd) { + + // 构建查询条件(空字段自动忽略) + ManageLog query = new ManageLog(); + query.setLogName(logName); + query.setLogType(logType); + query.setCreateId(createId); + // 扩展字段:用于时间范围查询(实体类无需新增字段,MyBatis 支持直接取参) + query.setStartTime(logWritetimeStart); // 实际用 logWritetimeStart,这里仅为传递参数 + query.setEndTime(logWritetimeEnd); + + PageBean 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()); + } + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java new file mode 100644 index 0000000..c0a91b2 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/PlcController.java @@ -0,0 +1,337 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.domain.Result; +import com.rczn.modbus.Modbus4jWriteUtils; +import com.rczn.rcznautoplc.cache.PlcRunStatus; +import com.rczn.rcznautoplc.domain.*; +import com.rczn.rcznautoplc.domain.query.StepInfoQuery; +import com.rczn.rcznautoplc.service.*; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.rczn.utils.ThreadLocalUtil; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 设备信息 Controller(RESTful API) + */ +@RestController +@RequestMapping("/plc") +@Tag(name = "plc设备控制类", description = "plc设备初始化,查询,控制方法集合") +public class PlcController { + + @Autowired + private PlcService plcService; + + /** + * 设备连接 + */ + @PostMapping(value = "/connect", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "连接设备", description = "连接设备...") + public Result plcConnect( + @ParameterObject + @Schema(description = "plc设备参数") + ModbusConnectObj connectObj) { + ModbusMaster connectorInit; + if(PlcConnectMap.modbusConnectorMap.containsKey(connectObj.getIpAddr())){ + return Result.error("设备连接已经存在!"); + } + try { + + connectorInit = plcService.connectModbus(connectObj); + if(connectorInit != null){ + return Result.success(true); + }else { + return Result.error("设备连接失败!"); + } + + } catch (Exception e) { + return Result.error("设备连接失败!"); + } + } + + /** + * 向plc寄存器写数据: + */ + @PostMapping(value = "/plcWrite", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "连接设备", description = "连接设备...") + public Result plcWrite( + @ParameterObject + @Schema(description = "plc设备参数") + ModbusConnectObj connectObj, + @Parameter + @Schema(description = "寄存器地址", required = true, example = "10000") + @RequestParam int registerAddress, + @Parameter + @Schema(description = "寄存器值", required = true, example = "12345") + @RequestParam int registerValue) { + ModbusMaster connectorInit; + if(PlcConnectMap.modbusConnectorMap.containsKey(connectObj.getIpAddr())){ + connectorInit = PlcConnectMap.modbusConnectorMap.get(connectObj.getIpAddr()); + try { + Modbus4jWriteUtils.writeHoldingRegister(connectorInit,1,registerAddress,registerValue, DataType.TWO_BYTE_INT_UNSIGNED); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ErrorResponseException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + return Result.error("设备连接已经存在!"); + } + try { + connectorInit = plcService.connectModbus(connectObj); + if(connectorInit != null){ + //往地址1000里面写入数据: + Modbus4jWriteUtils.writeHoldingRegister(connectorInit,1,registerAddress,registerValue, DataType.TWO_BYTE_INT_UNSIGNED); + return Result.success(true); + }else { + return Result.error("设备连接失败!"); + } + + } catch (Exception e) { + return Result.error("设备连接失败!"); + } + } + + /** + * 根据ID删除设备(逻辑删除) + */ + @PostMapping(value = "/run") + @Operation(summary = "运行plc", description = "plc设备运行停止") + public Result runPlc( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.startPlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据ID删除设备(逻辑删除) + */ + @PostMapping(value = "/pause") + @Operation(summary = "暂停运行plc", description = "暂停运行plc") + public Result pausePlc( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.pausePlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据设备ip地址,停止执行 + */ + @PostMapping(value = "/stop") + @Operation(summary = "停止plc", description = "plc设备运行停止") + public Result stop( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.stopPlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,故障复位 + */ + @PostMapping(value = "/resetError") + @Operation(summary = "plc设备复位故障", description = "plc设备复位故障") + public Result resetError( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Boolean success = plcService.resetErrorPlc(ipAddr); + return Result.success(success); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,获取plc设备状态 + */ + @GetMapping(value = "/plcStatus") + @Operation(summary = "plc设备获取状态值", description = "状态值:10-就绪,11-执行中,12-暂停中,19已停止,20-故障中") + public Result plcStatus( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Integer resultValue = plcService.getPlcStatus(ipAddr); + return Result.success(resultValue); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + + /** + * 根据plc ip地址,获取plc设备状态 + */ + @GetMapping(value = "/mastertPlcStatus") + @Operation(summary = "获取主plc状态对象", description = "goodsScanStatus = 0; //货物扫描:0-准备,1-扫描完毕;//系统准备:0-未准备,1-空闲,2-忙,4异常") + public Result mastertPlcStatus() { + try { + PlcRunStatus.PlcRunStatusResponse response = new PlcRunStatus.PlcRunStatusResponse(); + response.setGoodsScanStatus(PlcRunStatus.goodsScanStatus); + response.setSystemPlcRunStatus(PlcRunStatus.systemPlcRunStatus); + response.setGoodsCount(PlcRunStatus.goodsCount); + response.setGoodsCurrentIndex(PlcRunStatus.goodsCurrentIndex); + response.setDefaultGoodsName(PlcRunStatus.defaultGoodsName); + response.setDefaultGoodsType(PlcRunStatus.defaultGoodsType); + response.setDefaultGoalDetect(PlcRunStatus.defaultGoalDetect); + + return Result.success(response); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,设置plc设备模式: + * 0-手动模式,1-自动模式 + */ + @PostMapping(value = "/setModel") + @Operation(summary = "plc设备设置模式", description = "模式值:0-手动模式,1-自动模式") + public Result setModel( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123", in = ParameterIn.QUERY) + @RequestParam String ipAddr, + @Parameter(name = "model", description = "设备模式值", required = true, example = "0-1", in = ParameterIn.QUERY) + @RequestParam Integer model) { + try { + Boolean resultValue = plcService.setPlcModel(ipAddr,model); + return Result.success(resultValue); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 根据plc ip地址,获取plc设备模式: + * 0-手动模式,1-自动模式 + */ + @GetMapping(value = "/getModel") + @Operation(summary = "plc设备获取模式值", description = "模式值:0-手动模式,1-自动模式") + public Result getModel( + @Parameter(name = "ipAddr", description = "设备ip地址", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + try { + Integer resultValue = plcService.getPlcModel(ipAddr); + return Result.success(resultValue); + } catch (Exception e) { + return Result.error("停止失败!"); + } + } + + /** + * 更新设备 + */ + @GetMapping(value = "/getAll", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "获取全部plc连接对象", description = "获取全部plc连接对象") + public Result getPlcAll() { + Map connectorMap = plcService.modbusALlMap(); + return Result.success(connectorMap); + } + + /** + * 根据ID查询设备 + */ + @GetMapping(value = "/getPlcByIp", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "更加ip地址,查询plc连接对象", description = "更加ip地址,查询plc连接对象") + public Result getConnectByIpaddr( + @Parameter(name = "ipAddr", description = "设备IP", required = true, example = "192.168.1.123") + @RequestParam String ipAddr) { + ModbusMaster connector = plcService.getModbusConnect(ipAddr); + return Result.success(connector); + } + + /** + * 查询所有设备(不分页) + */ + @PostMapping(value = "/doAction", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "调用plc设备执行动作", description = "根据plc设备ip,执行动作") + public Result doAction( + @RequestParam String ip, + @RequestParam String action + ) { + Boolean aBoolean = plcService.doAction(ip, action); + return Result.success(aBoolean); + } + + @Autowired + StepInfoService stepInfoService; + @Autowired + GoodsInfoService goodsInfoService; + + @Autowired + ManageLogService manageLogService; + + @PostMapping(value = "/runFlow") + @Operation(summary = "为样品执行国标" ,description = "为样品执行国标") + public Result doStandGoods( + + @RequestParam String plcIp, + @RequestParam Integer flowId, + @RequestParam List goodsIds + ){ + //根据flowId获取步骤信息表: + StepInfoQuery stepInfo = new StepInfoQuery(); + stepInfo.setFlowId(flowId); + List stepInfoList = stepInfoService.selectList(stepInfo); + //stepInfoList根据StepInfo里面的stepOrder(int)排序 + stepInfoList.sort(Comparator.comparing(StepInfo::getStepOrder)); + //根据goodsIds获取样品信息的 bar_code编码列表: + List goodsInfoList = goodsInfoService.selectByIdList(goodsIds); + List barCodeList = goodsInfoList.stream().map(GoodsInfo::getBarCode).collect(Collectors.toList()); + Boolean aBoolean = plcService.runSopInfoForGoodsList(plcIp,flowId, barCodeList, stepInfoList); + //记录操作样品执行SOP操作日志: + LocalDateTime loginTime = LocalDateTime.now(); + ManageLog info = new ManageLog(); + // ========== 修复开始 ========== + Map mapClaims = ThreadLocalUtil.get(); + UserBusy userBusy = new UserBusy(); + userBusy.setId(Long.valueOf( mapClaims.get("id").toString())); + userBusy.setUserName((String) mapClaims.get("username")); + // ========== 修复结束 ========== + info.setCreateId(userBusy.getId()); + info.setLogName("SOP操作日志"); + info.setLogType("SOP操作日志");//1:登录日志、2:SOP操作日志、3:基础数据操作日志 + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("用户名:").append(userBusy.getUserName()).append(",SOP执行操作时间:").append(loginTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); + info.setLogContent(stringBuilder.toString()); + info.setCreateTime(loginTime); + manageLogService.insert(info); + + return Result.success(aBoolean); + } + + +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/RecordInfoController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/RecordInfoController.java new file mode 100644 index 0000000..802dcb2 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/RecordInfoController.java @@ -0,0 +1,84 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.RecordInfo; +import com.rczn.rcznautoplc.service.RecordInfoService; +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.*; + +@RestController +@RequestMapping("/recordInfo") +@Tag(name = "记录信息管理", description = "记录信息增删改查+分页查询接口") +public class RecordInfoController { + + @Autowired + RecordInfoService recordInfoService; + + + @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 = "recordName", description = "记录名称(可选,模糊查询)", required = false, example = "设备故障", in = ParameterIn.QUERY), + @Parameter(name = "recordType", description = "记录类型(可选,精准查询:1-设备异常,2-样品异常,3-操作异常)", required = false, example = "1", in = ParameterIn.QUERY), + @Parameter(name = "recordStatus", description = "记录状态(可选,精准查询:false-未处理,true-已处理)", required = false, example = "false", in = ParameterIn.QUERY) + }) + public Result getRecordInfoPage( + @RequestParam Integer pageNum, + @RequestParam Integer pageSize, + @RequestParam(required = false) String recordName, + @RequestParam(required = false) Integer recordType, + @RequestParam(required = false) Boolean recordStatus) { + PageInfo pageBean = recordInfoService.selectPage(pageNum, pageSize, recordName, recordType, recordStatus); + return Result.success(pageBean); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个记录信息", description = "根据记录信息ID查询详情") + public Result getRecordInfoById(@PathVariable Long id) { + RecordInfo recordInfo = recordInfoService.selectById(id); + return recordInfo != null ? Result.success(recordInfo) : Result.error("记录信息不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增记录信息", description = "记录名称、类型、内容为必填项(类型:1-设备异常,2-样品异常,3-操作异常)") + public Result addRecordInfo(@RequestBody RecordInfo recordInfo) { + try { + Long recordInfoId = recordInfoService.insert(recordInfo); + return Result.success(recordInfoId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改记录信息", description = "需传入记录信息ID,其他字段可选(非空则更新)") + public Result updateRecordInfo(@RequestBody RecordInfo recordInfo) { + try { + Boolean success = recordInfoService.update(recordInfo); + 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 deleteRecordInfo(@PathVariable Long id) { + try { + Boolean success = recordInfoService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(记录信息不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/StepInfoController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/StepInfoController.java new file mode 100644 index 0000000..9c856f6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/StepInfoController.java @@ -0,0 +1,133 @@ +package com.rczn.rcznautoplc.controller; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.domain.Result; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.domain.query.StepInfoQuery; +import com.rczn.rcznautoplc.service.StepInfoService; +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.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springdoc.core.annotations.ParameterObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/stepInfo") +@Tag(name = "步骤信息管理", description = "步骤信息增删改查+分页查询接口") +public class StepInfoController { + + @Autowired + StepInfoService stepInfoService; + + @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) + }) + public Result getStepInfoPage( + @ParameterObject // 核心注解:标记该实体类从查询参数取值 + @Schema(description = "设备查询条件(可选)") // 补充描述 + StepInfoQuery stepInfo, + @RequestParam Integer pageNum, + @RequestParam Integer pageSize + ) { + PageInfo pageBean = stepInfoService.selectPage(pageNum, pageSize, stepInfo); + return Result.success(pageBean); + } + + + @GetMapping(value = "/list", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询步骤信息", description = "支持岛屿ID精准查询、步骤名称模糊查询") + public Result getStepInfoList( + @ParameterObject // 核心注解:标记该实体类从查询参数取值 + @Schema(description = "设备查询条件(可选)") // 补充描述 + StepInfoQuery stepInfo) { + List list = stepInfoService.selectList( stepInfo); + return Result.success(list); + } + + @GetMapping(value = "/getById/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "查询单个步骤信息", description = "根据步骤信息ID查询详情") + public Result getStepInfoById(@PathVariable Long id) { + StepInfo stepInfo = stepInfoService.selectById(id); + return stepInfo != null ? Result.success(stepInfo) : Result.error("步骤信息不存在"); + } + + @PostMapping(value = "/add", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "新增步骤信息", description = "岛屿ID、步骤名称为必填项") + public Result addStepInfo(@RequestBody StepInfo stepInfo) { + try { + Long stepInfoId = stepInfoService.insert(stepInfo); + return Result.success(stepInfoId); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + @PostMapping(value = "/batchAdd", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "批量新增步骤信息", description = "岛屿ID、步骤名称为必填项") + public Result batchAddStepInfo(@RequestBody List stepInfoList) { + try { + stepInfoService.insertBatch(stepInfoList); + return Result.success(true); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + //批量更新步骤信息 + @PostMapping(value = "/batchUpdate", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "批量更新步骤信息", description = "岛屿ID、步骤名称为必填项") + public Result batchUpdateStepInfo(@RequestBody List stepInfoList) { + try { + stepInfoService.updateBatch(stepInfoList); + return Result.success(true); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + + @PutMapping(value = "/update", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "修改步骤信息", description = "需传入步骤信息ID,其他字段可选(非空则更新)") + public Result updateStepInfo(@RequestBody StepInfo stepInfo) { + try { + Boolean success = stepInfoService.update(stepInfo); + 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 deleteStepInfo(@PathVariable Long id) { + try { + Boolean success = stepInfoService.deleteById(id); + return success ? Result.success(true) : Result.error("删除失败(步骤信息不存在或已删除)"); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } + + //批量删除步骤信息 + @DeleteMapping(value = "/batchDel", produces = MediaType.APPLICATION_JSON_VALUE) + @Operation(summary = "批量删除步骤信息", description = "逻辑删除(设置delSign=1,不物理删除数据)") + public Result batchDeleteStepInfo(@RequestBody List ids) { + try { + stepInfoService.deleteBatchByIds(ids); + return Result.success(true); + } catch (IllegalArgumentException e) { + return Result.error(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java new file mode 100644 index 0000000..6682c86 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/controller/WebSocketController.java @@ -0,0 +1,23 @@ +package com.rczn.rcznautoplc.controller; + +import com.rczn.websocket.WebSocketServer; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/websocket") +@Tag(name = "websocket", description = "websocket接口") +public class WebSocketController { + + @Autowired + private WebSocketServer webSocketServer; + + @RequestMapping("/send/{message}") + public String send(@PathVariable("message") String message){ + webSocketServer.onMessage(message,null); + return "success"; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevInfo.java new file mode 100644 index 0000000..bd1a36a --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevInfo.java @@ -0,0 +1,132 @@ +package com.rczn.rcznautoplc.domain; + +import com.rczn.domain.BaseBean; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public class DevInfo extends BaseBean { + + //功能岛外键 + private Integer islandId; + + //设备名称 + private String devName; + + //设备型号 + private String devModel; + + //plc映射地址 + private Integer plcAddr; + + //设备IP地址 + private String ipAddr; + + private Integer port; + + private String protocolType; + + private String company; + + private Integer status; // 0-空闲,1-运行,4-故障 + + private Integer runModel;//0-手动模式,1-自动模式 + + private String devDesc; + + 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 Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + 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 Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + 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 Integer getRunModel() { + return runModel; + } + + public void setRunModel(Integer runModel) { + this.runModel = runModel; + } + + public String getDevDesc() { + return devDesc; + } + + public void setDevDesc(String devDesc) { + this.devDesc = devDesc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevParam.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevParam.java new file mode 100644 index 0000000..de17b38 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/DevParam.java @@ -0,0 +1,119 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public class DevParam extends BaseBean { + private String devIds; + + //字典类型-参数分类id + private Integer dicDataId; + + private String paramName; + //plc映射地址 + private Integer plcAddr; + + private String paramValue; + + private String paramType; + + private String paramUnit; + + private String formType; + + private String paramDesc; + + @JsonIgnore + 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 String getDevIds() { + return devIds; + } + + public void setDevIds(String devIds) { + this.devIds = devIds; + } + + 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 getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + public Integer getDicDataId() { + return dicDataId; + } + + public void setDicDataId(Integer dicDataId) { + this.dicDataId = dicDataId; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public String getParamDesc() { + return paramDesc; + } + + public void setParamDesc(String paramDesc) { + this.paramDesc = paramDesc; + } + + public DevInfo getDevInfo() { + return devInfo; + } + + public void setDevInfo(DevInfo devInfo) { + this.devInfo = devInfo; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/FlowInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/FlowInfo.java new file mode 100644 index 0000000..9bb0a48 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/FlowInfo.java @@ -0,0 +1,114 @@ +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; + + private String busyCode; + + private String goodsCode; + + private String goodsName; + + private String checkCode; // 校验码 + + private String programName; // 程序名称 + + private String testMethod; // 测试方法 + + private String scanNum; //扫描编号 + + 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 String getBusyCode() { + return busyCode; + } + + public void setBusyCode(String busyCode) { + this.busyCode = busyCode; + } + + public String getGoodsCode() { + return goodsCode; + } + + public void setGoodsCode(String goodsCode) { + this.goodsCode = goodsCode; + } + + public String getGoodsName() { + return goodsName; + } + + public void setGoodsName(String goodsName) { + this.goodsName = goodsName; + } + + public String getCheckCode() { + return checkCode; + } + + public void setCheckCode(String checkCode) { + this.checkCode = checkCode; + } + + public String getProgramName() { + return programName; + } + + public void setProgramName(String programName) { + this.programName = programName; + } + + public String getTestMethod() { + return testMethod; + } + + public void setTestMethod(String testMethod) { + this.testMethod = testMethod; + } + + public String getScanNum() { + return scanNum; + } + + public void setScanNum(String scanNum) { + this.scanNum = scanNum; + } + + 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; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/GoodsFlowStatus.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/GoodsFlowStatus.java new file mode 100644 index 0000000..2e031f7 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/GoodsFlowStatus.java @@ -0,0 +1,107 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public class GoodsFlowStatus extends BaseBean { + private Integer goodsId; + + private Integer flowId; + + private Integer islandId; + + private Integer devId; + + 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 getDevId() { + return devId; + } + + public void setDevId(Integer devId) { + this.devId = devId; + } + + 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; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/GoodsInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/GoodsInfo.java new file mode 100644 index 0000000..c1af170 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/GoodsInfo.java @@ -0,0 +1,129 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.models.security.SecurityScheme; + +import java.time.LocalDateTime; + + +public class GoodsInfo extends BaseBean { + private String goodsName; + + private String goodsType; + + private LocalDateTime incomeTime; + + private String goodFrom; + + private Integer goodBatch; + + //进样点位 + private Integer pointNum; + + //目标监测物 + private String goalDetect; + + //条码 + private String barCode; + + //国标id + private Integer flowId; + + private Integer goodsStatus; + + private String desc; + + public GoodsInfo() { + } + + public String getGoodsName() { + return goodsName; + } + + public void setGoodsName(String goodsName) { + this.goodsName = goodsName; + } + + public String getGoodsType() { + return goodsType; + } + + public void setGoodsType(String goodsType) { + this.goodsType = goodsType; + } + + public LocalDateTime getIncomeTime() { + return incomeTime; + } + + public void setIncomeTime(LocalDateTime incomeTime) { + this.incomeTime = incomeTime; + } + + public String getGoodFrom() { + return goodFrom; + } + + public void setGoodFrom(String goodFrom) { + this.goodFrom = goodFrom; + } + + public Integer getGoodBatch() { + return goodBatch; + } + + public void setGoodBatch(Integer goodBatch) { + this.goodBatch = goodBatch; + } + + public Integer getPointNum() { + return pointNum; + } + + public void setPointNum(Integer pointNum) { + this.pointNum = pointNum; + } + + public String getGoalDetect() { + return goalDetect; + } + + public void setGoalDetect(String goalDetect) { + this.goalDetect = goalDetect; + } + + public String getBarCode() { + return barCode; + } + + public void setBarCode(String barCode) { + this.barCode = barCode; + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + public Integer getGoodsStatus() { + return goodsStatus; + } + + public void setGoodsStatus(Integer goodsStatus) { + this.goodsStatus = goodsStatus; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java new file mode 100644 index 0000000..3c965dc --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandInfo.java @@ -0,0 +1,62 @@ +package com.rczn.rcznautoplc.domain; + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + + +public class IslandInfo extends BaseBean { + private String islandName; + + private String islandCode; + + //plc映射地址 + private Integer plcAddr; + + private String islandLogo; + + private String desc; + + public IslandInfo() { + } + + public String getIslandName() { + return islandName; + } + + public void setIslandName(String islandName) { + this.islandName = islandName; + } + + public String getIslandCode() { + return islandCode; + } + + public void setIslandCode(String islandCode) { + this.islandCode = islandCode; + } + + public Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + public String getIslandLogo() { + return islandLogo; + } + + public void setIslandLogo(String islandLogo) { + this.islandLogo = islandLogo; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandParam.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandParam.java new file mode 100644 index 0000000..89ad895 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/IslandParam.java @@ -0,0 +1,109 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +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; + + @JsonIgnore + private IslandInfo islandInfo; + + @JsonIgnore + private StepInfo stepInfo; + + public IslandParam() { + } + + public IslandParam(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getStepId() { + return stepId; + } + + public void setStepId(Integer stepId) { + this.stepId = stepId; + } + + public String getParamName() { + return paramName; + } + + public void setParamName(String paramName) { + this.paramName = paramName; + } + + public String getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public IslandInfo getIslandInfo() { + return islandInfo; + } + + public void setIslandInfo(IslandInfo islandInfo) { + this.islandInfo = islandInfo; + } + + public StepInfo getStepInfo() { + return stepInfo; + } + + public void setStepInfo(StepInfo stepInfo) { + this.stepInfo = stepInfo; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java new file mode 100644 index 0000000..4b5462e --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ManageLog.java @@ -0,0 +1,65 @@ +package com.rczn.rcznautoplc.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; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java new file mode 100644 index 0000000..9091a67 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/ModbusConnectObj.java @@ -0,0 +1,85 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.github.s7connector.api.S7Connector; +import com.serotonin.modbus4j.ModbusMaster; + +public class ModbusConnectObj { + + /** + * ip地址 + */ + private String ipAddr; + + /** + * 端口号 + */ + private Integer port; + + /** + * 机架号 + */ + private Integer rack; + + /** + * 插槽 + */ + private Integer slot; + + /** + * 是否是主机 + */ + private Boolean host; + + + public ModbusConnectObj(String ipAddr, Integer port, Integer rack, Integer slot,Boolean host) { + this.ipAddr = ipAddr; + this.port = port; + this.rack = rack; + this.slot = slot; + this.host = host; + } + + public ModbusConnectObj() { + } + + 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 Integer getRack() { + return rack; + } + + public void setRack(Integer rack) { + this.rack = rack; + } + + public Integer getSlot() { + return slot; + } + + public void setSlot(Integer slot) { + this.slot = slot; + } + + public Boolean getHost() { + return host; + } + + public void setHost(Boolean host) { + this.host = host; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java new file mode 100644 index 0000000..48db0a6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/PlcConnectObj.java @@ -0,0 +1,84 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonBackReference; +import com.github.s7connector.api.S7Connector; + +public class PlcConnectObj { + + /** + * ip地址 + */ + private String ipAddr; + + /** + * 端口号 + */ + private Integer port; + + /** + * 机架号 + */ + private Integer rack; + + /** + * 插槽 + */ + private Integer slot; + + /** + * 连接对象 + */ + @JsonBackReference + private S7Connector connector; + + public PlcConnectObj(String ipAddr, Integer port, Integer rack, Integer slot, S7Connector connector) { + this.ipAddr = ipAddr; + this.port = port; + this.rack = rack; + this.slot = slot; + this.connector = connector; + } + + public PlcConnectObj() { + } + + 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 Integer getRack() { + return rack; + } + + public void setRack(Integer rack) { + this.rack = rack; + } + + public Integer getSlot() { + return slot; + } + + public void setSlot(Integer slot) { + this.slot = slot; + } + + public S7Connector getConnector() { + return connector; + } + + public void setConnector(S7Connector connector) { + this.connector = connector; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java new file mode 100644 index 0000000..043e333 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/RecordInfo.java @@ -0,0 +1,54 @@ +package com.rczn.rcznautoplc.domain; + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + +public class RecordInfo extends BaseBean { + private String recordName; + + private Integer recordType; // 1-设备异常,2-样品异常,3-操作异常 + + private Boolean recordStatus; // 0-未处理,1-已处理 + + private String recordContent; + + public RecordInfo() { + } + + public RecordInfo(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + public String getRecordName() { + return recordName; + } + + public void setRecordName(String recordName) { + this.recordName = recordName; + } + + public Integer getRecordType() { + return recordType; + } + + public void setRecordType(Integer recordType) { + this.recordType = recordType; + } + + public Boolean getRecordStatus() { + return recordStatus; + } + + public void setRecordStatus(Boolean recordStatus) { + this.recordStatus = recordStatus; + } + + public String getRecordContent() { + return recordContent; + } + + public void setRecordContent(String recordContent) { + this.recordContent = recordContent; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/StepInfo.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/StepInfo.java new file mode 100644 index 0000000..7bb77e8 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/StepInfo.java @@ -0,0 +1,133 @@ +package com.rczn.rcznautoplc.domain; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public class StepInfo extends BaseBean { + private Integer islandId; + + //设备id + private Integer devId; + private Integer flowId; + + private String paramName; + private String paramType; + private String paramUnit; + private String paramValue; + private String formType; + + private Integer stepOrder; + private String stepName; + + private String stepDesc; + + @JsonIgnore + private IslandInfo islandInfo; + + public StepInfo() { + } + + public StepInfo(Long id, Long createId, LocalDateTime createTime, Long updateId, LocalDateTime updateTime, boolean delSign, String remark) { + super(id, createId, createTime, updateId, updateTime, delSign, remark); + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + 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 getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getStepOrder() { + return stepOrder; + } + + public void setStepOrder(Integer stepOrder) { + this.stepOrder = stepOrder; + } + + public String getStepName() { + return stepName; + } + + public void setStepName(String stepName) { + this.stepName = stepName; + } + + public String getStepDesc() { + return stepDesc; + } + + public void setStepDesc(String stepDesc) { + this.stepDesc = stepDesc; + } + + public IslandInfo getIslandInfo() { + return islandInfo; + } + + public void setIslandInfo(IslandInfo islandInfo) { + this.islandInfo = islandInfo; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java new file mode 100644 index 0000000..2b67731 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/UserBusy.java @@ -0,0 +1,111 @@ +package com.rczn.rcznautoplc.domain; + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + +public class UserBusy extends BaseBean { + + private Long id; + private String userName; + + private String password; + + private String salt; + + private String nicke; + + private Boolean sex; // 0-女, 1-男 + + private String emailAddr; + + private String address; + + + public UserBusy() { + } + + public UserBusy(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 + '\'' + + '}'; + } + + @Override + public Long getId() { + return id; + } + + @Override + public void setId(Long id) { + this.id = id; + } + + 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; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java new file mode 100644 index 0000000..aa74bc1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevInfoQuery.java @@ -0,0 +1,122 @@ +package com.rczn.rcznautoplc.domain.query; + +public class DevInfoQuery { + + //功能岛外键 + private Integer islandId; + + //设备名称 + private String devName; + + //设备型号 + private String devModel; + + //plc映射地址 + private Integer plcAddr; + + //设备IP地址 + private String ipAddr; + + private Integer port; + + private String protocolType; + + private String company; + + private Integer status; // 0-空闲,1-运行,4-故障 + + private Integer runModel;//0-手动模式,1-自动模式 + + private String devDesc; + + public DevInfoQuery() { + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + 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 Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + 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 Integer getRunModel() { + return runModel; + } + + public void setRunModel(Integer runModel) { + this.runModel = runModel; + } + + public String getDevDesc() { + return devDesc; + } + + public void setDevDesc(String devDesc) { + this.devDesc = devDesc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java new file mode 100644 index 0000000..a1b4e14 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/DevParamQuery.java @@ -0,0 +1,87 @@ +package com.rczn.rcznautoplc.domain.query; + +public class DevParamQuery { + private String devIds; + + private Integer devId; + + private String paramName; + + private String paramValue; + + private String paramTypeData; + + private String paramUnit; + + private String formType; + + private String paramDesc; + + public DevParamQuery() { + } + + public Integer getDevId() { + return devId; + } + + public void setDevId(Integer devId) { + this.devId = devId; + } + + public String getDevIds() { + return devIds; + } + + public void setDevIds(String devIds) { + this.devIds = devIds; + } + + 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 getParamTypeData() { + return paramTypeData; + } + + public void setParamTypeData(String paramTypeData) { + this.paramTypeData = paramTypeData; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public String getParamDesc() { + return paramDesc; + } + + public void setParamDesc(String paramDesc) { + this.paramDesc = paramDesc; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java new file mode 100644 index 0000000..7e667d7 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsFlowStatusQuery.java @@ -0,0 +1,75 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.rczn.domain.BaseBean; +import com.rczn.rcznautoplc.domain.FlowInfo; +import com.rczn.rcznautoplc.domain.IslandInfo; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +public class GoodsFlowStatusQuery { + private Integer goodsId; + + private Integer flowId; + + private Integer islandId; + + private Integer devId; + + private Integer flowSort; + + private Integer status; // 0-未执行,1-执行,10-通过,11-失败 + + public GoodsFlowStatusQuery() { + } + + + 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 getDevId() { + return devId; + } + + public void setDevId(Integer devId) { + this.devId = devId; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java new file mode 100644 index 0000000..cc523d1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/GoodsInfoQuery.java @@ -0,0 +1,125 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.rczn.domain.BaseBean; + +import java.time.LocalDateTime; + + +public class GoodsInfoQuery extends BaseBean{ + private String goodsName; + + private String goodsType; + + private LocalDateTime incomeTime; + + private String goodFrom; + + private Integer goodBatch; + + private Integer pointNum; + + //目标监测物 + private String goalDetect; + + //条码 + private String barCode; + + //国标id + private Integer flowId; + + private Integer goodsStatus; + + private String desc; + + public GoodsInfoQuery() { + } + + + public String getGoodsName() { + return goodsName; + } + + public void setGoodsName(String goodsName) { + this.goodsName = goodsName; + } + + public String getGoodsType() { + return goodsType; + } + + public void setGoodsType(String goodsType) { + this.goodsType = goodsType; + } + + public LocalDateTime getIncomeTime() { + return incomeTime; + } + + public void setIncomeTime(LocalDateTime incomeTime) { + this.incomeTime = incomeTime; + } + + public String getGoodFrom() { + return goodFrom; + } + + public void setGoodFrom(String goodFrom) { + this.goodFrom = goodFrom; + } + + public Integer getGoodBatch() { + return goodBatch; + } + + public void setGoodBatch(Integer goodBatch) { + this.goodBatch = goodBatch; + } + + public Integer getPointNum() { + return pointNum; + } + + public void setPointNum(Integer pointNum) { + this.pointNum = pointNum; + } + + public String getGoalDetect() { + return goalDetect; + } + + public void setGoalDetect(String goalDetect) { + this.goalDetect = goalDetect; + } + + public String getBarCode() { + return barCode; + } + + public void setBarCode(String barCode) { + this.barCode = barCode; + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + public Integer getGoodsStatus() { + return goodsStatus; + } + + public void setGoodsStatus(Integer goodsStatus) { + this.goodsStatus = goodsStatus; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java new file mode 100644 index 0000000..34d9e1b --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandInfoQuery.java @@ -0,0 +1,60 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.rczn.domain.BaseBean; + + +public class IslandInfoQuery { + private String islandName; + + private String islandCode; + + //plc映射地址 + private Integer plcAddr; + + private String islandLogo; + + private String desc; + + public IslandInfoQuery() { + } + + public String getIslandName() { + return islandName; + } + + public void setIslandName(String islandName) { + this.islandName = islandName; + } + + public String getIslandCode() { + return islandCode; + } + + public void setIslandCode(String islandCode) { + this.islandCode = islandCode; + } + + public Integer getPlcAddr() { + return plcAddr; + } + + public void setPlcAddr(Integer plcAddr) { + this.plcAddr = plcAddr; + } + + public String getIslandLogo() { + return islandLogo; + } + + public void setIslandLogo(String islandLogo) { + this.islandLogo = islandLogo; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java new file mode 100644 index 0000000..6920b16 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/IslandParamQuery.java @@ -0,0 +1,84 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import com.rczn.rcznautoplc.domain.IslandInfo; + +import java.time.LocalDateTime; + +public class IslandParamQuery { + private Integer islandId; + + private Integer stepId; + + private String paramName; + + private String paramType; + + private String paramUnit; + + private String paramValue; + + private String formType; + + public IslandParamQuery() { + } + + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getStepId() { + return stepId; + } + + public void setStepId(Integer stepId) { + this.stepId = stepId; + } + + public String getParamName() { + return paramName; + } + + public void setParamName(String paramName) { + this.paramName = paramName; + } + + public String getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java new file mode 100644 index 0000000..164dcba --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/domain/query/StepInfoQuery.java @@ -0,0 +1,118 @@ +package com.rczn.rcznautoplc.domain.query; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.rczn.domain.BaseBean; +import com.rczn.rcznautoplc.domain.IslandInfo; + +import java.time.LocalDateTime; + +public class StepInfoQuery { + private Integer islandId; + + //设备id + private Integer devId; + private Integer flowId; + + private String paramName; + private String paramType; + private String paramUnit; + private String paramValue; + private String formType; + + private Integer stepOrder; + private String stepName; + + private String stepDesc; + + public StepInfoQuery() { + } + + public Integer getFlowId() { + return flowId; + } + + public void setFlowId(Integer flowId) { + this.flowId = flowId; + } + + 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 getParamType() { + return paramType; + } + + public void setParamType(String paramType) { + this.paramType = paramType; + } + + public String getParamUnit() { + return paramUnit; + } + + public void setParamUnit(String paramUnit) { + this.paramUnit = paramUnit; + } + + public String getParamValue() { + return paramValue; + } + + public void setParamValue(String paramValue) { + this.paramValue = paramValue; + } + + public String getFormType() { + return formType; + } + + public void setFormType(String formType) { + this.formType = formType; + } + + public Integer getIslandId() { + return islandId; + } + + public void setIslandId(Integer islandId) { + this.islandId = islandId; + } + + public Integer getStepOrder() { + return stepOrder; + } + + public void setStepOrder(Integer stepOrder) { + this.stepOrder = stepOrder; + } + + public String getStepName() { + return stepName; + } + + public void setStepName(String stepName) { + this.stepName = stepName; + } + + public String getStepDesc() { + return stepDesc; + } + + public void setStepDesc(String stepDesc) { + this.stepDesc = stepDesc; + } + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/DevInfoMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/DevInfoMapper.java new file mode 100644 index 0000000..1658eae --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/DevInfoMapper.java @@ -0,0 +1,37 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.DevInfo; +import com.rczn.rcznautoplc.domain.query.DevInfoQuery; +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 selectList(DevInfoQuery devInfo); + // 分页查询设备(支持多条件过滤) + List selectPage(DevInfo devInfo); + + // 查询符合条件的设备总数(用于分页) + int selectTotal(DevInfo devInfo); + + // 查询所有未删除的设备(用于下拉选择等场景) + List selectAll(); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/DevParamMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/DevParamMapper.java new file mode 100644 index 0000000..1b3f0a4 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/DevParamMapper.java @@ -0,0 +1,40 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.DevParam; +import com.rczn.rcznautoplc.domain.query.DevParamQuery; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface DevParamMapper { + /** + * 新增设备参数 + */ + Long insert(DevParam devParam); + + /** + * 根据ID更新设备参数 + */ + Boolean update(DevParam devParam); + + /** + * 逻辑删除设备参数 + */ + Boolean deleteById(@Param("id") Long id); + + /** + * 根据ID查询设备参数 + */ + DevParam selectById(@Param("id") Long id); + + /** + * 分页查询设备参数(支持条件过滤) + */ + List selectPage(DevParamQuery devParam); + + Boolean addDevId(@Param("devId") Integer devId,@Param("paramId") Integer paramId); + + Boolean delDevId(@Param("devId")Integer devId,@Param("paramId") Integer paramId); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/FlowInfoMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/FlowInfoMapper.java new file mode 100644 index 0000000..b62a2bb --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/FlowInfoMapper.java @@ -0,0 +1,16 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.FlowInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface FlowInfoMapper { + Long insert(FlowInfo flowInfo); + Boolean update(FlowInfo flowInfo); + Boolean deleteById(@Param("id") Long id); + FlowInfo selectById(@Param("id") Long id); + List selectPage(FlowInfo flowInfo); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/GoodsFlowStatusMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/GoodsFlowStatusMapper.java new file mode 100644 index 0000000..782e23b --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/GoodsFlowStatusMapper.java @@ -0,0 +1,17 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.query.GoodsFlowStatusQuery; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface GoodsFlowStatusMapper { + Long insert(GoodsFlowStatus goodsFlowStatus); + Boolean update(GoodsFlowStatus goodsFlowStatus); + Boolean deleteById(@Param("id") Long id); + GoodsFlowStatus selectById(@Param("id") Long id); + List selectPage(GoodsFlowStatusQuery goodsFlowStatus); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/GoodsInfoMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/GoodsInfoMapper.java new file mode 100644 index 0000000..b0d3325 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/GoodsInfoMapper.java @@ -0,0 +1,25 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface GoodsInfoMapper { + Long insert(GoodsInfo goodsInfo); + + //批量插入样品数据: +// Long batchInsert(List goodsInfoList); + Boolean update(GoodsInfo goodsInfo); + Boolean deleteById(@Param("id") Long id); + + GoodsInfo selectById(@Param("id") Long id); + + List selectByIdList(@Param("idList") List idList); + + GoodsInfo selectByBarCode(@Param("barCode") String barCode); + List selectPage(GoodsInfoQuery goodsInfo); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/IslandInfoMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/IslandInfoMapper.java new file mode 100644 index 0000000..9cc0daa --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/IslandInfoMapper.java @@ -0,0 +1,22 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.IslandInfo; +import com.rczn.rcznautoplc.domain.query.IslandInfoQuery; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface IslandInfoMapper { + Long insert(IslandInfo islandInfo); + Boolean update(IslandInfo islandInfo); + Boolean deleteById(@Param("id") Long id); + IslandInfo selectById(@Param("id") Long id); + + /** + * 查询功能岛信息List + */ + List selectList(IslandInfoQuery islandInfoQuery); + List selectPage(IslandInfo islandInfo); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/IslandParamMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/IslandParamMapper.java new file mode 100644 index 0000000..65a97e1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/IslandParamMapper.java @@ -0,0 +1,40 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.IslandParam; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface IslandParamMapper { + /** + * 新增岛屿参数(返回自增ID) + */ + Long insert(IslandParam islandParam); + + /** + * 根据ID更新岛屿参数(非空字段才更新) + */ + Boolean update(IslandParam islandParam); + + /** + * 逻辑删除岛屿参数(设置delSign=1) + */ + Boolean deleteById(@Param("id") Long id); + + /** + * 根据ID查询岛屿参数(关联查询岛屿信息和步骤信息) + */ + IslandParam selectById(@Param("id") Long id); + + /** + * 分页查询岛屿参数(支持条件过滤,不关联查询关联对象) + */ + List selectPage(IslandParam islandParam); + + /** + * 分页查询岛屿参数(关联查询岛屿信息和步骤信息,支持条件过滤) + */ + List selectPageWithRelations(IslandParam islandParam); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java new file mode 100644 index 0000000..1300631 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/ManageLogMapper.java @@ -0,0 +1,27 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.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 selectPage(ManageLog manageLog); + + // 查询分页总数(与分页查询条件一致) + Long selectTotal(ManageLog manageLog); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/RecordInfoMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/RecordInfoMapper.java new file mode 100644 index 0000000..7bd2f59 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/RecordInfoMapper.java @@ -0,0 +1,16 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.RecordInfo; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface RecordInfoMapper { + Long insert(RecordInfo recordInfo); + Boolean update(RecordInfo recordInfo); + Boolean deleteById(@Param("id") Long id); + RecordInfo selectById(@Param("id") Long id); + List selectPage(RecordInfo recordInfo); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/StepInfoMapper.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/StepInfoMapper.java new file mode 100644 index 0000000..195c072 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/mapper/StepInfoMapper.java @@ -0,0 +1,24 @@ +package com.rczn.rcznautoplc.mapper; + +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.domain.query.StepInfoQuery; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface StepInfoMapper { + Long insert(StepInfo stepInfo); + Boolean update(StepInfo stepInfo); + Boolean deleteById(@Param("id") Long id); + + Long deleteBatchByIds(List ids); + StepInfo selectById(@Param("id") Long id); + List selectList(StepInfo stepInfo); + List selectPage(StepInfoQuery stepInfo); + + Long insertBatch(List stepInfoList); + + Long updateBatch(List stepInfoList); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/DevInfoService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/DevInfoService.java new file mode 100644 index 0000000..d6f9b79 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/DevInfoService.java @@ -0,0 +1,39 @@ +package com.rczn.rcznautoplc.service; + +import com.rczn.rcznautoplc.domain.DevInfo; +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.query.DevInfoQuery; + +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); + + //根据设备信息查询设备列表数据 + +/** + * Retrieves a list of device information based on the provided query parameters. + * + * @param devInfo The query parameters used to filter device information + * @return List A list of device information objects that match the query criteria + */ + List getDevInfoList(DevInfoQuery devInfo); + // 分页查询设备 + PageInfo getDevInfoPage(DevInfo devInfo, Integer pageNum, Integer pageSize); + + // 查询所有设备 + List getAllDevInfo(); +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/DevParamService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/DevParamService.java new file mode 100644 index 0000000..dd21971 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/DevParamService.java @@ -0,0 +1,47 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.DevParam; +import com.rczn.rcznautoplc.domain.query.DevParamQuery; + +import java.util.List; + +public interface DevParamService { + /** + * 分页查询 + */ + PageInfo selectPage(Integer pageNum, Integer pageSize, Integer devId,String paramTypeData, String paramName, String paramValue); + + List selectList(DevParamQuery queryParam); + + /** + * 根据ID查询 + */ + DevParam selectById(Long id); + + /** + * 新增 + */ + Long insert(DevParam devParam); + + /** + * 修改 + */ + Boolean update(DevParam devParam); + + /** + * 为参数增加devId值 + */ + Boolean addDevId(Integer devId, Integer paramId); + + /** + * 根据paramId,减少devIds中的devId + */ + Boolean reduceDevId(Integer devId, Integer paramId); + + /** + * 逻辑删除 + */ + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/FlowInfoService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/FlowInfoService.java new file mode 100644 index 0000000..b6c65dc --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/FlowInfoService.java @@ -0,0 +1,16 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.FlowInfo; + +import java.util.List; + +public interface FlowInfoService { + PageInfo selectPage(Integer pageNum, Integer pageSize, Integer flowIndex, String flowName, String islandIdList); + List selectList( Integer flowIndex, String flowName, String islandIdList); + FlowInfo selectById(Long id); + Long insert(FlowInfo flowInfo); + Boolean update(FlowInfo flowInfo); + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/GoodsFlowStatusService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/GoodsFlowStatusService.java new file mode 100644 index 0000000..26021b0 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/GoodsFlowStatusService.java @@ -0,0 +1,17 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.query.GoodsFlowStatusQuery; + +import java.util.List; + +public interface GoodsFlowStatusService { + PageInfo selectPage(Integer pageNum, Integer pageSize, GoodsFlowStatusQuery goodsFlowStatus); + List selectList( GoodsFlowStatusQuery goodsFlowStatus); + GoodsFlowStatus selectById(Long id); + Long insert(GoodsFlowStatus goodsFlowStatus); + Boolean update(GoodsFlowStatus goodsFlowStatus); + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/GoodsInfoService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/GoodsInfoService.java new file mode 100644 index 0000000..5ec4a54 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/GoodsInfoService.java @@ -0,0 +1,49 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; + +import java.util.List; + +public interface GoodsInfoService { + /** + * 分页查询货物信息 + */ + PageInfo selectPage(Integer pageNum, Integer pageSize, GoodsInfoQuery goodsInfo); + + /** + * 查询样品信息List + */ + List selectList(GoodsInfoQuery goodsInfo); + + /** + * 根据ID查询货物信息 + */ + GoodsInfo selectById(Long id); + + /** + * 根据ID列表查询货物列表信息 + */ + List selectByIdList(List ids); + + /** + * 新增货物信息 + */ + Long insert(GoodsInfo goodsInfo); + + /** + * 扫码新增货物信息 + */ + GoodsInfo insertByScan(GoodsInfo goodsInfo); + + /** + * 修改货物信息 + */ + Boolean update(GoodsInfo goodsInfo); + + /** + * 逻辑删除货物信息 + */ + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/IslandInfoService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/IslandInfoService.java new file mode 100644 index 0000000..7848ddd --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/IslandInfoService.java @@ -0,0 +1,24 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.IslandInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; +import com.rczn.rcznautoplc.domain.query.IslandInfoQuery; + +import java.util.List; + +public interface IslandInfoService { + PageInfo selectPage(Integer pageNum, Integer pageSize, String islandName, String islandCode); + IslandInfo selectById(Long id); + + /** + * 查询功能岛信息List + */ + List selectList(IslandInfoQuery islandInfoQuery); + + Long insert(IslandInfo islandInfo); + Boolean update(IslandInfo islandInfo); + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/IslandParamService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/IslandParamService.java new file mode 100644 index 0000000..8b6d031 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/IslandParamService.java @@ -0,0 +1,13 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.IslandParam; + +public interface IslandParamService { + PageInfo selectPage(Integer pageNum, Integer pageSize, Integer islandId, Integer stepId, String paramName, String paramType); + IslandParam selectById(Long id); + Long insert(IslandParam islandParam); + Boolean update(IslandParam islandParam); + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java new file mode 100644 index 0000000..7302508 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/ManageLogService.java @@ -0,0 +1,21 @@ +package com.rczn.rcznautoplc.service; + +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.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 selectPage(Integer pageNum, Integer pageSize, ManageLog manageLog); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java new file mode 100644 index 0000000..e6d1bde --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/PlcService.java @@ -0,0 +1,125 @@ +package com.rczn.rcznautoplc.service; + +import com.github.s7connector.api.S7Connector; +import com.rczn.rcznautoplc.domain.ModbusConnectObj; +import com.rczn.rcznautoplc.domain.PlcConnectObj; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; + +import java.util.List; +import java.util.Map; + +public interface PlcService { + /** + * 连接plc设备 + * @param connectObj- + * @return + */ + PlcConnectObj connect(PlcConnectObj connectObj); + + /** + * 连接modbus设备 + * @param connectObj- + * @return + */ + ModbusMaster connectModbus(ModbusConnectObj connectObj) throws ModbusInitException, ModbusTransportException; + + /** + * 启动plc设备 + * @param ipAddr- + * @return + */ + Boolean startPlc(String ipAddr); + + /** + * plc设备暂停运行 + * @param ipAddr- + * @return + */ + Boolean pausePlc(String ipAddr); + + /** + * plc设备故障复位 + * @param ipAddr- + * @return + */ + Boolean resetErrorPlc(String ipAddr); + + /** + * 根据ip地址获取plc设备状态值 + * 0-未连接,1-连接,11-执行,12-暂停,19暂停,20-故障复位 + * @param ipAddr + * @return + */ + Integer getPlcStatus(String ipAddr); + + /** + * 根据ip地址设置plc设备模式 + * 0-手动,1-自动 + * @param ipAddr + * @return + */ + Boolean setPlcModel(String ipAddr,Integer modelValue); + + /** + * 根据ip地址获取plc设备模式值 + * 0-手动,1-自动 + * @param ipAddr + * @return + */ + Integer getPlcModel(String ipAddr); + + /** + * 根据ip地址获取modbus连接设备 + * + * @param ipAddr + * @return + */ + public ModbusMaster getModbusConnect(String ipAddr); + + /** + * 根据ip地址获取plc设备 + * @param ipAddr + * @return + */ + S7Connector getPlc(String ipAddr); + + /** + * 获取全部plc连接对象 + * @return + */ + Map plcALlMap(); + + /** + * 获取全部plc连接对象 + * + * @return + */ + public Map modbusALlMap(); + /** + * 执行plc动作 + * @param ipAddr + * @param action + * @return + */ + Boolean doAction(String ipAddr,String action); + + /** + * 停止plc运行: + * @param ipAddr + * @return + */ + Boolean stopPlc(String ipAddr); + + /** + * 执行sop信息 + * @param sopId + * @param barCodeList + * @param stepInfoList + * @return + */ + Boolean runSopInfoForGoodsList(String plcIp, Integer sopId, List barCodeList,List stepInfoList); +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/RecordInfoService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/RecordInfoService.java new file mode 100644 index 0000000..b427cf9 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/RecordInfoService.java @@ -0,0 +1,12 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.RecordInfo; + +public interface RecordInfoService { + PageInfo selectPage(Integer pageNum, Integer pageSize, String recordName, Integer recordType, Boolean recordStatus); + RecordInfo selectById(Long id); + Long insert(RecordInfo recordInfo); + Boolean update(RecordInfo recordInfo); + Boolean deleteById(Long id); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/StepInfoService.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/StepInfoService.java new file mode 100644 index 0000000..873d46e --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/StepInfoService.java @@ -0,0 +1,33 @@ +package com.rczn.rcznautoplc.service; + +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.domain.query.StepInfoQuery; + +import java.util.List; + +public interface StepInfoService { + PageInfo selectPage(Integer pageNum, Integer pageSize, StepInfoQuery stepInfo); + List selectList( StepInfoQuery stepInfo); + StepInfo selectById(Long id); + Long insert(StepInfo stepInfo); + + Long insertBatch(List stepInfoList); + Boolean update(StepInfo stepInfo); + + /** + * 批量更新 + * @param stepInfoList + * @return + */ + Long updateBatch(List stepInfoList); + Boolean deleteById(Long id); + + /** + * 批量删除 + * @param ids + * @return + * @throws Exception + */ + Long deleteBatchByIds(List ids); +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/DevInfoServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/DevInfoServiceImpl.java new file mode 100644 index 0000000..97d3bfa --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/DevInfoServiceImpl.java @@ -0,0 +1,118 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.rczn.rcznautoplc.domain.DevInfo; +import com.rczn.rcznautoplc.domain.query.DevInfoQuery; +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()); + } + //判断设备是否是PLC,PLC设备只有一个主PLC:company-主站 + if(devInfo.getDevModel().equals("PLC")&&devInfo.getCompany().equals("主站")){ + //查询出devModel为PLC,company为“主站”的设备 + DevInfoQuery devInfo1 = new DevInfoQuery(); + devInfo1.setDevModel("PLC"); + devInfo1.setCompany("主站"); + List devInfoList = devInfoMapper.selectList(devInfo1); + if(devInfoList.size()>0){ + //如果存在,报错抛出异常 + throw new RuntimeException("主站PLC设备只能有一个"); + } + } + // 调用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()); + } + + //判断设备是否是PLC,PLC设备只有一个主PLC:company-主站 + if(devInfo.getDevModel().equals("PLC")&&devInfo.getCompany().equals("主站")){ + //查询出devModel为PLC,company为“主站”的设备 + DevInfoQuery devInfo1 = new DevInfoQuery(); + devInfo1.setDevModel("PLC"); + devInfo1.setCompany("主站"); + List devInfoList = devInfoMapper.selectList(devInfo1); + if(devInfoList.size()>0){ + for (DevInfo devInfo2 : devInfoList) + if(devInfo2.getId().equals(devInfo.getId())) + continue; + else { + //如果存在,报错抛出异常 + throw new RuntimeException("主站PLC设备只能有一个"); + } + + } + } + // 调用Mapper更新 + return devInfoMapper.updateById(devInfo) > 0; + } + + @Override + public DevInfo getDevInfoById(Long id) { + Assert.notNull(id, "设备ID不能为空"); + return devInfoMapper.selectById(id); + } + + @Override + public List getDevInfoList(DevInfoQuery devInfo) { + return devInfoMapper.selectList(devInfo); + } + + @Override + public PageInfo getDevInfoPage(DevInfo devInfo, Integer pageNum, Integer pageSize) { + // 分页参数默认值 + if (pageNum == null) pageNum = 1; + if (pageSize == null) pageSize = 10; + // PageHelper开启分页 + PageHelper.startPage(pageNum, pageSize); + // 查询数据 + List devInfoList = devInfoMapper.selectPage(devInfo); + // 封装分页结果 + return new PageInfo<>(devInfoList); + } + + @Override + public List getAllDevInfo() { + return devInfoMapper.selectAll(); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/DevParamServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/DevParamServiceImpl.java new file mode 100644 index 0000000..2e07fdd --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/DevParamServiceImpl.java @@ -0,0 +1,107 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.DevParam; +import com.rczn.rcznautoplc.domain.query.DevParamQuery; +import com.rczn.rcznautoplc.mapper.DevParamMapper; +import com.rczn.rcznautoplc.service.DevParamService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class DevParamServiceImpl implements DevParamService { + + @Autowired + DevParamMapper devParamMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, Integer devId, String paramTypeData, String paramName, String paramValue) { + // 1. 开启分页 + PageHelper.startPage(pageNum, pageSize); + // 2. 构建查询条件 + DevParamQuery queryParam = new DevParamQuery(); + queryParam.setDevId(devId); + queryParam.setParamTypeData(paramTypeData); + queryParam.setParamName(paramName); + queryParam.setParamValue(paramValue); + // 3. 执行查询 + List list = devParamMapper.selectPage(queryParam); + // 4. 包装分页结果 + return new PageInfo<>(list); + } + + /** + * 根据条件查询设备参数列表 + * @param devId + * @param paramName + * @param paramValue + * @return + */ + @Override + public List selectList(DevParamQuery queryParam) { + // 3. 执行查询 + List list = devParamMapper.selectPage(queryParam); + return list; + } + + @Override + public DevParam selectById(Long id) { + if (id == null) { + throw new IllegalArgumentException("ID不能为空"); + } + return devParamMapper.selectById(id); + } + + @Override + public Long insert(DevParam devParam) { + if (devParam.getDevIds() == null) { + devParam.setDevIds(";"); + } + if (devParam.getParamName() == null || devParam.getParamName().isEmpty()) { + throw new IllegalArgumentException("参数名称不能为空"); + } + return devParamMapper.insert(devParam); + } + + @Override + public Boolean update(DevParam devParam) { + if (devParam.getId() == null) { + throw new IllegalArgumentException("ID不能为空"); + } + return devParamMapper.update(devParam); + } + + /** + * 为参数增加devId值 + * + * @param devId + * @param paramId + */ + @Override + public Boolean addDevId(Integer devId, Integer paramId) { + return devParamMapper.addDevId(devId, paramId); + } + + /** + * 根据paramId,减少devIds中的devId + * + * @param devId + * @param paramId + */ + @Override + public Boolean reduceDevId(Integer devId, Integer paramId) { + return devParamMapper.delDevId(devId, paramId); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) { + throw new IllegalArgumentException("ID不能为空"); + } + return devParamMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/FlowInfoServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/FlowInfoServiceImpl.java new file mode 100644 index 0000000..ca403ea --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/FlowInfoServiceImpl.java @@ -0,0 +1,74 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.FlowInfo; +import com.rczn.rcznautoplc.mapper.FlowInfoMapper; +import com.rczn.rcznautoplc.service.FlowInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class FlowInfoServiceImpl implements FlowInfoService { + + @Autowired + FlowInfoMapper flowInfoMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, Integer flowIndex, String flowName, String islandIdList) { + PageHelper.startPage(pageNum, pageSize); + FlowInfo queryParam = new FlowInfo(); + queryParam.setFlowIndex(flowIndex); + queryParam.setFlowName(flowName); + queryParam.setIslandIdList(islandIdList); + List list = flowInfoMapper.selectPage(queryParam); + return new PageInfo<>(list); + } + + /** + * 查询列表g根据国标流程 + * @param flowIndex + * @param flowName + * @param islandIdList + * @return + */ + @Override + public List selectList(Integer flowIndex, String flowName, String islandIdList) { + FlowInfo queryParam = new FlowInfo(); + queryParam.setFlowIndex(flowIndex); + queryParam.setFlowName(flowName); + queryParam.setIslandIdList(islandIdList); + List list = flowInfoMapper.selectPage(queryParam); + return list; + } + + @Override + public FlowInfo selectById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return flowInfoMapper.selectById(id); + } + + @Override + public Long insert(FlowInfo flowInfo) { + if (flowInfo.getFlowName() == null || flowInfo.getFlowName().isEmpty()) { + throw new IllegalArgumentException("流程名称不能为空"); + } + Long result = flowInfoMapper.insert(flowInfo); + return flowInfo.getId(); + } + + @Override + public Boolean update(FlowInfo flowInfo) { + if (flowInfo.getId() == null) throw new IllegalArgumentException("ID不能为空"); + return flowInfoMapper.update(flowInfo); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return flowInfoMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/GoodsFlowStatusServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/GoodsFlowStatusServiceImpl.java new file mode 100644 index 0000000..501403c --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/GoodsFlowStatusServiceImpl.java @@ -0,0 +1,60 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.query.GoodsFlowStatusQuery; +import com.rczn.rcznautoplc.mapper.GoodsFlowStatusMapper; +import com.rczn.rcznautoplc.service.GoodsFlowStatusService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class GoodsFlowStatusServiceImpl implements GoodsFlowStatusService { + + @Autowired + GoodsFlowStatusMapper goodsFlowStatusMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, GoodsFlowStatusQuery goodsFlowStatus){ + PageHelper.startPage(pageNum, pageSize); + + List list = goodsFlowStatusMapper.selectPage(goodsFlowStatus); + return new PageInfo<>(list); + } + + @Override + public List selectList(GoodsFlowStatusQuery goodsFlowStatus) { + List list = goodsFlowStatusMapper.selectPage(goodsFlowStatus); + return list; + } + + @Override + public GoodsFlowStatus selectById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return goodsFlowStatusMapper.selectById(id); + } + + @Override + public Long insert(GoodsFlowStatus goodsFlowStatus) { + if (goodsFlowStatus.getGoodsId() == null) throw new IllegalArgumentException("货物ID不能为空"); + if (goodsFlowStatus.getFlowId() == null) throw new IllegalArgumentException("流程ID不能为空"); + if (goodsFlowStatus.getStatus() == null) throw new IllegalArgumentException("状态不能为空(0-未执行,1-执行,10-通过,11-失败)"); + return goodsFlowStatusMapper.insert(goodsFlowStatus); + } + + @Override + public Boolean update(GoodsFlowStatus goodsFlowStatus) { + if (goodsFlowStatus.getId() == null) throw new IllegalArgumentException("ID不能为空"); + return goodsFlowStatusMapper.update(goodsFlowStatus); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return goodsFlowStatusMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/GoodsInfoServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/GoodsInfoServiceImpl.java new file mode 100644 index 0000000..2e903d4 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/GoodsInfoServiceImpl.java @@ -0,0 +1,121 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; +import com.rczn.rcznautoplc.mapper.GoodsInfoMapper; +import com.rczn.rcznautoplc.service.GoodsInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class GoodsInfoServiceImpl implements GoodsInfoService { + + @Autowired + GoodsInfoMapper goodsInfoMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, GoodsInfoQuery goodsInfo) { + // 开启分页 + PageHelper.startPage(pageNum, pageSize); + + // 执行查询 + List list = goodsInfoMapper.selectPage(goodsInfo); + // 包装分页结果 + return new PageInfo<>(list); + } + + /** + * 查询样品信息 + * + * @param goodsInfo + */ + @Override + public List selectList(GoodsInfoQuery goodsInfo) { + // 执行查询 + List list = goodsInfoMapper.selectPage(goodsInfo); + // 包装分页结果 + return list; + } + + @Override + public GoodsInfo selectById(Long id) { + if (id == null) { + throw new IllegalArgumentException("ID不能为空"); + } + return goodsInfoMapper.selectById(id); + } + + /** + * 根据ID列表查询货物列表信息 + * + * @param ids + */ + @Override + public List selectByIdList(List ids) { + return goodsInfoMapper.selectByIdList(ids); + } + + @Override + public Long insert(GoodsInfo goodsInfo) { + if (goodsInfo.getGoodsName() == null || goodsInfo.getGoodsName().isEmpty()) { + throw new IllegalArgumentException("货物名称不能为空"); + } + if (goodsInfo.getGoodsType() == null || goodsInfo.getGoodsType().isEmpty()) { + throw new IllegalArgumentException("货物类型不能为空"); + } + if (goodsInfo.getIncomeTime() == null) { + throw new IllegalArgumentException("入库时间不能为空"); + } + return goodsInfoMapper.insert(goodsInfo); + } + + /** + * 扫码新增货物信息 + * + * @param goodsInfo + */ + @Override + public GoodsInfo insertByScan(GoodsInfo goodsInfo) { + //根据业务扫码录入样品信息有:样品编码,样品类型,样品名称,样品录入时间,点位号 + + //根据样品编码查询数据库样品信息 + GoodsInfo goodsInfo1 = goodsInfoMapper.selectByBarCode(goodsInfo.getBarCode()); + + if(goodsInfo1 != null){ + return goodsInfo1; + } + + if (goodsInfo.getGoodsName() == null || goodsInfo.getGoodsName().isEmpty()) { + throw new IllegalArgumentException("货物名称不能为空"); + } + if (goodsInfo.getGoodsType() == null || goodsInfo.getGoodsType().isEmpty()) { + throw new IllegalArgumentException("货物类型不能为空"); + } + if (goodsInfo.getIncomeTime() == null) { + throw new IllegalArgumentException("入库时间不能为空"); + } + goodsInfoMapper.insert(goodsInfo); + return goodsInfo; + } + + @Override + public Boolean update(GoodsInfo goodsInfo) { + if (goodsInfo.getId() == null) { + throw new IllegalArgumentException("ID不能为空"); + } + return goodsInfoMapper.update(goodsInfo); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) { + throw new IllegalArgumentException("ID不能为空"); + } + return goodsInfoMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/IslandInfoServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/IslandInfoServiceImpl.java new file mode 100644 index 0000000..dd4dd08 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/IslandInfoServiceImpl.java @@ -0,0 +1,68 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.IslandInfo; +import com.rczn.rcznautoplc.domain.query.IslandInfoQuery; +import com.rczn.rcznautoplc.mapper.IslandInfoMapper; +import com.rczn.rcznautoplc.service.IslandInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class IslandInfoServiceImpl implements IslandInfoService { + + @Autowired + IslandInfoMapper islandInfoMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, String islandName, String islandCode) { + PageHelper.startPage(pageNum, pageSize); + IslandInfo queryParam = new IslandInfo(); + queryParam.setIslandName(islandName); + queryParam.setIslandCode(islandCode); + List list = islandInfoMapper.selectPage(queryParam); + return new PageInfo<>(list); + } + + @Override + public IslandInfo selectById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return islandInfoMapper.selectById(id); + } + + /** + * 查询功能岛信息List + * + * @param islandInfoQuery + */ + @Override + public List selectList(IslandInfoQuery islandInfoQuery) { + return islandInfoMapper.selectList(islandInfoQuery); + } + + @Override + public Long insert(IslandInfo islandInfo) { + if (islandInfo.getIslandName() == null || islandInfo.getIslandName().isEmpty()) { + throw new IllegalArgumentException("岛屿名称不能为空"); + } + if (islandInfo.getIslandCode() == null || islandInfo.getIslandCode().isEmpty()) { + throw new IllegalArgumentException("岛屿编码不能为空"); + } + return islandInfoMapper.insert(islandInfo); + } + + @Override + public Boolean update(IslandInfo islandInfo) { + if (islandInfo.getId() == null) throw new IllegalArgumentException("ID不能为空"); + return islandInfoMapper.update(islandInfo); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return islandInfoMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/IslandParamServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/IslandParamServiceImpl.java new file mode 100644 index 0000000..129f7c6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/IslandParamServiceImpl.java @@ -0,0 +1,59 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.IslandParam; +import com.rczn.rcznautoplc.mapper.IslandParamMapper; +import com.rczn.rcznautoplc.service.IslandParamService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class IslandParamServiceImpl implements IslandParamService { + + @Autowired + IslandParamMapper islandParamMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, Integer islandId, Integer stepId, String paramName, String paramType) { + PageHelper.startPage(pageNum, pageSize); + IslandParam queryParam = new IslandParam(); + queryParam.setIslandId(islandId); + queryParam.setStepId(stepId); + queryParam.setParamName(paramName); + queryParam.setParamType(paramType); + List list = islandParamMapper.selectPage(queryParam); + return new PageInfo<>(list); + } + + @Override + public IslandParam selectById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return islandParamMapper.selectById(id); + } + + @Override + public Long insert(IslandParam islandParam) { + if (islandParam.getIslandId() == null) throw new IllegalArgumentException("岛屿ID不能为空"); + if (islandParam.getStepId() == null) throw new IllegalArgumentException("步骤ID不能为空"); + if (islandParam.getParamName() == null || islandParam.getParamName().isEmpty()) { + throw new IllegalArgumentException("参数名称不能为空"); + } + return islandParamMapper.insert(islandParam); + } + + @Override + public Boolean update(IslandParam islandParam) { + if (islandParam.getId() == null) throw new IllegalArgumentException("ID不能为空"); + return islandParamMapper.update(islandParam); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return islandParamMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java new file mode 100644 index 0000000..da73bba --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/ManageLogServiceImpl.java @@ -0,0 +1,85 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import com.rczn.domain.PageBean; +import com.rczn.rcznautoplc.domain.ManageLog; +import com.rczn.rcznautoplc.mapper.ManageLogMapper; +import com.rczn.rcznautoplc.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 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 logList = manageLogMapper.selectPage(manageLog); + Page page = (Page) logList; + + PageBean pageBean = new PageBean<>(); + pageBean.setTotal(page.getTotal()); + pageBean.setItems(page.getResult()); + + // 封装PageBean返回 + return pageBean; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java new file mode 100644 index 0000000..da7d539 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/PlcServiceImpl.java @@ -0,0 +1,499 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.rczn.ModbusCmdConst; +import com.rczn.modbus.Modbus4jUtils; +import com.rczn.modbus.Modbus4jWriteUtils; +import com.rczn.plc_common.S7ConnectorPLC; +import com.rczn.rcznautoplc.cache.IsLandActionParamToPlc; +import com.rczn.rcznautoplc.cache.PlcRunStatus; +import com.rczn.rcznautoplc.cache.RegisterAddrDic; +import com.rczn.rcznautoplc.domain.*; +import com.rczn.rcznautoplc.domain.query.DevInfoQuery; +import com.rczn.rcznautoplc.domain.query.DevParamQuery; +import com.rczn.rcznautoplc.domain.query.IslandInfoQuery; +import com.rczn.rcznautoplc.service.DevInfoService; +import com.rczn.rcznautoplc.service.DevParamService; +import com.rczn.rcznautoplc.service.IslandInfoService; +import com.rczn.rcznautoplc.service.PlcService; +import com.rczn.rcznautoplc.utils.PlcCommonProtcolUtil; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.ByteBuffer; +import java.nio.ShortBuffer; +import java.util.*; + + +@Service +public class PlcServiceImpl implements PlcService { + + // 核心:创建log对象(private static final,名称固定为log) + private static final Logger log = LoggerFactory.getLogger(PlcServiceImpl.class); + // Log log = LogFactory.getLog(PlcServiceImpl.class); + /** + * 连接plc设备 + * + * @param connectObj - + * @return + */ + @Override + public PlcConnectObj connect(PlcConnectObj connectObj) { + S7ConnectorPLC plc = new S7ConnectorPLC(); +// S7Connector connector = plc.initConnect(connectObj.getIpAddr(), connectObj.getPort(), connectObj.getRack(), connectObj.getSlot()); + S7Connector connector = S7ConnectorFactory.buildTCPConnector().build(); + + connectObj.setConnector(connector); + PlcConnectMap.plcConnectorMap.put(connectObj.getIpAddr(),connector); + return connectObj; + } + + /** + * 连接modbus设备 + * + * @param connectObj - + * @return + */ + @Override + public ModbusMaster connectModbus(ModbusConnectObj connectObj) throws ModbusInitException, ModbusTransportException { + //初始化modbus连接对象 + ModbusMaster modbusMaster = Modbus4jUtils.getAndTestMaster(connectObj.getIpAddr(), connectObj.getPort()); + //以ip地址为键值保存连接对象modbusMaster + PlcConnectMap.modbusConnectorMap.put(connectObj.getIpAddr(),modbusMaster); + if(connectObj.getHost()){ + PlcConnectMap.masterModbusConnector = modbusMaster; + } + return modbusMaster; + } + + + /** + * 启动plc设备 + * + * @param ipAddr - + * @return + */ + @Override + public Boolean startPlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdByte = new byte[4]; +// connector.write(DaveArea.DB,1,1,cmdByte); + +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_run); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + + return false; + } + + /** + * plc设备暂停运行 + * + * @param ipAddr - + * @return + */ + @Override + public Boolean pausePlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdByte = new byte[4]; +// connector.write(DaveArea.DB,1,1,cmdByte); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_pause); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * plc设备故障复位 + * + * @param ipAddr - + * @return + */ + @Override + public Boolean resetErrorPlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdByte = new byte[4]; +// connector.write(DaveArea.DB,1,1,cmdByte); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_ready); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * 根据ip地址获取plc设备状态值 + * 0-未连接,1-连接,10-就绪,11-执行,12-暂停,19暂停,20-故障复位 + * + * @param ipAddr + * @return + */ + @Override + public Integer getPlcStatus(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Number number = Modbus4jUtils.readHoldingRegister(modbusMaster, 1, 1, DataType.TWO_BYTE_INT_UNSIGNED); + return number.intValue(); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ErrorResponseException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return -1; + } + + /** + * 根据ip地址设置plc设备模式 + * 0-手动,1-自动 + * + * @param ipAddr + * @param modelValue + * @return + */ + @Override + public Boolean setPlcModel(String ipAddr, Integer modelValue) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,0,(short) modelValue.intValue()); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * 根据ip地址获取plc设备模式值 + * 0-手动,1-自动 + * + * @param ipAddr + * @return + */ + @Override + public Integer getPlcModel(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Number number = Modbus4jUtils.readHoldingRegister(modbusMaster, 1, 0, DataType.TWO_BYTE_INT_UNSIGNED); + if(number.intValue() != 0 && number.intValue()!=1){ + number = 0; + } + return number.intValue(); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ErrorResponseException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return -1; + } + + /** + * 根据ip地址获取plc设备 + * + * @param ipAddr + * @return + */ + @Override + public S7Connector getPlc(String ipAddr) { + return PlcConnectMap.plcConnectorMap.get(ipAddr); + } + + /** + * 根据ip地址获取modbus连接设备 + * + * @param ipAddr + * @return + */ + @Override + public ModbusMaster getModbusConnect(String ipAddr) { + return PlcConnectMap.modbusConnectorMap.get(ipAddr); + } + + /** + * 获取全部plc连接对象 + * + * @return + */ + @Override + public Map plcALlMap() { + return PlcConnectMap.plcConnectorMap; + } + + /** + * 获取全部plc连接对象 + * + * @return + */ + @Override + public Map modbusALlMap() { + return PlcConnectMap.modbusConnectorMap; + } + + /** + * 执行plc动作 + * + * @param ipAddr + * @param action + * @return + */ + @Override + public Boolean doAction(String ipAddr, String action) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = new byte[5]; +// connector.write(DaveArea.DB,1,1,cmdBytes); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_run); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + /** + * 停止plc运行: + * + * @param ipAddr + * @return + */ + @Override + public Boolean stopPlc(String ipAddr) { +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = new byte[5]; +// connector.write(DaveArea.DB,1,1,cmdBytes); +// S7Connector connector = PlcConnectMap.plcConnectorMap.get(ipAddr); +// byte[] cmdBytes = {(byte)(ModbusCmdConst.plc_run>>8),(byte)ModbusCmdConst.plc_run}; +// if(connector != null){ +// connector.write(DaveArea.DB,1,0,cmdBytes); +// } + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(ipAddr); + if(modbusMaster!=null){ + try { + Modbus4jWriteUtils.writeRegister(modbusMaster,1,1,(short) ModbusCmdConst.plc_stop); + return true; + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + return false; + } + + @Autowired + IslandInfoService islandInfoService; + @Autowired + DevInfoService devInfoService; + @Autowired + DevParamService devParamService; + /** + * 执行sop信息 + * + * @param sopId + * @param barCodeList + * @param stepInfoList + * @return + */ + @Override + public Boolean runSopInfoForGoodsList(String plcIp,Integer sopId, List barCodeList, List stepInfoList) { + // 1. 空值校验:提前拦截null,避免线程内空指针 + if (barCodeList == null || barCodeList.isEmpty() || stepInfoList == null || stepInfoList.isEmpty()) { + log.warn("样品编码列表或步骤信息列表为空,无需执行PLC动作"); + return false; + } + //更新一次功能岛、动作单元、参数对应plc映射地址缓存: + List islandInfos = islandInfoService.selectList(new IslandInfoQuery()); + IsLandActionParamToPlc.islandToPlc.clear(); + + for (int i = 0; i < islandInfos.size(); i++) { + IslandInfo islandInfo = islandInfos.get(i); + IsLandActionParamToPlc.islandToPlc.put(islandInfo.getId().intValue(),islandInfo.getPlcAddr()); + } + List devInfos = devInfoService.getDevInfoList(new DevInfoQuery()); + IsLandActionParamToPlc.actionToPlc.clear(); + + for (int i = 0; i < devInfos.size(); i++) { + DevInfo devInfo = devInfos.get(i); + IsLandActionParamToPlc.actionToPlc.put(devInfo.getId().intValue(),devInfo.getPlcAddr()); + } + + List devParams = devParamService.selectList(new DevParamQuery()); + IsLandActionParamToPlc.paramToPlc.clear(); + IsLandActionParamToPlc.paramIdToPlc.clear(); + + for (int i = 0; i < devParams.size(); i++) { + DevParam devParam = devParams.get(i); + IsLandActionParamToPlc.paramToPlc.put(devParam.getParamName(),devParam.getPlcAddr()); + IsLandActionParamToPlc.paramIdToPlc.put(devParam.getId().intValue(),devParam.getPlcAddr()); + } + + //为stepInfoList排序,根据StepInfo的step_order(int)字段 + stepInfoList.sort(Comparator.comparingInt(StepInfo::getStepOrder)); + + // 2. 深拷贝集合:避免线程共享导致的并发修改问题 + List barCodeListCopy = new ArrayList<>(barCodeList); + List stepInfoListCopy = new ArrayList<>(stepInfoList); + // 若StepInfo是自定义对象,需保证深拷贝(如果是浅拷贝,对象属性仍会共享) + // stepInfoListCopy = stepInfoList.stream().map(step -> 深拷贝StepInfo).collect(Collectors.toList()); + + // 3. 启动线程执行分组逻辑 + new Thread(() -> { + try { + runSopInfoForGroup(plcIp,sopId,barCodeListCopy, stepInfoListCopy); + } catch (Exception e) { + // 4. 捕获线程内异常:避免线程静默失败 + log.error("执行PLC分组任务失败", e); + } + }, "Sop-PLC-Thread-" + sopId).start(); // 给线程命名,便于日志排查 + + return true; + } + + private void runSopInfoForGroup(String plcIp,Integer sopId,List barCodeList, List stepInfoList) throws InterruptedException { + //更新:plc状态中的当前处理样品数量: + PlcRunStatus.goodsCount = barCodeList.size(); + PlcRunStatus.goodsCurrentIndex = 0; + // 5. 实现8个一组的分组逻辑(核心业务补充) + int groupSize = 8; + for (int i = 0; i < barCodeList.size(); i += groupSize) { + // 截取8个一组的子列表(最后一组可能不足8个) + int end = Math.min(i + groupSize, barCodeList.size()); + List subBarCodeList = barCodeList.subList(i, end); + + //先判断PLC状态: + while (true){ + if(PlcRunStatus.systemPlcRunStatus == 1){ + // 按分组执行PLC动作(核心业务逻辑) + executePlcActionByGroup(plcIp,sopId,subBarCodeList, stepInfoList); + //更新样品处理数量索引: + PlcRunStatus.goodsCurrentIndex += subBarCodeList.size(); + break; + } + } + + //暂停2.2秒,获取状态 + Thread.sleep(2200); + //获取PLC整体状态: + while (true){ + if(PlcRunStatus.systemPlcRunStatus == 1){ + //如果空闲 + break; + } + } + + } + } + + // 补充:按分组执行PLC动作的核心方法 + private void executePlcActionByGroup(String plcIp,Integer sopId,List subBarCodeList, List stepInfoList) { + // 根据样品编码获取PLC设备 + // 根据步骤信息执行PLC动作 + log.info("执行PLC分组任务,当前分组样品编码:{}", subBarCodeList); + ModbusMaster modbusMaster = PlcConnectMap.modbusConnectorMap.get(plcIp); + if(modbusMaster!=null){ + int startAddr = RegisterAddrDic.downProtcolRegisterArr; + //获取样品+sop序列协议 + List sopProtcol = PlcCommonProtcolUtil.getSopProtcol(sopId, subBarCodeList, stepInfoList); + //将协议写入PLC + ByteBuffer sopBuff = ByteBuffer.allocate(sopProtcol.size()); + for (byte b1: + sopProtcol) { + sopBuff.put(b1); + } + ShortBuffer sopBuffShort = sopBuff.asShortBuffer(); + try { + Modbus4jWriteUtils.writeRegisters(modbusMaster,1,startAddr, sopBuffShort.array()); + } catch (ModbusTransportException e) { + throw new RuntimeException(e); + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + }else { + throw new RuntimeException("未找到对应的modbusMaster"); + } + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/RecordInfoServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/RecordInfoServiceImpl.java new file mode 100644 index 0000000..d3ad190 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/RecordInfoServiceImpl.java @@ -0,0 +1,61 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.RecordInfo; +import com.rczn.rcznautoplc.mapper.RecordInfoMapper; +import com.rczn.rcznautoplc.service.RecordInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class RecordInfoServiceImpl implements RecordInfoService { + + @Autowired + RecordInfoMapper recordInfoMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, String recordName, Integer recordType, Boolean recordStatus) { + PageHelper.startPage(pageNum, pageSize); + RecordInfo queryParam = new RecordInfo(); + queryParam.setRecordName(recordName); + queryParam.setRecordType(recordType); + queryParam.setRecordStatus(recordStatus); + List list = recordInfoMapper.selectPage(queryParam); + return new PageInfo<>(list); + } + + @Override + public RecordInfo selectById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return recordInfoMapper.selectById(id); + } + + @Override + public Long insert(RecordInfo recordInfo) { + if (recordInfo.getRecordName() == null || recordInfo.getRecordName().isEmpty()) { + throw new IllegalArgumentException("记录名称不能为空"); + } + if (recordInfo.getRecordType() == null) { + throw new IllegalArgumentException("记录类型不能为空(1-设备异常,2-样品异常,3-操作异常)"); + } + if (recordInfo.getRecordContent() == null || recordInfo.getRecordContent().isEmpty()) { + throw new IllegalArgumentException("记录内容不能为空"); + } + return recordInfoMapper.insert(recordInfo); + } + + @Override + public Boolean update(RecordInfo recordInfo) { + if (recordInfo.getId() == null) throw new IllegalArgumentException("ID不能为空"); + return recordInfoMapper.update(recordInfo); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return recordInfoMapper.deleteById(id); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/StepInfoServiceImpl.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/StepInfoServiceImpl.java new file mode 100644 index 0000000..632fb79 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/service/impl/StepInfoServiceImpl.java @@ -0,0 +1,89 @@ +package com.rczn.rcznautoplc.service.impl; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.domain.query.StepInfoQuery; +import com.rczn.rcznautoplc.mapper.StepInfoMapper; +import com.rczn.rcznautoplc.service.StepInfoService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public class StepInfoServiceImpl implements StepInfoService { + + @Autowired + StepInfoMapper stepInfoMapper; + + @Override + public PageInfo selectPage(Integer pageNum, Integer pageSize, StepInfoQuery stepInfo) { + PageHelper.startPage(pageNum, pageSize); + List list = stepInfoMapper.selectPage(stepInfo); + return new PageInfo<>(list); + } + + @Override + public List selectList(StepInfoQuery stepInfo) { + List list = stepInfoMapper.selectPage(stepInfo); + return list; + } + + @Override + public StepInfo selectById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return stepInfoMapper.selectById(id); + } + + + + @Override + public Long insert(StepInfo stepInfo) { + if (stepInfo.getIslandId() == null) throw new IllegalArgumentException("岛屿ID不能为空"); + if (stepInfo.getStepName() == null || stepInfo.getStepName().isEmpty()) { + throw new IllegalArgumentException("步骤名称不能为空"); + } + return stepInfoMapper.insert(stepInfo); + } + + @Override + public Long insertBatch(List stepInfoList) { + return stepInfoMapper.insertBatch(stepInfoList); + } + + @Override + public Boolean update(StepInfo stepInfo) { + if (stepInfo.getId() == null) throw new IllegalArgumentException("ID不能为空"); + return stepInfoMapper.update(stepInfo); + } + + /** + * 批量更新 + * + * @param stepInfoList + * @return + */ + @Override + public Long updateBatch(List stepInfoList) { + return stepInfoMapper.updateBatch(stepInfoList); + } + + @Override + public Boolean deleteById(Long id) { + if (id == null) throw new IllegalArgumentException("ID不能为空"); + return stepInfoMapper.deleteById(id); + } + + /** + * 批量删除 + * + * @param ids + * @return + * @throws Exception + */ + @Override + public Long deleteBatchByIds(List ids) { + return stepInfoMapper.deleteBatchByIds(ids); + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java new file mode 100644 index 0000000..3082848 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/task/PlcTask.java @@ -0,0 +1,159 @@ +package com.rczn.rcznautoplc.task; + +import com.rczn.modbus.Modbus4jUtils; +import com.rczn.modbus.Modbus4jWriteUtils; +import com.rczn.rcznautoplc.cache.RegisterAddrDic; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.service.GoodsFlowStatusService; +import com.rczn.rcznautoplc.service.GoodsInfoService; +import com.rczn.rcznautoplc.cache.PlcRunStatus; +import com.rczn.rcznautoplc.utils.PlcCommonProtcolUtil; +import com.rczn.rcznautoplc.utils.PlcConnectMap; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +@Component +public class PlcTask { + Log log = LogFactory.getLog(PlcTask.class); + + //样品状态service + @Autowired + GoodsFlowStatusService goodsFlowStatusService; + + //定时任务,每2秒执行一次:Cron 表达式支持 6 位(秒 分 时 日 月 周)或 7 位(秒 分 时 日 月 周 年) + @Scheduled(cron = "0/2 * * * * ?") + public void statusMonitor() throws ModbusInitException, ModbusTransportException, ErrorResponseException { + log.info("plc 设备状态监控."); + //判断是否有plc连接设备, + if(PlcConnectMap.masterModbusConnector != null ){ + log.info("plc 主设备状态监控开始..."); + //遍历连接对象 + ModbusMaster connector = PlcConnectMap.masterModbusConnector; + //1-读取功能岛状态: + //1-1:sop中第一个功能岛,定容岛>10000(十进制):样品是否扫描完毕-0-1:0-未扫描完毕,1-扫描完毕 + Number scanReadyStatusNum = Modbus4jUtils.readHoldingRegister(connector, 1, 5000, DataType.TWO_BYTE_INT_UNSIGNED); + PlcRunStatus.goodsScanStatus = scanReadyStatusNum.intValue(); + + //判断如果扫描完成,获取样品编码数据,保存数据库,修改plc寄存器状态值和修改索引状态: + if(PlcRunStatus.goodsScanStatus == 1){ + getGoodsInfoFromPlc( connector, PlcRunStatus.goodsScanStatus); + } + //查看plc的状态返回寄存器:(开头:cc cc-有返回状态数据) + Number goodsStatusStart = Modbus4jUtils.readHoldingRegister(connector, 1, RegisterAddrDic.upProtcolRegisterArr, DataType.TWO_BYTE_INT_UNSIGNED); + if(goodsStatusStart.intValue() == 0xcccc){ + //2-读取状态数据长度值 + Number goodsStatusLength = Modbus4jUtils.readHoldingRegister(connector, 1, RegisterAddrDic.upProtcolRegisterArr+1, DataType.TWO_BYTE_INT_UNSIGNED); + //3-读取状态数据 + Number[] goodsStatusArr = Modbus4jUtils.readHoldingRegisters(connector, 1, RegisterAddrDic.upProtcolRegisterArr, goodsStatusLength.intValue()/2+4, DataType.TWO_BYTE_INT_UNSIGNED); + //4-解析样品状态数据:把number数组数据转正List + List goodsStatusByteList = new ArrayList<>(); + for (Number goodsStatusNum:goodsStatusArr + ) { + goodsStatusByteList.add((byte) (goodsStatusNum.intValue()>>8)); + goodsStatusByteList.add((byte) (goodsStatusNum.intValue()&0xff)); + } + List list = PlcCommonProtcolUtil.pareseProtcolStatus(goodsStatusByteList); + //5-插入数据库样品状态: + for (GoodsFlowStatus goodsFlowStatus:list + ) { + goodsFlowStatusService.insert(goodsFlowStatus); + } + + //6-清空寄存器数据: + Modbus4jWriteUtils.writeRegisters(connector,1,RegisterAddrDic.upProtcolRegisterArr, new short[goodsStatusLength.intValue()/2+4]); + } + + + //2-读取整个系统sop执行后状态:0-未准备,1-空闲,2-忙,4-异常 + Number sopRunStatus = Modbus4jUtils.readHoldingRegister(connector, 1, 5500, DataType.TWO_BYTE_INT_UNSIGNED); + PlcRunStatus.systemPlcRunStatus = sopRunStatus.intValue(); + + }else { + log.info("plc 主设备未连接."); + } + } + + @Autowired + GoodsInfoService goodsInfoService; + + //任务:样品编码扫描完毕,读取 + /** + * 异步执行样品信息读取(单独线程) + * @Async("plcAsyncExecutor") 指定使用自定义的PLC专用线程池 + */ + @Async("plcAsyncExecutor") + public void getGoodsInfoFromPlc(ModbusMaster connector,int goodsScanStatus) { + try { + log.info("异步读取样品信息开始,线程名:" + Thread.currentThread().getName()); + //10001-10032:32个槽位放置样品: + //一个寄存器返回两个字节:是两个样品索引地址: + Number[] goodsIndexStatus = Modbus4jUtils.readHoldingRegisters(connector,1, 5001,16,DataType.TWO_BYTE_INT_UNSIGNED); + List goodsIndexNumList = new ArrayList<>(); + for (Number goodsIndexNum:goodsIndexStatus + ) { + //一个寄存器返回值分成两个样品状态值: + int registerStatus = goodsIndexNum.intValue(); + goodsIndexNumList.add(registerStatus>>8); + goodsIndexNumList.add(registerStatus&0xff); + } + +// List goodsInfoList = new ArrayList<>(); + //当前时间: + LocalDateTime localDateTime = LocalDateTime.now(); + //样品编码地址:10033-10048;10049-10063; + for (int i = 0; i < goodsIndexNumList.size(); i++) { + int goodsIndexNum = goodsIndexNumList.get(i); + if (goodsIndexNum == 1) { + Number[] goodsCodeNumTemp = Modbus4jUtils.readHoldingRegisters(connector, 1, 10018 + i * 16,16, DataType.TWO_BYTE_INT_UNSIGNED); + StringBuilder goodCodeNumStr = new StringBuilder(); + for (Number goodsIndexNumTemp:goodsCodeNumTemp){ + goodCodeNumStr.append(goodsIndexNumTemp.intValue()>>8); + goodCodeNumStr.append(goodsIndexNumTemp.intValue()&0xff); + } + GoodsInfo goodsInfo = new GoodsInfo(); + goodsInfo.setBarCode(goodCodeNumStr.toString()); + goodsInfo.setPointNum(i+1); + goodsInfo.setGoodsName(PlcRunStatus.defaultGoodsName); + goodsInfo.setGoodsType(PlcRunStatus.defaultGoodsType); + goodsInfo.setGoalDetect(PlcRunStatus.defaultGoalDetect); + goodsInfo.setIncomeTime(localDateTime); + goodsInfo.setCreateTime(LocalDateTime.now()); + +// goodsInfoList.add(goodsInfo); + //获取的样品对象,保存到数据库, + goodsInfoService.insert(goodsInfo); + log.info("样品编码:" + goodCodeNumStr.toString() + ",样品索引:" + goodsIndexNum); + } + } + + //修改寄存器样品索引值: + //10001-10032:16个寄存器,每个寄存器两个样品状态值,修改样品索引值为:0 + short[] goodsRegisterValues = new short[16]; + Modbus4jWriteUtils.writeRegisters(connector,1, 10001,goodsRegisterValues); + //修改10000寄存器的值为:0 + Modbus4jWriteUtils.writeHoldingRegister(connector,1, 10000,0,DataType.TWO_BYTE_INT_UNSIGNED); + + // 此处可添加:保存数据到数据库、修改寄存器状态等业务逻辑 + log.info("异步读取样品信息完成"); + + } catch (ModbusInitException | ModbusTransportException | ErrorResponseException e) { + // 捕获异步线程中的异常并记录日志(异步方法异常不会自动抛出到主线程) + log.error("异步读取样品信息失败", e); + } + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java new file mode 100644 index 0000000..3e382c8 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcCommonProtcolUtil.java @@ -0,0 +1,282 @@ +package com.rczn.rcznautoplc.utils; + +import com.rczn.rcznautoplc.cache.IsLandActionParamToPlc; +import com.rczn.rcznautoplc.domain.GoodsFlowStatus; +import com.rczn.rcznautoplc.domain.GoodsInfo; +import com.rczn.rcznautoplc.domain.StepInfo; +import com.rczn.rcznautoplc.domain.query.GoodsInfoQuery; +import com.rczn.rcznautoplc.service.GoodsInfoService; +import com.rczn.utils.BeanFactoryUtils; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.*; + +public class PlcCommonProtcolUtil { +// 样品SOP执行指令 开始字节(2) 总字节长度(2) SOP id号(4) 样品数量(1) 样品地址(16) 样品地址(16) 样品地址(16) ... 功能岛PLC(2) 动作PLC地址(2) 参数PLC地址(2) 参数值(2) ... 结束码 +// CC CC 0011 11223344 16 0 1 2 AA+01 BB+01 CC+01 0011 EEEE + public static List getSopProtcol(Integer sopId,List subBarCodeList, List stepInfoList) { + List protcolByteList = new ArrayList<>(); + + Byte[] startByte = {(byte) 0xcc,(byte) 0xcc}; + for (int i = 0; i < startByte.length; i++) { + protcolByteList.add(startByte[i]); + } + + //后面修正数据 + byte[] dataLength = new byte[2]; + for (int i = 0; i < dataLength.length; i++) { + protcolByteList.add(dataLength[i]); + } + + // sop id + byte[] sopIdByte = new byte[4]; + sopIdByte[0] = (byte) (sopId >> 24); + sopIdByte[1] = (byte) (sopId >> 16); + sopIdByte[2] = (byte) (sopId >> 8); + sopIdByte[3] = (byte) sopId.intValue(); + for (int i = 0; i < sopIdByte.length; i++) { + protcolByteList.add(sopIdByte[i]); + } + + //样品数量 + byte sampleNum = (byte) subBarCodeList.size(); + protcolByteList.add(sampleNum); + + //把样品地址写入协议字符串列表 + for (int i = 0; i < subBarCodeList.size(); i++) { + String subBarCode = subBarCodeList.get(i); + //subBarCode是一系列数字字符串,转成16个10进制数字(需要兼容subBarCode长度超过或少于16的情况) + byte[] sampleAddress = new byte[16]; + for (int j = 0; j < subBarCode.length() && j < sampleAddress.length; j++) { + sampleAddress[j] = (byte) Integer.parseInt(subBarCode.substring(j, j + 1)); + } + + for (int j = 0; j < sampleAddress.length; j++) { + protcolByteList.add(sampleAddress[j]); + } + } + //stepInfoList列表按照StepInfo对象里面的Integer islandId属性 + // 属性里面有stepOrder,计算出有多少个连续的不同islandId属性值 + //第一个stepInfo的islandId + StepInfo stepInfo_0 = stepInfoList.get(0); + // 1-第一个功能岛plc + Integer islandPlcIntV = IsLandActionParamToPlc.islandToPlc.get(stepInfo_0.getIslandId()); + byte[] islandPlc_0 = new byte[2]; + islandPlc_0[0] = (byte) 0xaa; + islandPlc_0[1] = (byte) islandPlcIntV.intValue(); + + for (int i = 0; i < islandPlc_0.length; i++) { + protcolByteList.add(islandPlc_0[i]); + } + //第一个动作单元plc + Integer actionPlcIntV = IsLandActionParamToPlc.actionToPlc.get(stepInfo_0.getDevId()); + byte[] actionPlc_0 = new byte[2]; + actionPlc_0[0] = (byte) 0xbb; + actionPlc_0[1] = (byte) actionPlcIntV.intValue(); + for (int i = 0; i < actionPlc_0.length; i++) { + protcolByteList.add(actionPlc_0[i]); + } + //第一个参数单元plc + Integer paramPlcIntV = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_0 = new byte[2]; + paramPlc_0[0] = (byte) 0xcc; + paramPlc_0[1] = (byte) paramPlcIntV.intValue(); + for (int i = 0; i < paramPlc_0.length; i++) { + protcolByteList.add(paramPlc_0[i]); + } + //第一个参数值 + int paramValueInt = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_0 = new byte[2]; + paramValue_0[0] = (byte) (paramValueInt>>8); + paramValue_0[1] = (byte) paramValueInt; + + for (int i = 0; i < paramValue_0.length; i++) { + protcolByteList.add(paramValue_0[i]); + } + + for (int i = 1; i < stepInfoList.size(); i++) { + // isLandId:1 order:1 => isLandId:1 order:2 => isLandId:2 order:3 => isLandId:2 order:4 => isLandId:3 order:5 + StepInfo stepInfo = stepInfoList.get(i); + //判断是否更换功能岛 + if (stepInfo.getIslandId() != stepInfo_0.getIslandId()) { + // 1-第一个功能岛plc + Integer islandPlcIntV_1 = IsLandActionParamToPlc.islandToPlc.get(stepInfo_0.getIslandId()); + byte[] islandPlc_1 = new byte[2]; + islandPlc_1[0] = (byte) 0xaa; + islandPlc_1[1] = (byte) islandPlcIntV_1.intValue(); + + for (int j = 0; j < islandPlc_1.length; j++) { + protcolByteList.add(islandPlc_1[j]); + } + + //第一个动作单元plc + Integer actionPlcIntV_1 = IsLandActionParamToPlc.actionToPlc.get(stepInfo_0.getDevId()); + byte[] actionPlc_1 = new byte[2]; + actionPlc_1[0] = (byte) 0xbb; + actionPlc_1[1] = (byte) actionPlcIntV_1.intValue(); + for (int j = 0; j < actionPlc_1.length; j++) { + protcolByteList.add(actionPlc_1[j]); + } + //第一个参数单元plc + Integer paramPlcIntV_1 = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_1 = new byte[2]; + paramPlc_1[0] = (byte) 0xcc; + paramPlc_1[1] = (byte) paramPlcIntV.intValue(); + for (int j = 0; j < paramPlc_1.length; j++) { + protcolByteList.add(paramPlc_1[j]); + } + //第一个参数值 + int paramValueInt_1 = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_1 = new byte[2]; + paramValue_1[0] = (byte) (paramValueInt_1>>8); + paramValue_1[1] = (byte) paramValueInt_1; + + for (int j = 0; j < paramValue_1.length; j++) { + protcolByteList.add(paramValue_1[j]); + } + + + }else if(stepInfo.getDevId()!= stepInfo_0.getDevId()){ + //判断是否更换动作单元 + //第一个动作单元plc + Integer actionPlcIntV_1 = IsLandActionParamToPlc.actionToPlc.get(stepInfo_0.getDevId()); + byte[] actionPlc_1 = new byte[2]; + actionPlc_1[0] = (byte) 0xbb; + actionPlc_1[1] = (byte) actionPlcIntV_1.intValue(); + for (int j = 0; j < actionPlc_1.length; j++) { + protcolByteList.add(actionPlc_1[j]); + } + //第一个参数单元plc + Integer paramPlcIntV_1 = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_1 = new byte[2]; + paramPlc_1[0] = (byte) 0xcc; + paramPlc_1[1] = (byte) paramPlcIntV.intValue(); + for (int j = 0; j < paramPlc_1.length; j++) { + protcolByteList.add(paramPlc_1[j]); + } + //第一个参数值 + int paramValueInt_1 = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_1 = new byte[2]; + paramValue_1[0] = (byte) (paramValueInt_1>>8); + paramValue_1[1] = (byte) paramValueInt_1; + + for (int j = 0; j < paramValue_1.length; j++) { + protcolByteList.add(paramValue_1[j]); + } + }else { + //第一个参数单元plc + Integer paramPlcIntV_1 = IsLandActionParamToPlc.paramToPlc.get(stepInfo_0.getParamName()); + byte[] paramPlc_1 = new byte[2]; + paramPlc_1[0] = (byte) 0xcc; + paramPlc_1[1] = (byte) paramPlcIntV.intValue(); + for (int j = 0; j < paramPlc_1.length; j++) { + protcolByteList.add(paramPlc_1[j]); + } + //第一个参数值 + int paramValueInt_1 = Integer.parseInt(stepInfo_0.getParamValue()); + byte[] paramValue_1 = new byte[2]; + paramValue_1[0] = (byte) (paramValueInt_1>>8); + paramValue_1[1] = (byte) paramValueInt_1; + + for (int j = 0; j < paramValue_1.length; j++) { + protcolByteList.add(paramValue_1[j]); + } + } + stepInfo_0 = stepInfo; + } + + int dataLengthInt = protcolByteList.size(); + protcolByteList.set(2, (byte) (dataLengthInt>>8)); + protcolByteList.set(3, (byte) dataLengthInt); + + byte[] endByte = {(byte) 0xee, (byte) 0xee}; + protcolByteList.add(endByte[0]); + protcolByteList.add(endByte[1]); + + return protcolByteList; + } + + +// 样品处理状态返回指令 开始字节(2) 总字节长度(2) SOP id号(4) 样品数量(4) 样品地址(4) 功能岛PLC(1) 动作PLC地址(1) 参数PLC地址(1) 检测值(2) 样品地址(4) 功能岛PLC(1) 动作PLC地址(1) 参数PLC地址(1) 检测值(2) ... crc校验 结束码 +// CCCC 0011 11223344 16 0 1 1 1 0011 1 1 1 1 0011 XX EEEE + public static List pareseProtcolStatus(List protcolByteList) { + //获取样品数据,整理处理Map对象,key:bar_code,value:goodsId + GoodsInfoService goodsInfoService = BeanFactoryUtils.getBean(GoodsInfoService.class); + List goodsInfoList = goodsInfoService.selectList(new GoodsInfoQuery()); + Map goodsInfoCodeIDMap = new HashMap<>(); + for (GoodsInfo goodsInfo : goodsInfoList) { + goodsInfoCodeIDMap.put(goodsInfo.getBarCode(), goodsInfo.getId()); + } + + List goodsFlowStatusList = new ArrayList<>(); + + //sop id值: + StringBuilder sopIdSb = new StringBuilder(); + for (int i = 0; i < 4; i++) { + Byte sopByte = protcolByteList.get(3 + i); + sopIdSb.append(sopByte.intValue()); + } + Integer sopId = Integer.parseInt(sopIdSb.toString()); + + byte goodsCount = protcolByteList.get(7); + for (int i = 0; i < goodsCount; i++) { + //样品扫描编码地址 + StringBuilder goodsAddressSb = new StringBuilder(); + for (int j = 0; j < 16; j++){ + Byte addByte = protcolByteList.get(8 + i * 16 + j); + goodsAddressSb.append(addByte.intValue()); + } + //功能岛PLC地址 + byte isLandPlc = protcolByteList.get(8 + (i+1) * 16); + //动作单元plc地址 + byte actionPlc = protcolByteList.get(8 + (i+1) * 16 + 1); + //参数plc地址 + byte paramPlc = protcolByteList.get(8 + (i+1) * 16 + 2); + //检测值 + byte[] checkValue = new byte[2]; + for (int j = 0; j < checkValue.length; j++) { + checkValue[j] = protcolByteList.get(8 + (i+1) * 16 + 3 + j); + } + + int checkValueInt = ByteBuffer.wrap(checkValue).order(ByteOrder.LITTLE_ENDIAN).getShort(); + + GoodsFlowStatus flowStatus = new GoodsFlowStatus(); + Long goodsId = goodsInfoCodeIDMap.get(goodsAddressSb.toString()); + flowStatus.setGoodsId(goodsId.intValue()); + flowStatus.setFlowId(sopId); + for (Integer isLandId : + IsLandActionParamToPlc.islandToPlc.keySet()) { + Integer plcValue = IsLandActionParamToPlc.islandToPlc.get(isLandId); + if (plcValue == isLandPlc) { + flowStatus.setIslandId(isLandId); + break; + } + } + for (Integer actionId : + IsLandActionParamToPlc.actionToPlc.keySet()) { + Integer plcValue = IsLandActionParamToPlc.actionToPlc.get(actionId); + if (plcValue == actionPlc) { + flowStatus.setDevId(actionId); + break; + } + } + + for (Integer paramId: + IsLandActionParamToPlc.paramIdToPlc.keySet()) { + Integer plcValue = IsLandActionParamToPlc.paramIdToPlc.get(paramId); + if (plcValue == paramPlc) { + flowStatus.setFlowSort(paramId); + break; + } + } + + flowStatus.setStatus(checkValueInt); + + //保存样品状态数据: + goodsFlowStatusList.add(flowStatus); + } + + return goodsFlowStatusList; + } +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java new file mode 100644 index 0000000..605cd98 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/java/com/rczn/rcznautoplc/utils/PlcConnectMap.java @@ -0,0 +1,24 @@ +package com.rczn.rcznautoplc.utils; + +import com.github.s7connector.api.S7Connector; +import com.rczn.rcznautoplc.domain.DevInfo; +import com.serotonin.modbus4j.ModbusMaster; + +import java.util.HashMap; +import java.util.Map; + +public class PlcConnectMap { + + //PLC设备map对象:key:ip,value:设备 + public static Map plcDevMap = new HashMap<>(); + + //plc连接对象缓存: + public static Map plcConnectorMap = new HashMap<>(); + + //Modbus连接对象缓存: + public static Map modbusConnectorMap = new HashMap<>(); + + //主plc modbus连接对象: + public static ModbusMaster masterModbusConnector = null; + +} diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/application-autoplc.yml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/application-autoplc.yml new file mode 100644 index 0000000..cf5f152 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/application-autoplc.yml @@ -0,0 +1 @@ +##spring.application.name=rczn-autoplc diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/DevInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/DevInfoMapper.xml new file mode 100644 index 0000000..ea39fb6 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/DevInfoMapper.xml @@ -0,0 +1,266 @@ + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + island_id, dev_name, dev_model,plc_addr, ip_addr, port, protocol_type, company, status,run_model, dev_desc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO tb_dev_info ( + + + island_id, + dev_name, + dev_model, + plc_addr, + ip_addr, + port, + protocol_type, + company, + status, + run_model, + `dev_desc`, + + create_id, + remark, + + create_time, + update_time, + del_sign + + ) VALUES ( + + + #{islandId}, + #{devName}, + #{devModel}, + #{plcAddr}, + #{ipAddr}, + #{port}, + #{protocolType}, + #{company}, + #{status}, + #{runModel}, + #{devDesc}, + + #{createId}, + #{remark}, + + NOW(), + NOW(), + 0 + + ) + + + + + UPDATE tb_dev_info + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE tb_dev_info + + + island_id = #{islandId}, + dev_name = #{devName}, + dev_model = #{devModel}, + plc_addr = #{plcAddr}, + ip_addr = #{ipAddr}, + port = #{port}, + protocol_type = #{protocolType}, + company = #{company}, + status = #{status}, + #{runModel}, + + `dev_desc` = #{devDesc}, + + update_id = #{updateId}, + remark = #{remark}, + + update_time = NOW() + + + WHERE id = #{id} AND del_sign = 0 + + + AND 1 = 0 + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/DevParamMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/DevParamMapper.xml new file mode 100644 index 0000000..b0b33a3 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/DevParamMapper.xml @@ -0,0 +1,126 @@ + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + dev_ids, param_name, plc_addr, dic_data_id, param_value, param_type, param_unit, form_type, param_desc + + + + + INSERT INTO tb_dev_param ( + + dev_ids, + plc_addr, + dic_data_id, + param_name, + param_value, + param_type, + param_unit, + form_type, + param_desc, + create_id, + update_id, + create_time, + update_time, + del_sign + + ) + VALUES ( + + #{devIds}, + #{plcAddr}, + #{dicDataId}, + #{paramName}, + #{paramValue}, + #{paramType}, + #{paramUnit}, + #{formType}, + #{paramDesc}, + #{createId}, + #{updateId}, + NOW(), + NOW(), + 0 + + ) + + + + + UPDATE tb_dev_param + + dev_ids = #{devIds}, + plc_addr = #{plcAddr}, + dic_data_id = #{dicDataId}, + param_name = #{paramName}, + param_value = #{paramValue}, + param_type = #{paramType}, + param_unit = #{paramUnit}, + form_type = #{formType}, + param_desc = #{paramDesc}, + update_id = #{updateId}, + remark = #{remark}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE tb_dev_param + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + AND 1=2 + + + + + + + + + + + UPDATE tb_dev_param + SET dev_ids = CASE + WHEN dev_ids IS NULL OR dev_ids = '' THEN CONCAT(#{devId}, ';') + ELSE CONCAT(dev_ids, #{devId}, ';') + END + WHERE id = #{paramId} + AND 1=2 + + + + + UPDATE tb_dev_param + SET dev_ids = REPLACE(dev_ids, CONCAT(#{devId}, ';'), '') + WHERE id = #{paramId} + AND 1=2 + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/FlowInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/FlowInfoMapper.xml new file mode 100644 index 0000000..54ad8ba --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/FlowInfoMapper.xml @@ -0,0 +1,112 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + flow_index, flow_name, island_id_list,busy_code,goods_code,goods_name,check_code,program_name,test_method,scan_num + + + + INSERT INTO tb_flow_info ( + + + + create_id, + update_id, + create_time, + update_time, + remark, + + + flow_index, + flow_name, + island_id_list, + busy_code, + goods_code, + goods_name, + check_code, + program_name, + test_method, + scan_num, + + ) VALUES ( + + #{createId}, + #{updateId}, + #{createTime}, + #{updateTime}, + #{remark}, + + + #{flowIndex}, + #{flowName}, + #{islandIdList}, + #{busyCode}, + #{goodsCode}, + #{goodsName}, + #{checkCode}, + #{programName}, + #{testMethod}, + #{scanNum}, + + + ) + + + + UPDATE tb_flow_info + + flow_index = #{flowIndex}, + flow_name = #{flowName}, + island_id_list = #{islandIdList}, + busy_code = #{busyCode}, + goods_code = #{goodsCode}, + goods_name = #{goodsName}, + check_code = #{checkCode}, + program_name = #{programName}, + test_method = #{testMethod}, + scan_num = #{scanNum}, + + update_id = #{updateId}, + + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE tb_flow_info + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/GoodsFlowStatusMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/GoodsFlowStatusMapper.xml new file mode 100644 index 0000000..04873f4 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/GoodsFlowStatusMapper.xml @@ -0,0 +1,64 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + goods_id, flow_id, island_id,dev_id, flow_sort, status + + + + INSERT INTO tb_goods_flow_status ( + , + create_id, create_time, update_id, update_time, del_sign + ) VALUES ( + #{goodsId}, #{flowId}, #{islandId},#{devId}, #{flowSort}, #{status}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + UPDATE tb_goods_flow_status + + goods_id = #{goodsId}, + flow_id = #{flowId}, + island_id = #{islandId}, + flow_sort = #{flowSort}, + dev_id = #{devId}, + status = #{status}, + update_id = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE tb_goods_flow_status + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/GoodsInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/GoodsInfoMapper.xml new file mode 100644 index 0000000..4286eee --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/GoodsInfoMapper.xml @@ -0,0 +1,97 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + goods_name, goods_type, income_time, good_from, good_batch,point_num ,goal_detect,bar_code,flow_id,goods_status, `desc` + + + + INSERT INTO tb_goods_info ( + , + create_id, create_time, update_id, update_time, del_sign + ) VALUES ( + #{goodsName}, #{goodsType}, #{incomeTime}, #{goodFrom}, #{goodBatch},#{pointNum},#{goalDetect}, #{barCode}, #{flowId}, #{goodsStatus}, #{desc}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + UPDATE tb_goods_info + + goods_name = #{goodsName}, + goods_type = #{goodsType}, + income_time = #{incomeTime}, + good_from = #{goodFrom}, + good_batch = #{goodBatch}, + point_num = #{pointNum}, + goal_detect = #{goalDetect}, + bar_code = #{barCode}, + flow_id = #{flowId}, + goods_status = #{goodsStatus}, + `desc` = #{desc}, + update_id = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE tb_goods_info + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/IslandInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/IslandInfoMapper.xml new file mode 100644 index 0000000..c2059a3 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/IslandInfoMapper.xml @@ -0,0 +1,75 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + island_name, island_code, plc_addr, island_logo, `desc` + + + + INSERT INTO tb_island_info ( + , + create_id, create_time, update_id, update_time, del_sign + ) VALUES ( + #{islandName}, #{islandCode},#{plcAddr}, #{islandLogo}, #{desc}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + UPDATE tb_island_info + + island_name = #{islandName}, + island_code = #{islandCode}, + plc_addr = #{plcAddr}, + island_logo = #{islandLogo}, + `desc` = #{desc}, + update_id = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE tb_island_info + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/IslandParamMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/IslandParamMapper.xml new file mode 100644 index 0000000..e662913 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/IslandParamMapper.xml @@ -0,0 +1,131 @@ + + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + island_id, step_id, param_name, param_type, param_unit, param_value, form_type + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INSERT INTO tb_island_param ( + , + create_id, create_time, update_id, update_time, del_sign + ) VALUES ( + #{islandId}, #{stepId}, #{paramName}, #{paramType}, #{paramUnit}, #{paramValue}, #{formType}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + + UPDATE tb_island_param + + island_id = #{islandId}, + step_id = #{stepId}, + param_name = #{paramName}, + param_type = #{paramType}, + param_unit = #{paramUnit}, + param_value = #{paramValue}, + form_type = #{formType}, + update_id = #{updateId}, + remark = #{remark}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE tb_island_param + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml new file mode 100644 index 0000000..fbfd66a --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/ManageLogMapper.xml @@ -0,0 +1,175 @@ + + + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + + log_name, log_type, log_writetime, log_content + + + + + + + + + + + + + + + + + + + + + + INSERT INTO sys_manage_log ( + + + log_name, + log_type, + log_writetime, + log_content, + + create_id, + create_time, + update_id, + update_time, + del_sign, + remark, + + ) VALUES ( + + + #{logName}, + #{logType}, + #{logWritetime}, + #{logContent}, + + #{createId}, + #{createTime}, + #{updateId}, + #{updateTime}, + #{delSign}, + #{remark}, + + ) + + + + + UPDATE sys_manage_log + + + log_name = #{logName}, + log_type = #{logType}, + log_writetime = #{logWritetime}, + log_content = #{logContent}, + + update_id = #{updateId}, + remark = #{remark}, + del_sign = #{delSign}, + + update_time = NOW() + + + WHERE id = #{id} + AND del_sign = 0 + + + + + UPDATE sys_manage_log + SET + del_sign = 1, + update_time = NOW(), + update_id = #{updateId} + WHERE id = #{id} + AND del_sign = 0 + + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml new file mode 100644 index 0000000..827f0c1 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/RecordInfoMapper.xml @@ -0,0 +1,60 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + record_name, record_type, record_status, record_content + + + + INSERT INTO tb_record_info ( + , + create_id, create_time, update_id, update_time, del_sign + ) VALUES ( + #{recordName}, #{recordType}, #{recordStatus}, #{recordContent}, + #{createId}, NOW(), #{updateId}, NOW(), 0 + ) + + + + UPDATE tb_record_info + + record_name = #{recordName}, + record_type = #{recordType}, + record_status = #{recordStatus}, + record_content = #{recordContent}, + update_id = #{updateId}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE tb_record_info + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/StepInfoMapper.xml b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/StepInfoMapper.xml new file mode 100644 index 0000000..6869197 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/main/resources/com/rczn/rcznautoplc/mapper/StepInfoMapper.xml @@ -0,0 +1,325 @@ + + + + + id, create_id, create_time, update_id, update_time, del_sign, remark + + + + island_id,dev_id,step_order ,step_name, step_desc,flow_id,param_name,param_type,param_unit,param_value,form_type + + + + INSERT INTO tb_step_info ( + + + create_id, + create_time, + update_id, + update_time, + remark, + + island_id, + dev_id, + step_order, + step_name, + step_desc, + flow_id, + param_name, + param_type, + param_unit, + param_value, + form_type, + + + + ) VALUES ( + + + #{createId}, + #{createTime}, + #{updateId}, + #{updateTime}, + #{remark}, + + #{islandId}, + #{devId}, + #{stepOrder}, + #{stepName}, + #{stepDesc}, + #{flowId}, + #{paramName}, + #{paramType}, + #{paramUnit}, + #{paramValue}, + #{formType}, + + + + ) + + + + + INSERT INTO tb_step_info ( + + create_id, + create_time, + update_id, + update_time, + remark, + del_sign, + island_id, + dev_id, + step_order, + step_name, + step_desc, + flow_id, + param_name, + param_type, + param_unit, + param_value, + form_type + + ) VALUES + + ( + + #{item.createId,jdbcType=BIGINT}, + NOW(), + #{item.updateId,jdbcType=BIGINT}, + NOW(), + #{item.remark}, + null, + 0, + #{item.islandId,jdbcType=INTEGER}, + null, + #{item.devId,jdbcType=INTEGER}, + null, + #{item.stepOrder,jdbcType=INTEGER}, + null, + #{item.stepName}, + null, + #{item.stepDesc}, + null, + #{item.flowId,jdbcType=INTEGER}, + null, + #{item.paramName}, + null, + #{item.paramType}, + null, + #{item.paramUnit}, + null, + #{item.paramValue}, + null, + #{item.formType}, + null, + + ) + + + + + + UPDATE tb_step_info + + update_id = #{item.updateId,jdbcType=BIGINT}, + remark = #{item.remark}, + + island_id = #{item.islandId,jdbcType=INTEGER}, + dev_id = #{item.devId,jdbcType=INTEGER}, + step_order = #{item.stepOrder,jdbcType=INTEGER}, + step_name = #{item.stepName}, + step_desc = #{item.stepDesc}, + flow_id = #{item.flowId,jdbcType=INTEGER}, + param_name = #{item.paramName}, + param_type = #{item.paramType}, + param_unit = #{item.paramUnit}, + param_value = #{item.paramValue}, + form_type = #{item.formType}, + + update_time = NOW() + + WHERE id = #{item.id,jdbcType=BIGINT} + AND del_sign = 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPDATE tb_step_info + + island_id = #{islandId}, + dev_id = #{devId}, + step_order = #{stepOrder}, + step_name = #{stepName}, + step_desc = #{stepDesc}, + update_id = #{updateId}, + remark = #{remark}, + flow_id = #{flowId}, + param_name = #{paramName}, + param_type = #{paramType}, + param_unit = #{paramUnit}, + param_value = #{paramValue}, + form_type = #{formType}, + update_time = NOW() + + WHERE id = #{id} AND del_sign = 0 + + + + UPDATE tb_step_info + SET del_sign = 1, update_time = NOW() + WHERE id = #{id} AND del_sign = 0 + + + + + UPDATE tb_step_info + SET del_sign = 1, update_time = NOW() + WHERE id in + + #{id} + + AND del_sign = 0 + + + + + + + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java b/rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java new file mode 100644 index 0000000..d230135 --- /dev/null +++ b/rc_autoplc_backend/rczn-autoplc/src/test/java/com/rczn/rcznautoplc/RcznAutoplcApplicationTests.java @@ -0,0 +1,13 @@ +package com.rczn.rcznautoplc; + +import org.testng.annotations.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RcznAutoplcApplicationTests { + +// @Test + void contextLoads() { + } + +} diff --git a/rc_autoplc_backend/rczn-common/.mvn/wrapper/maven-wrapper.properties b/rc_autoplc_backend/rczn-common/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..c0bcafe --- /dev/null +++ b/rc_autoplc_backend/rczn-common/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/rc_autoplc_backend/rczn-common/pom.xml b/rc_autoplc_backend/rczn-common/pom.xml new file mode 100644 index 0000000..2fa8c62 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/pom.xml @@ -0,0 +1,176 @@ + + + 4.0.0 + + com.rczn + Rc-autoplc-backend + 0.0.1-SNAPSHOT + ../pom.xml + + + rczn-common + rczn-common + rczn-common(公共模块:实体类、工具类、统一响应) + jar + + + + + + false + + + true + + ias-snapshots + Infinite Automation Snapshot Repository + https://maven.mangoautomation.net/repository/ias-snapshot/ + + + + true + + + false + + ias-releases + Infinite Automation Release Repository + https://maven.mangoautomation.net/repository/ias-release/ + + + + spring-milestones + Spring Milestones + https://repo.spring.io/milestone + + false + + + + spring-releases + Spring Releases + https://repo.spring.io/release + + + + + + + + org.projectlombok + lombok + true + + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + + jakarta.validation + jakarta.validation-api + + + + + org.apache.commons + commons-lang3 + + + + + org.springframework + spring-web + provided + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + + + + + + + + + + jakarta.servlet + jakarta.servlet-api + provided + + + + com.github.s7connector + s7connector + 2.1 + + + + + com.infiniteautomation + modbus4j + 3.0.3 + + + + org.apache.commons + commons-pool2 + 2.12.0 + + + + org.springframework + spring-context + provided + + + com.auth0 + java-jwt + ${jwt.version} + + + org.testng + testng + RELEASE + test + + + org.springframework.boot + spring-boot-test + test + + + org.junit.jupiter + junit-jupiter-api + test + + + + + org.springframework.boot + spring-boot-starter-websocket + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java new file mode 100644 index 0000000..f27034e --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/ModbusCmdConst.java @@ -0,0 +1,23 @@ +package com.rczn; + +/** + * modbus 指令常量enum + */ +public class ModbusCmdConst { + //下面是指令值: + //就绪 + public static final int plc_ready = 10; + //运行 + public static final int plc_run = 11; + //暂停 + public static final int plc_pause = 12; + //停止 + public static final int plc_stop = 10; + //故障复位 + public static final int plc_reset_error = 20; + //修改模式 + public static final int plc_set_model = 0; + //参数读取: + public static final int plc_read_param = 18; + // +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java new file mode 100644 index 0000000..870604d --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/AsyncThreadPoolConfig.java @@ -0,0 +1,40 @@ +package com.rczn.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 异步线程池配置(用于PLC数据读取的异步执行) + */ +@Configuration +@EnableAsync //开启异步任务 +public class AsyncThreadPoolConfig { + + /** + * 定义PLC专用线程池 + */ + @Bean(name = "plcAsyncExecutor") + public Executor plcAsyncExecutor(){ + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + // 核心线程数(根据业务调整) + executor.setCorePoolSize(5); + // 最大线程数 + executor.setMaxPoolSize(10); + // 队列容量 + executor.setQueueCapacity(20); + // 线程名前缀(便于日志排查) + executor.setThreadNamePrefix("PLC-Async-"); + // 线程空闲超时时间 + executor.setKeepAliveSeconds(60); + // 拒绝策略:队列满时由调用线程处理(避免任务丢失) + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + // 初始化线程池 + executor.initialize(); + return executor; + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java new file mode 100644 index 0000000..abeba08 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/config/WebSocketConfig.java @@ -0,0 +1,14 @@ +package com.rczn.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.socket.server.standard.ServerEndpointExporter; + +@Configuration +public class WebSocketConfig { + + @Bean + public ServerEndpointExporter serverEndpointExporter(){ + return new ServerEndpointExporter(); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/BaseBean.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/BaseBean.java new file mode 100644 index 0000000..e61368e --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/BaseBean.java @@ -0,0 +1,69 @@ +package com.rczn.domain; + +import org.springframework.format.annotation.DateTimeFormat; + +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; + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/PageBean.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/PageBean.java new file mode 100644 index 0000000..40e2c2c --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/PageBean.java @@ -0,0 +1,28 @@ +package com.rczn.domain; + +import java.util.List; + +//分页返回结果对象 +public class PageBean { + private Long total;//总条数 + private List items;//当前页数据集合 + + public PageBean() { + } + + public Long getTotal() { + return total; + } + + public void setTotal(Long total) { + this.total = total; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/Result.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/Result.java new file mode 100644 index 0000000..66a7d6f --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/domain/Result.java @@ -0,0 +1,55 @@ +package com.rczn.domain; + +//统一响应结果 +public class Result { + private Integer code;//业务状态码 0-成功 1-失败 + private String message;//提示信息 + private T data;//响应数据 + + //快速返回操作成功响应结果(带响应数据) + public static Result 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 success() { + return new Result(0, "操作成功", null); + } + + public static Result error(String message) { + return new Result(1, message, null); + } + + public Result(Integer code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java new file mode 100644 index 0000000..15f9a19 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/exception/GlobalException.java @@ -0,0 +1,16 @@ +package com.rczn.exception; + +import com.rczn.domain.Result; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalException { + + @ExceptionHandler(Exception.class) + public Result handleException(Exception e){ + e.printStackTrace(); + return Result.error(StringUtils.hasLength(e.getMessage())? e.getMessage() : "系统异常"); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/interceptors/LoginInterceptor.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/interceptors/LoginInterceptor.java new file mode 100644 index 0000000..dfb74f7 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/interceptors/LoginInterceptor.java @@ -0,0 +1,54 @@ +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.stereotype.Component; +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 { + // 1. 放行OPTIONS预检请求,直接返回200 OK,不做任何校验 + if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { + response.setStatus(HttpServletResponse.SC_OK); + // 手动添加跨域响应头(兜底) + response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); + response.setHeader("Access-Control-Allow-Credentials", "true"); + response.setHeader("Access-Control-Allow-Methods", "GET,POST,PATCH,PUT,DELETE,OPTIONS"); + response.setHeader("Access-Control-Allow-Headers", "*"); + response.setHeader("Access-Control-Max-Age", "3600"); + return true; // 直接放行,不执行后续拦截逻辑 + } + + try { + String token = request.getHeader("Authorization"); + String[] tokens = token.split(" "); + if(tokens.length>1){ + token = tokens[1]; + } + Map 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(); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java new file mode 100644 index 0000000..8af87df --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jUtils.java @@ -0,0 +1,380 @@ +package com.rczn.modbus; + +import com.serotonin.modbus4j.BatchRead; +import com.serotonin.modbus4j.BatchResults; +import com.serotonin.modbus4j.ModbusFactory; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import com.serotonin.modbus4j.ip.IpParameters; +import com.serotonin.modbus4j.locator.BaseLocator; +import com.serotonin.modbus4j.msg.ReadInputRegistersResponse; + +import java.util.Map; + +/** + * modbus通讯工具类,采用modbus4j实现 + * + * @author lxq + * @dependencies modbus4j-3.0.3.jar + * @website https://github.com/infiniteautomation/modbus4j + */ +public class Modbus4jUtils { + /** + * 工厂。 + */ + static ModbusFactory modbusFactory; + static { + if (modbusFactory == null) { + modbusFactory = new ModbusFactory(); + } + } + + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster() throws ModbusInitException { + IpParameters params = new IpParameters(); + params.setHost("localhost"); + params.setPort(502); + + // + // modbusFactory.createRtuMaster(params); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(params);//ASCII 协议 + + // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true) + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.setTimeout(3000); + master.setRetries(1); + master.init(); + + return master; + } + + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster(String ipAddr,Integer port) throws ModbusInitException { + IpParameters params = new IpParameters(); +// params.setHost("localhost"); + params.setHost(ipAddr); +// params.setPort(502); + params.setPort(port); + // + // modbusFactory.createRtuMaster(params); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(params);//ASCII 协议 + + // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true) + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.setTimeout(3000); + master.setRetries(1); + master.init(); + + return master; + } + + /** + * 获取和测试Master对象 + * @param ip + * @param port + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getAndTestMaster(String ip, Integer port) + throws ModbusInitException { + + ModbusMaster master = getMaster(ip, port); + + try { + // 随便读一个确定存在的寄存器 + BaseLocator locator = + BaseLocator.holdingRegister(1, 0, DataType.TWO_BYTE_INT_SIGNED); + + Number value = master.getValue(locator);// ⭐ 真正触发 TCP 连接 + System.out.println("value:"+value); + } catch (Exception e) { + master.destroy(); + throw new RuntimeException("PLC 连接失败:" + ip + ":" + port, e); + } + + return master; + } + + /** + * 读取[01 Coil Status 0x]类型 开关数据 + * + * @param slaveId + * slaveId + * @param offset + * 位置 + * @return 读取值 + * @throws ModbusTransportException + * 异常 + * @throws ErrorResponseException + * 异常 + * @throws ModbusInitException + * 异常 + */ + public static Boolean readCoilStatus(ModbusMaster modbusMaster,int slaveId, int offset) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 01 Coil Status + BaseLocator loc = BaseLocator.coilStatus(slaveId, offset); + Boolean value = modbusMaster.getValue(loc); + return value; + } + + /** + * 读取[02 Input Status 1x]类型 开关数据 + * + * @param slaveId + * @param offset + * @return + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static Boolean readInputStatus(ModbusMaster modbusMaster,int slaveId, int offset) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 02 Input Status + BaseLocator loc = BaseLocator.inputStatus(slaveId, offset); + Boolean value = modbusMaster.getValue(loc); + return value; + } + + /** + * 读取[03 Holding Register类型 2x]模拟量数据 + * + * @param slaveId + * slave Id + * @param offset + * 位置 + * @param dataType + * 数据类型,来自com.serotonin.modbus4j.code.DataType + * @return + * @throws ModbusTransportException + * 异常 + * @throws ErrorResponseException + * 异常 + * @throws ModbusInitException + * 异常 + */ + public static Number readHoldingRegister(ModbusMaster modbusMaster,int slaveId, int offset, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 03 Holding Register类型数据读取 + BaseLocator loc = BaseLocator.holdingRegister(slaveId, offset, dataType); + Number value = modbusMaster.getValue(loc); + return value; + } + + /** + * 读取[04 Input Registers 3x]类型 模拟量数据 + * + * @param modbusMaster + * modbusMaster modbus连接对象 + * @param slaveId + * slaveId 设备号 + * @param offset + * 位置 + * @param dataType + * 数据类型,来自com.serotonin.modbus4j.code.DataType + * @return 返回结果 + * @throws ModbusTransportException + * 异常 + * @throws ErrorResponseException + * 异常 + * @throws ModbusInitException + * 异常 + */ + public static Number readInputRegisters(ModbusMaster modbusMaster,int slaveId, int offset, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 04 Input Registers类型数据读取 + BaseLocator loc = BaseLocator.inputRegister(slaveId, offset, dataType); + Number value = modbusMaster.getValue(loc); + return value; + } + + /** + * 批量读取使用方法 + * + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static BatchResults batchRead(ModbusMaster modbusMaster,int slaveId, int offset, int dataType) throws ModbusTransportException, ErrorResponseException, ModbusInitException { + + BatchRead batch = new BatchRead(); + + batch.addLocator(0, BaseLocator.holdingRegister(1, 1, DataType.FOUR_BYTE_FLOAT)); + batch.addLocator(1, BaseLocator.inputStatus(1, 0)); + + batch.setContiguousRequests(false); + BatchResults results = modbusMaster.send(batch); + System.out.println(results.getValue(0)); + System.out.println(results.getValue(1)); + return results; + } + + /** + * 连续读取多个 Holding Register + */ + public static Number[] readHoldingRegisters( + ModbusMaster master, + int slaveId, + int startOffset, + int count, + int dataType) + throws ModbusTransportException, ErrorResponseException { + + Number[] values = new Number[count]; + + for (int i = 0; i < count; i++) { + BaseLocator locator = + BaseLocator.holdingRegister(slaveId, startOffset + i, dataType); + + values[i] = master.getValue(locator); + } + + return values; + } + + /** + * 连续读取多个 Input Register + */ + public static Number[] readInputRegistersBatch( + ModbusMaster master, + int slaveId, + int startOffset, + int count, + int dataType) + throws ModbusTransportException, ErrorResponseException { + + Number[] values = new Number[count]; + + for (int i = 0; i < count; i++) { + BaseLocator locator = + BaseLocator.inputRegister(slaveId, startOffset + i, dataType); + + values[i] = master.getValue(locator); + } + + return values; + } + + /** + * 批量读取多个 Holding Register(高性能) + */ + public static BatchResults batchReadHoldingRegisters( + ModbusMaster master, + int slaveId, + int[] offsets, + int dataType) + throws ModbusTransportException, ErrorResponseException { + + BatchRead batch = new BatchRead<>(); + + for (int i = 0; i < offsets.length; i++) { + batch.addLocator(i, + BaseLocator.holdingRegister(slaveId, offsets[i], dataType)); + } + + batch.setContiguousRequests(true); // 连续优化 + return master.send(batch); + } + + /** + * 混合批量读取 + */ + public static BatchResults batchReadMixed( + ModbusMaster master, + int slaveId) + throws ModbusTransportException, ErrorResponseException { + + BatchRead batch = new BatchRead<>(); + + batch.addLocator(0, + BaseLocator.holdingRegister(slaveId, 0, DataType.FOUR_BYTE_FLOAT)); + + batch.addLocator(1, + BaseLocator.holdingRegister(slaveId, 2, DataType.TWO_BYTE_INT_SIGNED)); + + batch.addLocator(2, + BaseLocator.coilStatus(slaveId, 0)); + + batch.setContiguousRequests(false); + + return master.send(batch); + } + + + public static void close(ModbusMaster master) { + if (master != null) { + master.destroy(); + } + } + + public static void main(String[] args) { + try { + ModbusMaster master = getMaster("192.178.111.123", 501); + + } catch (ModbusInitException e) { + throw new RuntimeException(e); + } + } + /** + * 测试 + * + * @param args + */ + public static void main1(String[] args) { + try { + ModbusMaster modbusMaster = getMaster(); + // 01测试 +// Boolean v011 = readCoilStatus(modbusMaster,1, 0); +// Boolean v012 = readCoilStatus(modbusMaster,1, 1); +// Boolean v013 = readCoilStatus(modbusMaster,1, 6); +// System.out.println("v011:" + v011); +// System.out.println("v012:" + v012); +// System.out.println("v013:" + v013); +// // 02测试 +// Boolean v021 = readInputStatus(modbusMaster,1, 0); +// Boolean v022 = readInputStatus(modbusMaster,1, 1); +// Boolean v023 = readInputStatus(modbusMaster,1, 2); +// System.out.println("v021:" + v021); +// System.out.println("v022:" + v022); +// System.out.println("v023:" + v023); +// +// // 03测试 +// Number v031 = readHoldingRegister(modbusMaster,1, 1, DataType.FOUR_BYTE_FLOAT);// 注意,float +// Number v032 = readHoldingRegister(modbusMaster,1, 3, DataType.FOUR_BYTE_FLOAT);// 同上 +// System.out.println("v031:" + v031); +// System.out.println("v032:" + v032); + + // 04测试 +// Number v041 = readInputRegisters(modbusMaster,1, 0, DataType.FOUR_BYTE_FLOAT);// + Number v041 = readInputRegisters(modbusMaster,1, 0, DataType.FOUR_BYTE_INT_UNSIGNED);// + Number v042 = readInputRegisters(modbusMaster,1, 2, DataType.FOUR_BYTE_FLOAT);// + System.out.println("v041:" + v041); + System.out.println("v042:" + v042); + + Number vff = readHoldingRegister(modbusMaster,1,0,DataType.TWO_BYTE_INT_SIGNED); + System.out.println("vff:" + vff); + Number vff2 = readHoldingRegister(modbusMaster,1,2,DataType.TWO_BYTE_INT_SIGNED); + System.out.println("vff2:" + vff2); + // 批量读取 +// batchRead(); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java new file mode 100644 index 0000000..ff16e21 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/modbus/Modbus4jWriteUtils.java @@ -0,0 +1,247 @@ +package com.rczn.modbus; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.serotonin.modbus4j.ModbusFactory; +import com.serotonin.modbus4j.ModbusMaster; +import com.serotonin.modbus4j.code.DataType; +import com.serotonin.modbus4j.exception.ErrorResponseException; +import com.serotonin.modbus4j.exception.ModbusInitException; +import com.serotonin.modbus4j.exception.ModbusTransportException; +import com.serotonin.modbus4j.ip.IpParameters; +import com.serotonin.modbus4j.locator.BaseLocator; +import com.serotonin.modbus4j.msg.ModbusResponse; +import com.serotonin.modbus4j.msg.WriteCoilRequest; +import com.serotonin.modbus4j.msg.WriteCoilResponse; +import com.serotonin.modbus4j.msg.WriteCoilsRequest; +import com.serotonin.modbus4j.msg.WriteCoilsResponse; +import com.serotonin.modbus4j.msg.WriteRegisterRequest; +import com.serotonin.modbus4j.msg.WriteRegisterResponse; +import com.serotonin.modbus4j.msg.WriteRegistersRequest; + +/** + * modbus4j写入数据 + * + * @author xq + * + */ +public class Modbus4jWriteUtils { + static Log log = LogFactory.getLog(Modbus4jWriteUtils.class); + /** + * 工厂。 + */ + static ModbusFactory modbusFactory; + static { + if (modbusFactory == null) { + modbusFactory = new ModbusFactory(); + } + } + + /** + * 获取tcpMaster + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster() throws ModbusInitException { + IpParameters params = new IpParameters(); + params.setHost("localhost"); + params.setPort(502); + + ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false); + tcpMaster.init(); + + return tcpMaster; + } + /** + * 获取master + * + * @return + * @throws ModbusInitException + */ + public static ModbusMaster getMaster(String ipAddr,Integer port) throws ModbusInitException { + IpParameters params = new IpParameters(); +// params.setHost("localhost"); + params.setHost(ipAddr); +// params.setPort(502); + params.setPort(port); + // + // modbusFactory.createRtuMaster(params); //RTU 协议 + // modbusFactory.createUdpMaster(params);//UDP 协议 + // modbusFactory.createAsciiMaster(params);//ASCII 协议 + + // 采用 Modbus RTU over TCP/IP,第二个参数为 true,即 modbusFactory.createTcpMaster(params, true) + ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议 + master.init(); + + return master; + } + + /** + * 写 [01 Coil Status(0x)]写一个 function ID = 5 + * + * @param slaveId + * slave的ID + * @param writeOffset + * 位置 + * @param writeValue + * 值 + * @return 是否写入成功 + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeCoil(ModbusMaster tcpMaster,int slaveId, int writeOffset, boolean writeValue) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求 + WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue); + // 发送请求并获取响应对象 + WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request); + if (response.isException()) { + return false; + } else { + return true; + } + } + + /** + * 写[01 Coil Status(0x)] 写多个 function ID = 15 + * + * @param slaveId + * slaveId + * @param startOffset + * 开始位置 + * @param bdata + * 写入的数据 + * @return 是否写入成功 + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeCoils(ModbusMaster tcpMaster,int slaveId, int startOffset, boolean[] bdata) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求 + WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bdata); + // 发送请求并获取响应对象 + WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request); + if (response.isException()) { + return false; + } else { + return true; + } + + } + + /*** + * 写[03 Holding Register(4x)] 写一个 function ID = 6 + * + * @param slaveId + * @param writeOffset + * @param writeValue + * @return + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeRegister(ModbusMaster tcpMaster,int slaveId, int writeOffset, short writeValue) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求对象 + WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue); + WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request); + if (response.isException()) { + log.error(response.getExceptionMessage()); + return false; + } else { + return true; + } + + } + + /** + * + * 写入[03 Holding Register(4x)]写多个 function ID=16 + * + * @param slaveId + * modbus的slaveID + * @param startOffset + * 起始位置偏移量值 + * @param sdata + * 写入的数据 + * @return 返回是否写入成功 + * @throws ModbusTransportException + * @throws ModbusInitException + */ + public static boolean writeRegisters(ModbusMaster tcpMaster,int slaveId, int startOffset, short[] sdata) + throws ModbusTransportException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 创建请求对象 + WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sdata); + // 发送请求并获取响应对象 + ModbusResponse response = tcpMaster.send(request); + if (response.isException()) { + log.error(response.getExceptionMessage()); + return false; + } else { + return true; + } + } + + /** + * 写入数字类型的模拟量(如:写入Float类型的模拟量、Double类型模拟量、整数类型Short、Integer、Long) + * + * @param slaveId + * @param offset + * @param value + * 写入值,Number的子类,例如写入Float浮点类型,Double双精度类型,以及整型short,int,long + * @param dataType + * ,com.serotonin.modbus4j.code.DataType + * @throws ModbusTransportException + * @throws ErrorResponseException + * @throws ModbusInitException + */ + public static void writeHoldingRegister(ModbusMaster tcpMaster,int slaveId, int offset, Number value, int dataType) + throws ModbusTransportException, ErrorResponseException, ModbusInitException { + // 获取master +// ModbusMaster tcpMaster = getMaster(); + // 类型 + BaseLocator locator = BaseLocator.holdingRegister(slaveId, offset, dataType); + tcpMaster.setValue(locator, value); + } + + public static void main1(String[] args) { + try { + ModbusMaster modbusMaster = getMaster(); + //@formatter:off + // 测试01 +// boolean t01 = writeCoil(1, 0, true); +// System.out.println("T01:" + t01); + + // 测试02 +// boolean t02 = writeCoils(1, 0, new boolean[] { true, false, true }); +// System.out.println("T02:" + t02); + + // 测试03 +// short v = -3; +// boolean t03 = writeRegister(1, 0, v); +// System.out.println("T03:" + t03); + // 测试04 +// boolean t04 = writeRegisters(1, 0, new short[] { -3, 3, 9 }); +// System.out.println("t04:" + t04); + + writeRegister(modbusMaster,1,2,(short) 3); + //写模拟量 + writeHoldingRegister(modbusMaster,1,0, 999, DataType.TWO_BYTE_INT_SIGNED); + + //@formatter:on + } catch (Exception e) { + e.printStackTrace(); + } + + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java new file mode 100644 index 0000000..a5056e0 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/PLCData.java @@ -0,0 +1,56 @@ +package com.rczn.plc; + + +import com.github.s7connector.api.annotation.S7Variable; +import com.github.s7connector.impl.utils.S7Type; +import lombok.Data; + +@Data +public class PLCData { + + /** + * type是这个点位在PLC中设置的类型,源码会解析其长度; + * byteOffset对应PLC偏移量中的整数部分; + * bitOffset指偏移量的小数部分,bitOffset指第几个bit. + * byteOffset和bitOffset 也可理解为返回的byte[]中第byteOffset到bitOffset + */ + @S7Variable(type= S7Type.BOOL,byteOffset = 0,bitOffset = 0) + public Boolean data10;//bool型的值不要用private + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 1) + public Boolean data11; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 2) + public Boolean data12; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 3) + public Boolean data13; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 4) + public Boolean data14; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 5) + public Boolean data15; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 6) + public Boolean data16; + + @S7Variable(type=S7Type.BOOL,byteOffset = 0,bitOffset = 7) + public Boolean data17; + + @S7Variable(type=S7Type.BYTE,byteOffset = 1,bitOffset = 0) + public Byte dataB1; + + @S7Variable(type=S7Type.STRING,byteOffset = 2,bitOffset = 0) + public String dataS1; + + @S7Variable(type=S7Type.STRING,byteOffset = 258,bitOffset = 40) + public String dataS2; + + @S7Variable(type=S7Type.STRING,byteOffset = 514,bitOffset = 40) + public String dataS3; + + @S7Variable(type=S7Type.STRING,byteOffset = 770) + public String dataS4; + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java new file mode 100644 index 0000000..f583fad --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcClient.java @@ -0,0 +1,102 @@ +package com.rczn.plc; + +import com.github.s7connector.api.DaveArea; +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.github.s7connector.impl.serializer.converter.StringConverter; + +import java.util.Scanner; + + +/** + * @author 木春 + * @className S7PlcClient.java + * @Form no + * @Description ToDo + * @createTime 2022 年 11 月 18 日 21 21:40:49 + **/ +public class S7PlcClient { + public static void main(String[] args) throws InterruptedException { + + //初始化 创建一个链接对象 + S7Connector connector = + S7ConnectorFactory + .buildTCPConnector() + .withHost("192.168.0.105") // + .withRack(0) //架机号 可选 + .withSlot(1) //插槽号 可选 + .build(); + +// 写数据线程 + new Thread(new Runnable() { + @Override + public void run() { + java_write_plc(connector);//写数据 + } + }).start(); + +// 读数据线程 + new Thread(new Runnable() { + @Override + public void run() { + java_read_plc(connector);//调用读取数据方法 + } + }).start(); + + } + + //读取数据 + public static void java_read_plc(S7Connector connector) { + /* 读取数据方法*/ + byte[] PlcData = null; + String str = null; + String str1 = null; + StringConverter converter = null; + String extract1 = null; + //循环读取 + while (true) { + PlcData = connector.read( + DaveArea.DB, //选择区块 + 1, // 区块编号 + 255, //长度 + 260); //偏移地址 + + converter = new StringConverter();//字符串转换 + + //将读取到的数据转换成字符串类型 读取到的数据转换后 + extract1 = converter.extract(String.class, PlcData, 0, 0); + //比对两次数据是否一样 不一样就打印 + if (!(extract1.equals(str1))) { + System.out.println(" "); + System.out.println("接收plc的数据为 = " + extract1); + str1 = extract1; + //plc发送 qu 就结束退出程序 + if (extract1.equals("qu")) { + break; + } + } + } + } + + //发送数据 + public static void java_write_plc(S7Connector connector) { + while (true) { + /*发送数据*/ + String data = null; +// byte[] bytes = null; + String input = null; + Scanner sc = new Scanner(System.in); + System.out.print("请输入要发送的数据: "); + input = sc.nextLine(); + + String data_Baotou = " ";//数据包头 两个空格 + String data_tail = " ";//包尾 六个空格 + data = data_Baotou + input + data_tail;//发送的数据 + byte[] bytes = new byte[input.length()]; + bytes = data.getBytes();//转字节 + System.out.println("发送的字节长度 = " + bytes.length);//发送的字节长度 + connector.write(DaveArea.DB, 1, 4, bytes);//写入到 DB1 偏移量为4的变量 + System.out.println("发送的数据为 = " + data); + } + } +} \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java new file mode 100644 index 0000000..35460dd --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc/S7PlcCommun.java @@ -0,0 +1,131 @@ +package com.rczn.plc; + +import com.github.s7connector.api.DaveArea; +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.S7Serializer; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.github.s7connector.api.factory.S7SerializerFactory; + +import java.io.IOException; + +public class S7PlcCommun { + + + /** + * 初始化PLC连接 + */ + public S7Connector initConnect(){ + //PLC地址 + String ipAddress = "192.168.1.2"; + //默认端口 + Integer port = 102; + S7Connector s7Connector = S7ConnectorFactory + .buildTCPConnector() + .withHost(ipAddress) + .withPort(port) + .withTimeout(10000) //连接超时时间 + .withRack(0) + .withSlot(1) + .build(); + S7Serializer s7Serializer2L = S7SerializerFactory.buildSerializer(s7Connector); + return s7Connector; + + } + + /** + * 读取PLC中的数据 + * + **/ + public void readPlcData() { + + S7Connector s7Connector = initConnect(); + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB地址,若plc中是DB1000,则填1000 + //第三个参数:数据长度, <=plc中两个偏移量的间隔,当前偏移量为1000,下一个地址偏移量为1100,则长度可填 0-1000; + //第四个参数:偏移量 + byte[] barcodeByte = s7Connector.read(DaveArea.DB, 1000, 2, 0); + //由于当前PLC地址中保存的数据类型是字符串类型,所以直接将byte[] 转成string即可; + String barcode =byteToHex(barcodeByte); + System.out.println(barcode); + try { + s7Connector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * byte数组转hex + * @param bytes + * @return + */ + public static String byteToHex(byte[] bytes){ + String strHex = ""; + StringBuilder sb = new StringBuilder(""); + for (int n = 0; n < bytes.length; n++) { + strHex = Integer.toHexString(bytes[n] & 0xFF); + sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示,位数不够,高位补0 + } + return sb.toString().trim(); + } + + /** + * 向PLC中写数据 + * + **/ + public void writePlcData() { + + S7Connector s7Connector = initConnect(); + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[],由于plc中地址的数据类型是word,所以写入的数据必须是4位的16进制数据 + s7Connector.write(DaveArea.DB,1000, 4,hexStringToBytes("0001")); + + try { + s7Connector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * 将16进制字符串转成二进制数组 + * @param hexString + * @return + */ + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || hexString.equals("")) { + return null; + } + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + + /** + * 将单个16进制字符转换为对应的字节值(核心补充方法) + * @param c 16进制字符(0-9、A-F) + * @return 对应的字节值(0-15) + */ + private static byte charToByte(char c) { + // 0-9 对应 48-57 + if (c >= '0' && c <= '9') { + return (byte) (c - '0'); + } + // A-F 对应 65-70 + else if (c >= 'A' && c <= 'F') { + return (byte) (c - 'A' + 10); + } + // 非法字符抛出异常(避免静默错误) + else { + throw new IllegalArgumentException("非法的16进制字符:" + c); + } + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java new file mode 100644 index 0000000..bf51222 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/plc_common/S7ConnectorPLC.java @@ -0,0 +1,220 @@ +package com.rczn.plc_common; + +import com.github.s7connector.api.DaveArea; +import com.github.s7connector.api.S7Connector; +import com.github.s7connector.api.factory.S7ConnectorFactory; +import com.github.s7connector.impl.serializer.converter.BitConverter; +import com.github.s7connector.impl.serializer.converter.IntegerConverter; +import com.github.s7connector.impl.serializer.converter.RealConverter; +import com.github.s7connector.impl.serializer.converter.StringConverter; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; + +public class S7ConnectorPLC { + public S7Connector initConnect(String ipAddress,int port,int rack,int slot) { + //默认端口 +// 创建与PLC的链接 + S7Connector connector = S7ConnectorFactory.buildTCPConnector() + .withHost(ipAddress) + .withPort(port) + .withRack(0) // 架机号 可选,建议选择,可能会报错 + .withSlot(2) // 插槽号 可选,建议选择,可能会报错 + .build(); + return connector; + } + + public static void main1(String[] args) { + S7ConnectorPLC s7ConnectorPLC = new S7ConnectorPLC(); + S7Connector connector = s7ConnectorPLC.initConnect("192.168.110.123", 102, 0, 2); +// s7ConnectorPLC.Java_To_write(connector); + s7ConnectorPLC.Cyclic_readT(connector); + } + + //Int类型的封装类 用来转义 + private static IntegerConverter intCon = new IntegerConverter(); + //String... + private static StringConverter strCon = new StringConverter(); + //Boolean... + private static BitConverter boolCon = new BitConverter(); + //real实数浮点... + private static RealConverter realCon = new RealConverter(); + + //获取到的数据存储 + public boolean in_bool = false;//bool + public Integer in_int = null;//int + public String in_String = "";//string + public double in_real = 0.0;//real + + public void Cyclic_read(S7Connector connector) { + + byte[] PlcData = null; + //读取bool型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 1, // 数据值长度 boolean长度1 + 0); // 开始位置偏移量 + Boolean extract_bool = boolCon.extract(Boolean.class, PlcData, 0, 0);//接收转换的数值 + in_bool = extract_bool;//赋值给全局变量 + +// 读取整型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 2, // 数据值长度 int长度2 + 2); // 开始位置 偏移量 + Integer extract_int = intCon.extract(Integer.class, PlcData, 0, 0); + in_int = extract_int; + +// 读取字符串型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 16, // 数据值长度 String最小3 随值长度增加 + 4); // 开始位置偏移量 + String extract_string = strCon.extract(String.class, PlcData, 0, 0); + in_String = extract_string; + +// 读取小数型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 4, // 数据值长度 double长度4 + 260); //偏移量 + Double num1 = realCon.extract(Double.class, PlcData, 0, 0); + /* BigDecimal bd1 = new BigDecimal(num1); + System.out.println("转换real浮点= " + bd1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());*/ + in_real = num1; + + try { + connector.close();//关闭链接 + } catch (IOException e) { + e.printStackTrace(); + } + + } + public void Cyclic_readT(S7Connector connector) { + + byte[] PlcData = null; + //读取bool型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 1, // 数据值长度 boolean长度1 + 0); // 开始位置偏移量 + Boolean extract_bool = boolCon.extract(Boolean.class, PlcData, 0, 0);//接收转换的数值 + in_bool = extract_bool;//赋值给全局变量 + +// 读取整型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 2, // 数据值长度 int长度2 + 2); // 开始位置 偏移量 + Integer extract_int = intCon.extract(Integer.class, PlcData, 0, 0); + in_int = extract_int; + +// 读取字符串型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 16, // 数据值长度 String最小3 随值长度增加 + 4); // 开始位置偏移量 + String extract_string = strCon.extract(String.class, PlcData, 0, 0); + in_String = extract_string; + +// 读取小数型 + PlcData = connector.read(DaveArea.DB, // 选择数据区块 + 5, // 区块编号 + 4, // 数据值长度 double长度4 + 260); //偏移量 + Double num1 = realCon.extract(Double.class, PlcData, 0, 0); + /* BigDecimal bd1 = new BigDecimal(num1); + System.out.println("转换real浮点= " + bd1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());*/ + in_real = num1; + + try { + connector.close();//关闭链接 + } catch (IOException e) { + e.printStackTrace(); + } + + } + public void Java_To_write(S7Connector connector) { + byte[] bytes = null; + + boolean out_boolen = true; +// bytes = S7Type.BOOL; +// connector.write(DaveArea.DB, 5, 264, bytes); + +// 向plc中写int整型数据 +// 向PLC中写短整型(2字节,对应PLC INT类型)数据 + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] + short out_int = 15; + bytes = ByteBuffer.allocate(2).putShort(out_int).array(); + connector.write(DaveArea.DB, 5, 266, bytes); + +// 向PLC中写整型(4字节,对应PLC DINT类型)数据 + int data=15; + bytes = ByteBuffer.allocate(4).putInt(data).array(); + connector.write(DaveArea.DB,5, 528,bytes); + + +// 写入字符串 + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] ,总长度为10的话,有效数据只能是10-8,第一位代表总长,第二位,代表有效数据字节 + String out_string = "helloPlc"; + int writeStrLength = 10;//地址块大小 + byte[] writeBytes = new byte[writeStrLength]; + writeBytes[0] = (byte) writeStrLength;//写入本字符串块总宽度 + out_string = out_string.trim();//清除掉两边的空串 + int availableEffectCharLength = 0;//有效字符数控制 + if (out_string.length() > writeStrLength - 2) {//>writeStrLength-2 截断到最大有效数据位 + availableEffectCharLength = writeStrLength - 2; + + } else {//<=writeStrLength-2 + availableEffectCharLength = out_string.length(); + } + writeBytes[1] = (byte) availableEffectCharLength;//写入有效字节数 + byte[] strBytes = out_string.getBytes(StandardCharsets.US_ASCII); + for (int i = 0; i < availableEffectCharLength; i++) { + writeBytes[i + 2] = strBytes[i]; + } + connector.write(DaveArea.DB, 5, 268, writeBytes); + + + /** + * 写入PLC中的浮点型数据 + * java float : plc Real 4 字节 + * java double : plc LReal 8 字节 + **/ + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] + float out_real= 5.54F; + bytes = ByteBuffer.allocate(4).putFloat(out_real).array(); + connector.write(DaveArea.DB,5, 524,bytes); + + /** + * 写入PLC中的浮点型LREAL(java中是double)数据 + * java float : plc Real 4 字节 + * java double : plc LReal 8 字节 + **/ + //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB + //第二个参数:DB块地址,若plc中是DB1000,则填1000 + //第三个参数:偏移量 + //第四个参数:写入的数据 二进制数组byte[] + float out_Lreal= 15.56F; + bytes = ByteBuffer.allocate(8).putDouble(out_Lreal).array(); + connector.write(DaveArea.DB,5, 532,bytes); + + + try { + connector.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java new file mode 100644 index 0000000..70aa3c0 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestCrc.java @@ -0,0 +1,22 @@ +package com.rczn.task; + +import java.time.LocalDateTime; + +public class TestCrc { + public static void main(String[] args) throws CloneNotSupportedException { + LocalDateTime localDateTime = LocalDateTime.now(); + Video v1 = new Video("123", localDateTime); + Video v2 = (Video) v1.clone(); + + System.out.println(v1); + System.out.println(v2); + System.out.println("==================================="); + + localDateTime.minusDays(10); + v1.setName("vvvvvv"); + + System.out.println(v1); + System.out.println(v2); + System.out.println("===============12312312312===================="); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java new file mode 100644 index 0000000..6c93bc0 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/TestTask.java @@ -0,0 +1,17 @@ +package com.rczn.task; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +public class TestTask { + Log log = LogFactory.getLog(TestTask.class); + + @Scheduled(cron = "0 0/30 * * * ?") + public void test() { + System.out.println("This is a test task."); + log.info("This is a test task."); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java new file mode 100644 index 0000000..2914449 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/task/Video.java @@ -0,0 +1,46 @@ +package com.rczn.task; + +import java.time.LocalDateTime; + +public class Video implements Cloneable{ + private String name; + private LocalDateTime createTime; + + public Video() { + + } + + public Video(String name, LocalDateTime createTime) { + this.name = name; + this.createTime = createTime; + } + + @Override + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + @Override + public String toString() { + return "Video{" + + "name='" + name + '\'' + + ", createTime=" + createTime + + '}'; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public LocalDateTime getCreateTime() { + return createTime; + } + + public void setCreateTime(LocalDateTime createTime) { + this.createTime = createTime; + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java new file mode 100644 index 0000000..b9cb240 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/BeanFactoryUtils.java @@ -0,0 +1,22 @@ +package com.rczn.utils; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.stereotype.Component; + +@Component +public class BeanFactoryUtils implements BeanFactoryPostProcessor { + + private static ConfigurableListableBeanFactory beanFactory; + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory factory) throws BeansException { + BeanFactoryUtils.beanFactory = factory; + } + + // 获取Bean + public static T getBean(Class clazz) { + return beanFactory.getBean(clazz); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/JwtUtil.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/JwtUtil.java new file mode 100644 index 0000000..082a819 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/JwtUtil.java @@ -0,0 +1,37 @@ +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 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 parseToken(String token) { + return JWT.require(Algorithm.HMAC256(KEY)) + .build() + .verify(token) + .getClaim("claims") + .asMap(); + } + + public static void main(String[] args) { + String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsicGVybWlzc2lvbnMiOlsiMTExMSIsIjIyMiIsIjU1NSJdLCJpZCI6MywidXNlcm5hbWUiOiJzdHJpbmcifSwiZXhwIjoxNzc2NzE2NzAyfQ.ynjs9Ys0CxoZjRstjz3mjr3c6NYMFiV3MmTGQYpJmKQ";//genToken(null); + System.out.println(token); + Map claims = parseToken(token); + System.out.println(claims); + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/Md5Util.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/Md5Util.java new file mode 100644 index 0000000..0026c74 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/Md5Util.java @@ -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); + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/ThreadLocalUtil.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/ThreadLocalUtil.java new file mode 100644 index 0000000..f923ea6 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/utils/ThreadLocalUtil.java @@ -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 get(){ + return (T) THREAD_LOCAL.get(); + } + + //存储键值对 + public static void set(Object value){ + THREAD_LOCAL.set(value); + } + + + //清除ThreadLocal 防止内存泄漏 + public static void remove(){ + THREAD_LOCAL.remove(); + } +} diff --git a/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java new file mode 100644 index 0000000..8fde0d5 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/java/com/rczn/websocket/WebSocketServer.java @@ -0,0 +1,75 @@ +package com.rczn.websocket; + + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.websocket.*; +import jakarta.websocket.server.PathParam; +import jakarta.websocket.server.ServerEndpoint; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.concurrent.CopyOnWriteArraySet; + +@Component +@ServerEndpoint("/websocket/{userId}") +public class WebSocketServer { + Log log = LogFactory.getLog(WebSocketServer.class); + + //springboot自带json转换器 + private static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + //存放每个连接对象 + private static CopyOnWriteArraySet webSockets = new CopyOnWriteArraySet<>(); + private Session session; + private Long userId; + + /** + * 连接建立成功调用的方法 + * @param session + * @param userId + */ + @OnOpen + public void onOpen(Session session, @PathParam("userId") Long userId) { + this.session = session; + this.userId = userId; + webSockets.add(this); + log.info("有新连接加入!当前在线人数为" + webSockets.size()); + } + + /** + * 连接关闭调用的方法 + */ + @OnClose + public void onClose(){ + webSockets.remove(this); + log.info("有连接关闭!当前在线人数为" + webSockets.size()); + } + + /** + * 收到客户端消息后调用的方法 + * @OnMessage + * @param message 客户端发送过来的消息 + * @param session + */ + @OnMessage + public void onMessage(String message,Session session){ + log.info("收到来自客户端的消息:" + message); + } + + @OnError + public void onError(Session session, Throwable error) { + log.error("发生错误:"+error.getStackTrace()); + } + + /** + * 发送消息 + * @param message + * @throws IOException + */ + public void sendMessage(String message) throws IOException { + this.session.getBasicRemote().sendText(message); + } + +} diff --git a/rc_autoplc_backend/rczn-common/src/main/resources/application-common.yml b/rc_autoplc_backend/rczn-common/src/main/resources/application-common.yml new file mode 100644 index 0000000..71923ab --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/main/resources/application-common.yml @@ -0,0 +1,12 @@ +##spring.application.name=rczn-common +#spring: +# ai: +# openai: +# api-key: "sk-b2b55f0bc7e140668e0326c0cc7a86df" #sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +# base-url: "https://api.deepseek.com" +# chat: +# options: +# model: "deepseek-chat" +# # 关键:给语音模型也配置上,就不报错了 +# speech: +# api-key: "sk-b2b55f0bc7e140668e0326c0cc7a86df" \ No newline at end of file diff --git a/rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java b/rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java new file mode 100644 index 0000000..66dc009 --- /dev/null +++ b/rc_autoplc_backend/rczn-common/src/test/java/com/rczn/rczncommon/RcznCommonApplicationTests.java @@ -0,0 +1,13 @@ +package com.rczn.rczncommon; + +//import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class RcznCommonApplicationTests { + +// @Test + void contextLoads() { + } + +} diff --git a/rc_autoplc_front/.env.development b/rc_autoplc_front/.env.development new file mode 100644 index 0000000..4d37822 --- /dev/null +++ b/rc_autoplc_front/.env.development @@ -0,0 +1 @@ +VITE_API_URL=http://223.71.122.54:9090 diff --git a/rc_autoplc_front/.env.production b/rc_autoplc_front/.env.production new file mode 100644 index 0000000..4d37822 --- /dev/null +++ b/rc_autoplc_front/.env.production @@ -0,0 +1 @@ +VITE_API_URL=http://223.71.122.54:9090 diff --git a/rc_autoplc_front/.gitignore b/rc_autoplc_front/.gitignore new file mode 100644 index 0000000..a3f7a51 --- /dev/null +++ b/rc_autoplc_front/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +.eslintcache + +# Cypress +/cypress/videos/ +/cypress/screenshots/ + +# Vitest +__screenshots__/ diff --git a/rc_autoplc_front/.vscode/extensions.json b/rc_autoplc_front/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/rc_autoplc_front/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/rc_autoplc_front/README.md b/rc_autoplc_front/README.md new file mode 100644 index 0000000..715c505 --- /dev/null +++ b/rc_autoplc_front/README.md @@ -0,0 +1,42 @@ +# rc_autoplc_front + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Recommended Browser Setup + +- Chromium-based browsers (Chrome, Edge, Brave, etc.): + - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) + - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters) +- Firefox: + - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/) + - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/) + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vite.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` diff --git a/rc_autoplc_front/env.d.ts b/rc_autoplc_front/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/rc_autoplc_front/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/rc_autoplc_front/index.html b/rc_autoplc_front/index.html new file mode 100644 index 0000000..9e5fc8f --- /dev/null +++ b/rc_autoplc_front/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/rc_autoplc_front/package-lock.json b/rc_autoplc_front/package-lock.json new file mode 100644 index 0000000..ee5814e --- /dev/null +++ b/rc_autoplc_front/package-lock.json @@ -0,0 +1,3575 @@ +{ + "name": "rc_autoplc_front", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "rc_autoplc_front", + "version": "0.0.0", + "dependencies": { + "axios": "^1.13.2", + "element-plus": "^2.12.0", + "pinia": "^3.0.4", + "pinia-plugin-persistedstate": "^4.7.1", + "vue": "^3.5.25", + "vue-router": "^4.6.3" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.3", + "@types/node": "^24.10.1", + "@vitejs/plugin-vue": "^6.0.2", + "@vue/tsconfig": "^0.8.1", + "npm-run-all2": "^8.0.4", + "typescript": "~5.9.0", + "vite": "^7.2.4", + "vite-plugin-vue-devtools": "^8.0.5", + "vue-tsc": "^3.1.5" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.28.0.tgz", + "integrity": "sha512-zOiZqvANjWDUaUS9xMxbMcK/Zccztbe/6ikvUXaG9nsPH3w6qh5UaPGAnirI/WhIbZ8m3OHU0ReyPrknG+ZKeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-decorators": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.27.1.tgz", + "integrity": "sha512-YMq8Z87Lhl8EGkmb0MwYkt36QnxC+fzCgrl66ereamPlYToRpIk5nUjKUY3QKLWq8mwUB1BgbeXcTJhZOCDg5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.28.5.tgz", + "integrity": "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-create-class-features-plugin": "^7.28.5", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-syntax-typescript": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@element-plus/icons-vue": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz", + "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==", + "license": "MIT", + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, + "node_modules/@popperjs/core": { + "name": "@sxzz/popperjs-es", + "version": "2.11.7", + "resolved": "https://registry.npmjs.org/@sxzz/popperjs-es/-/popperjs-es-2.11.7.tgz", + "integrity": "sha512-Ccy0NlLkzr0Ex2FKvh2X+OyERHXJ88XJ1MXtsI9y9fGexlaXaVTPzBCRBwIxFkORuOb+uBqeu+RqnpgYTEZRUQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.50", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.50.tgz", + "integrity": "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", + "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", + "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", + "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", + "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", + "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", + "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", + "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", + "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", + "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", + "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", + "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", + "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", + "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", + "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", + "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", + "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", + "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", + "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", + "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", + "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", + "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", + "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tsconfig/node24": { + "version": "24.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node24/-/node24-24.0.3.tgz", + "integrity": "sha512-vcERKtKQKHgzt/vfS3Gjasd8SUI2a0WZXpgJURdJsMySpS5+ctgbPfuLj2z/W+w4lAfTWxoN4upKfu2WzIRYnw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-FOvQ0YPD5NOfPgMzJihoT+Za5pdkDJWcbpuj1DjaKZIr/gxodQjY/uWEFlTNqW2ugXHUiL8lRQgw63dzKHZdeQ==", + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "24.10.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.2.tgz", + "integrity": "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.16.tgz", + "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.2.tgz", + "integrity": "sha512-iHmwV3QcVGGvSC1BG5bZ4z6iwa1SOpAPWmnjOErd4Ske+lZua5K9TtAVdx0gMBClJ28DViCbSmZitjWZsWO3LA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "1.0.0-beta.50" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.26.tgz", + "integrity": "sha512-hH0SMitMxnB43OZpyF1IFPS9bgb2I3bpCh76m2WEK7BE0A0EzpYsRp0CCH2xNKshr7kacU5TQBLYn4zj7CG60A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.26" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.26.tgz", + "integrity": "sha512-JJw0Tt/kSFsIRmgTQF4JSt81AUSI1aEye5Zl65EeZ8H35JHnTvFGmpDOBn5iOxd48fyGE+ZvZBp5FcgAy/1Qhw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.26", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.26.tgz", + "integrity": "sha512-N87ecLD48Sp6zV9zID/5yuS1+5foj0DfuYGdQ6KHj/IbKvyKv1zNX6VCmnKYwtmHadEO6mFc2EKISiu3RDPAvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.26", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.25.tgz", + "integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/shared": "3.5.25", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.25.tgz", + "integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.25.tgz", + "integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@vue/compiler-core": "3.5.25", + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.6", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.25.tgz", + "integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/devtools-api": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.9.tgz", + "integrity": "sha512-kIE8wvwlcZ6TJTbNeU2HQNtaxLx3a84aotTITUuL/4bzfPxzajGBOoqjMhwZJ8L9qFYDU/lAYMEEm11dnZOD6g==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^7.7.9" + } + }, + "node_modules/@vue/devtools-core": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.0.5.tgz", + "integrity": "sha512-dpCw8nl0GDBuiL9SaY0mtDxoGIEmU38w+TQiYEPOLhW03VDC0lfNMYXS/qhl4I0YlysGp04NLY4UNn6xgD0VIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.0.5", + "@vue/devtools-shared": "^8.0.5", + "mitt": "^3.0.1", + "nanoid": "^5.1.5", + "pathe": "^2.0.3", + "vite-hot-client": "^2.1.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-kit": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.5.tgz", + "integrity": "sha512-q2VV6x1U3KJMTQPUlRMyWEKVbcHuxhqJdSr6Jtjz5uAThAIrfJ6WVZdGZm5cuO63ZnSUz0RCsVwiUUb0mDV0Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.0.5", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^2.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-core/node_modules/@vue/devtools-shared": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.5.tgz", + "integrity": "sha512-bRLn6/spxpmgLk+iwOrR29KrYnJjG9DGpHGkDFG82UM21ZpJ39ztUT9OXX3g+usW7/b2z+h46I9ZiYyB07XMXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/devtools-core/node_modules/nanoid": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.6.tgz", + "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/@vue/devtools-core/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/devtools-kit": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.9.tgz", + "integrity": "sha512-PyQ6odHSgiDVd4hnTP+aDk2X4gl2HmLDfiyEnn3/oV+ckFDuswRs4IbBT7vacMuGdwY/XemxBoh302ctbsptuA==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.7.9", + "birpc": "^2.3.0", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "7.7.9", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.9.tgz", + "integrity": "sha512-iWAb0v2WYf0QWmxCGy0seZNDPdO3Sp5+u78ORnyeonS6MT4PC7VPrryX2BpMJrwlDeaZ6BD4vP4XKjK0SZqaeA==", + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/@vue/language-core": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.1.8.tgz", + "integrity": "sha512-PfwAW7BLopqaJbneChNL6cUOTL3GL+0l8paYP5shhgY5toBNidWnMXWM+qDwL7MC9+zDtzCF2enT8r6VPu64iw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.26", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.0.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.25.tgz", + "integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.25.tgz", + "integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/shared": "3.5.25" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.25.tgz", + "integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.25", + "@vue/runtime-core": "3.5.25", + "@vue/shared": "3.5.25", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.25.tgz", + "integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "vue": "3.5.25" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz", + "integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.8.1.tgz", + "integrity": "sha512-aK7feIWPXFSUhsCP9PFqPyFOcz4ENkb8hZ2pneL6m2UjCkccvaOhC/5KCKluuBufvp2KzkbdA2W2pk20vLzu3g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": "5.x", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-9.13.0.tgz", + "integrity": "sha512-pujnclbeHWxxPRqXWmdkKV5OX4Wk4YeK7wusHqRwU0Q7EFusHoqNA/aPhB6KCh9hEqJkLAJo7bb0Lh9b+OIVzw==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.16", + "@vueuse/metadata": "9.13.0", + "@vueuse/shared": "9.13.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/core/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/metadata": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-9.13.0.tgz", + "integrity": "sha512-gdU7TKNAUVlXXLbaF+ZCfte8BjRJQWPCa2J55+7/h+yDtzw3vOoGQDRXzI6pyKyo6bXFT5/QoPE4hAknExjRLQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "9.13.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-9.13.0.tgz", + "integrity": "sha512-UrnhU+Cnufu4S6JLCPZnkWh0WwZGUp72ktOF2DFptMlOs3TOdVv8xJN53zhHGARmVOsz5KqOls09+J1NR6sBKw==", + "license": "MIT", + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/alien-signals": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.1.1.tgz", + "integrity": "sha512-ogkIWbVrLwKtHY6oOAXaYkAxP+cTH7V5FZ5+Tm4NZFd8VDZ6uNMDrfzqctTZ42eTMCSR3ne3otpcxmqSnFfPYA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz", + "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.5.tgz", + "integrity": "sha512-D5vIoztZOq1XM54LUdttJVc96ggEsIfju2JBvht06pSzpckp3C7HReun67Bghzrtdsq9XdMGbSSB3v3GhMNmAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-4.0.5.tgz", + "integrity": "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA==", + "license": "MIT", + "dependencies": { + "is-what": "^5.2.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/dayjs": { + "version": "1.11.19", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz", + "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/default-browser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, + "node_modules/element-plus": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/element-plus/-/element-plus-2.12.0.tgz", + "integrity": "sha512-M9YLSn2np9OnqrSKWsiXvGe3qnF8pd94+TScsHj1aTMCD+nSEvucXermf807qNt6hOP040le0e5Aft7E9ZfHmA==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.1", + "@element-plus/icons-vue": "^2.3.2", + "@floating-ui/dom": "^1.0.1", + "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.7", + "@types/lodash": "^4.17.20", + "@types/lodash-es": "^4.17.12", + "@vueuse/core": "^9.1.0", + "async-validator": "^4.2.5", + "dayjs": "^1.11.19", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "lodash-unified": "^1.0.3", + "memoize-one": "^6.0.0", + "normalize-wheel-es": "^1.2.0" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-what": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-5.5.0.tgz", + "integrity": "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isexe": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-4.0.0.tgz", + "integrity": "sha512-lR4MXjGNgkJc7tkQ97kb2nuEMnNCyU//XYVH0MKTGcXEiSudQ5MKGKen3C5QubYy0vmq+JGitUg92uuywGEwIA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT", + "peer": true + }, + "node_modules/lodash-unified": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/lodash-unified/-/lodash-unified-1.0.3.tgz", + "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==", + "license": "MIT", + "peerDependencies": { + "@types/lodash-es": "*", + "lodash": "*", + "lodash-es": "*" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz", + "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==", + "license": "MIT" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-wheel-es": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz", + "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==", + "license": "BSD-3-Clause" + }, + "node_modules/npm-normalize-package-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-4.0.0.tgz", + "integrity": "sha512-TZKxPvItzai9kN9H/TkmCtx/ZN/hvr3vUycjlfmH0ootY9yFBzNOpiXAdIn1Iteqsvk4lQn6B5PTrt+n6h8k/w==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/npm-run-all2": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-8.0.4.tgz", + "integrity": "sha512-wdbB5My48XKp2ZfJUlhnLVihzeuA1hgBnqB2J9ahV77wLS+/YAJAlN8I+X3DIFIPZ3m5L7nplmlbhNiFDmXRDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "picomatch": "^4.0.2", + "pidtree": "^0.6.0", + "read-package-json-fast": "^4.0.0", + "shell-quote": "^1.7.3", + "which": "^5.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^20.5.0 || >=22.0.0", + "npm": ">= 10" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/open": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz", + "integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "wsl-utils": "^0.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pinia": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-3.0.4.tgz", + "integrity": "sha512-l7pqLUFTI/+ESXn6k3nu30ZIzW5E2WZF/LaHJEpoq6ElcLD+wduZoB2kBN19du6K/4FDpPMazY2wJr+IndBtQw==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/devtools-api": "^7.7.7" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "typescript": ">=4.5.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia-plugin-persistedstate": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/pinia-plugin-persistedstate/-/pinia-plugin-persistedstate-4.7.1.tgz", + "integrity": "sha512-WHOqh2esDlR3eAaknPbqXrkkj0D24h8shrDPqysgCFR6ghqP/fpFfJmMPJp0gETHsvrh9YNNg6dQfo2OEtDnIQ==", + "license": "MIT", + "dependencies": { + "defu": "^6.1.4" + }, + "peerDependencies": { + "@nuxt/kit": ">=3.0.0", + "@pinia/nuxt": ">=0.10.0", + "pinia": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + }, + "@pinia/nuxt": { + "optional": true + }, + "pinia": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/read-package-json-fast": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-4.0.0.tgz", + "integrity": "sha512-qpt8EwugBWDw2cgE2W+/3oxC+KTez2uSVR8JU9Q36TXPAGCaozfQUs59v4j4GFpWTaw0i6hAZSvOmu1J0uOEUg==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^4.0.0", + "npm-normalize-package-bin": "^4.0.0" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "license": "MIT" + }, + "node_modules/rollup": { + "version": "4.53.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", + "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.53.3", + "@rollup/rollup-android-arm64": "4.53.3", + "@rollup/rollup-darwin-arm64": "4.53.3", + "@rollup/rollup-darwin-x64": "4.53.3", + "@rollup/rollup-freebsd-arm64": "4.53.3", + "@rollup/rollup-freebsd-x64": "4.53.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", + "@rollup/rollup-linux-arm-musleabihf": "4.53.3", + "@rollup/rollup-linux-arm64-gnu": "4.53.3", + "@rollup/rollup-linux-arm64-musl": "4.53.3", + "@rollup/rollup-linux-loong64-gnu": "4.53.3", + "@rollup/rollup-linux-ppc64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-gnu": "4.53.3", + "@rollup/rollup-linux-riscv64-musl": "4.53.3", + "@rollup/rollup-linux-s390x-gnu": "4.53.3", + "@rollup/rollup-linux-x64-gnu": "4.53.3", + "@rollup/rollup-linux-x64-musl": "4.53.3", + "@rollup/rollup-openharmony-arm64": "4.53.3", + "@rollup/rollup-win32-arm64-msvc": "4.53.3", + "@rollup/rollup-win32-ia32-msvc": "4.53.3", + "@rollup/rollup-win32-x64-gnu": "4.53.3", + "@rollup/rollup-win32-x64-msvc": "4.53.3", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz", + "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superjson": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.6.tgz", + "integrity": "sha512-H+ue8Zo4vJmV2nRjpx86P35lzwDT3nItnIsocgumgr0hHMQ+ZGq5vrERg9kJBo5AWGmxZDhzDo+WVIJqkB0cGA==", + "license": "MIT", + "dependencies": { + "copy-anything": "^4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unplugin-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.1.tgz", + "integrity": "sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==", + "dev": true, + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/vite": { + "version": "7.2.7", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz", + "integrity": "sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-dev-rpc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz", + "integrity": "sha512-pKXZlgoXGoE8sEKiKJSng4hI1sQ4wi5YT24FCrwrLt6opmkjlqPPVmiPWWJn8M8byMxRGzp1CrFuqQs4M/Z39A==", + "dev": true, + "license": "MIT", + "dependencies": { + "birpc": "^2.4.0", + "vite-hot-client": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0" + } + }, + "node_modules/vite-hot-client": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.1.0.tgz", + "integrity": "sha512-7SpgZmU7R+dDnSmvXE1mfDtnHLHQSisdySVR7lO8ceAXvM0otZeuQQ6C8LrS5d/aYyP/QZ0hI0L+dIPrm4YlFQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-inspect": { + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.3.3.tgz", + "integrity": "sha512-u2eV5La99oHoYPHE6UvbwgEqKKOQGz86wMg40CCosP6q8BkB6e5xPneZfYagK4ojPJSj5anHCrnvC20DpwVdRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.1.0", + "debug": "^4.4.1", + "error-stack-parser-es": "^1.0.5", + "ohash": "^2.0.11", + "open": "^10.2.0", + "perfect-debounce": "^2.0.0", + "sirv": "^3.0.1", + "unplugin-utils": "^0.3.0", + "vite-dev-rpc": "^1.1.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-inspect/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.0.5.tgz", + "integrity": "sha512-p619BlKFOqQXJ6uDWS1vUPQzuJOD6xJTfftj57JXBGoBD/yeQCowR7pnWcr/FEX4/HVkFbreI6w2uuGBmQOh6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^8.0.5", + "@vue/devtools-kit": "^8.0.5", + "@vue/devtools-shared": "^8.0.5", + "sirv": "^3.0.2", + "vite-plugin-inspect": "^11.3.3", + "vite-plugin-vue-inspector": "^5.3.2" + }, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-kit": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.0.5.tgz", + "integrity": "sha512-q2VV6x1U3KJMTQPUlRMyWEKVbcHuxhqJdSr6Jtjz5uAThAIrfJ6WVZdGZm5cuO63ZnSUz0RCsVwiUUb0mDV0Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.0.5", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^2.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.2" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/@vue/devtools-shared": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.0.5.tgz", + "integrity": "sha512-bRLn6/spxpmgLk+iwOrR29KrYnJjG9DGpHGkDFG82UM21ZpJ39ztUT9OXX3g+usW7/b2z+h46I9ZiYyB07XMXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "rfdc": "^1.4.1" + } + }, + "node_modules/vite-plugin-vue-devtools/node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.3.2.tgz", + "integrity": "sha512-YvEKooQcSiBTAs0DoYLfefNja9bLgkFM7NI2b07bE2SruuvX0MEa9cMaxjKVMkeCp5Nz9FRIdcN1rOdFVBeL6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0" + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.25", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.25.tgz", + "integrity": "sha512-YLVdgv2K13WJ6n+kD5owehKtEXwdwXuj2TTyJMsO7pSeKw2bfRNZGjhB7YzrpbMYj5b5QsUebHpOqR3R3ziy/g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@vue/compiler-dom": "3.5.25", + "@vue/compiler-sfc": "3.5.25", + "@vue/runtime-dom": "3.5.25", + "@vue/server-renderer": "3.5.25", + "@vue/shared": "3.5.25" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-router": { + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.3.tgz", + "integrity": "sha512-ARBedLm9YlbvQomnmq91Os7ck6efydTSpRP3nuOKCvgJOHNrhRoJDSKtee8kcL1Vf7nz6U+PMBL+hTvR3bTVQg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-router/node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/vue-tsc": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.1.8.tgz", + "integrity": "sha512-deKgwx6exIHeZwF601P1ktZKNF0bepaSN4jBU3AsbldPx9gylUc1JDxYppl82yxgkAgaz0Y0LCLOi+cXe9HMYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.26", + "@vue/language-core": "3.1.8" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/which": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-5.0.0.tgz", + "integrity": "sha512-JEdGzHwwkrbWoGOlIHqQ5gtprKGOenpDHpxE9zVR1bWbOtYRyPPHMe9FaP6x61CmNaTThSkb0DAJte5jD+DmzQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^3.1.1" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^18.17.0 || >=20.5.0" + } + }, + "node_modules/wsl-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz", + "integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + } + } +} diff --git a/rc_autoplc_front/package.json b/rc_autoplc_front/package.json new file mode 100644 index 0000000..843cb50 --- /dev/null +++ b/rc_autoplc_front/package.json @@ -0,0 +1,35 @@ +{ + "name": "rc_autoplc_front", + "version": "0.0.0", + "private": true, + "type": "module", + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build" + }, + "dependencies": { + "axios": "^1.13.2", + "element-plus": "^2.12.0", + "pinia": "^3.0.4", + "pinia-plugin-persistedstate": "^4.7.1", + "vue": "^3.5.25", + "vue-router": "^4.6.3" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.3", + "@types/node": "^24.10.1", + "@vitejs/plugin-vue": "^6.0.2", + "@vue/tsconfig": "^0.8.1", + "npm-run-all2": "^8.0.4", + "typescript": "~5.9.0", + "vite": "^7.2.4", + "vite-plugin-vue-devtools": "^8.0.5", + "vue-tsc": "^3.1.5" + } +} diff --git a/rc_autoplc_front/public/favicon.ico b/rc_autoplc_front/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/rc_autoplc_front/public/favicon.ico differ diff --git a/rc_autoplc_front/src/App.vue b/rc_autoplc_front/src/App.vue new file mode 100644 index 0000000..b7a6acd --- /dev/null +++ b/rc_autoplc_front/src/App.vue @@ -0,0 +1,71 @@ + + + + + diff --git a/rc_autoplc_front/src/api/system/department.ts b/rc_autoplc_front/src/api/system/department.ts new file mode 100644 index 0000000..529de58 --- /dev/null +++ b/rc_autoplc_front/src/api/system/department.ts @@ -0,0 +1,46 @@ +import request from '@/utils/request' + +export function departmentadd(data: any) { + return request({ + url: '/depart/add', + method: 'post', + data, + }) +} + +export function departmentdel(id: string | number) { + return request({ + url: `/depart/del/${id}`, + method: 'delete', + }) +} + +export function departupd(data: any) { + return request({ + url: '/depart/update', + method: 'put', + data, + }) +} + +export function departlist(data: any) { + return request({ + url: '/depart/listPage', + method: 'get', + params: data, + }) +} + +export function departbyid(id: string | number) { + return request({ + url: `/depart/getById/${id}`, + method: 'get', + }) +} + +export function departtree() { + return request({ + url: `/depart/tree`, + method: 'get', + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/system/manage-log.ts b/rc_autoplc_front/src/api/system/manage-log.ts new file mode 100644 index 0000000..83611b4 --- /dev/null +++ b/rc_autoplc_front/src/api/system/manage-log.ts @@ -0,0 +1,39 @@ +import request from '@/utils/request' + +export function managelogadd(data: any) { + return request({ + url: '/manage-log/add', + method: 'post', + data, + }) +} + +export function managelogdel(id: string | number) { + return request({ + url: `/manage-log/del/${id}`, + method: 'delete', + }) +} + +export function managelogupd(data: any) { + return request({ + url: '/manage-log/update', + method: 'put', + data, + }) +} + +export function manageloglist(data: any) { + return request({ + url: '/manage-log/listPage', + method: 'get', + params: data, + }) +} + +export function managelogbyid(id: string | number) { + return request({ + url: `/manage-log/getById/${id}`, + method: 'get', + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/system/position.ts b/rc_autoplc_front/src/api/system/position.ts new file mode 100644 index 0000000..c131d2a --- /dev/null +++ b/rc_autoplc_front/src/api/system/position.ts @@ -0,0 +1,46 @@ +import request from '@/utils/request' + +export function positionadd(data: any) { + return request({ + url: '/position/add', + method: 'post', + data, + }) +} + +export function positiondel(id: string | number) { + return request({ + url: `/position/del/${id}`, + method: 'delete', + }) +} + +export function positionupd(data: any) { + return request({ + url: '/position/update', + method: 'put', + data, + }) +} + +export function positionlist(data: any) { + return request({ + url: '/position/listPage', + method: 'get', + params: data, + }) +} + +export function positionbyid(id: string | number) { + return request({ + url: `/position/getById/${id}`, + method: 'get', + }) +} + +export function positionselect() { + return request({ + url: `/position/list`, + method: 'get', + }) +} diff --git a/rc_autoplc_front/src/api/system/role.ts b/rc_autoplc_front/src/api/system/role.ts new file mode 100644 index 0000000..5bbf493 --- /dev/null +++ b/rc_autoplc_front/src/api/system/role.ts @@ -0,0 +1,47 @@ +import request from '@/utils/request' + +export function roleadd(data: any) { + return request({ + url: '/role/add', + method: 'post', + data, + }) +} + +export function roledel(id: string | number) { + return request({ + url: `/role/del/${id}`, + method: 'delete', + }) +} + +export function roleupd(data: any) { + return request({ + url: '/role/update', + method: 'put', + data, + }) +} + +export function rolelist(data: any) { + return request({ + url: '/role/listPage', + method: 'get', + params: data, + }) +} + +export function rolebyid(id: string | number) { + return request({ + url: `/role/getById/${id}`, + method: 'get', + }) +} + +export function rleselect(data: any) { + return request({ + url: '/role/list', + method: 'get', + params: data, + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/system/user-role.ts b/rc_autoplc_front/src/api/system/user-role.ts new file mode 100644 index 0000000..f202c31 --- /dev/null +++ b/rc_autoplc_front/src/api/system/user-role.ts @@ -0,0 +1,67 @@ +import request from '@/utils/request' + +// 新增用户角色关联 +export function userRoleAdd(data: any) { + return request({ + url: '/user-role/add', + method: 'post', + data, + }) +} + +// 根据ID删除用户角色关联 +export function userRoleDel(id: string | number) { + return request({ + url: `/user-role/del/${id}`, + method: 'delete', + }) +} + +// 分页查询用户角色关联列表 +export function userRoleList(data: any) { + return request({ + url: '/user-role/listPage', + method: 'get', + params: data, + }) +} + +// 根据ID查询用户角色关联 +export function userRoleById(id: string | number) { + return request({ + url: `/user-role/getById/${id}`, + method: 'get', + }) +} + +// 根据角色ID查询关联用户(先封装不调用) +export function userRoleByRoleId(roleId: string | number) { + return request({ + url: `/user-role/role/${roleId}`, + method: 'get', + }) +} + +// 根据角色ID删除所有关联(先封装不调用) +export function userRoleDelByRoleId(roleId: string | number) { + return request({ + url: `/user-role/role/${roleId}`, + method: 'delete', + }) +} + +// 根据用户ID查询关联角色(先封装不调用) +export function userRoleByUserId(userId: string | number) { + return request({ + url: `/user-role/user/${userId}`, + method: 'get', + }) +} + +// 根据用户ID删除所有关联(先封装不调用) +export function userRoleDelByUserId(userId: string | number) { + return request({ + url: `/user-role/user/${userId}`, + method: 'delete', + }) +} diff --git a/rc_autoplc_front/src/api/system/user.ts b/rc_autoplc_front/src/api/system/user.ts new file mode 100644 index 0000000..9c032ef --- /dev/null +++ b/rc_autoplc_front/src/api/system/user.ts @@ -0,0 +1,47 @@ +import request from '@/utils/request' + +export function useradd(data: any) { + return request({ + url: '/user/add', + method: 'post', + data, + }) +} + +export function userdel(id: string | number) { + return request({ + url: `/user/del/${id}`, + method: 'delete', + }) +} + +export function userupd(data: any) { + return request({ + url: '/user/update', + method: 'put', + data, + }) +} + +export function userlist(data: any) { + return request({ + url: '/user/listPage', + method: 'get', + params: data, + }) +} + +export function userselect(data: any) { + return request({ + url: '/user/list', + method: 'get', + params: data, + }) +} + +export function userbyid(id: string | number) { + return request({ + url: `/user/getById/${id}`, + method: 'get', + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/tb/devinfo.ts b/rc_autoplc_front/src/api/tb/devinfo.ts new file mode 100644 index 0000000..dd56c4b --- /dev/null +++ b/rc_autoplc_front/src/api/tb/devinfo.ts @@ -0,0 +1,47 @@ +import request from '@/utils/request' + +export function devInfoadd(data: any) { + return request({ + url: '/devInfo/add', + method: 'post', + data, + }) +} + +export function devInfodel(id: string | number) { + return request({ + url: `/devInfo/del/${id}`, + method: 'delete', + }) +} + +export function devInfoupd(data: any) { + return request({ + url: '/devInfo/update', + method: 'put', + data, + }) +} + +export function devInfolist(data: any) { + return request({ + url: '/devInfo/listPage', + method: 'get', + params: data, + }) +} + +export function devInfobyid(id: string | number) { + return request({ + url: `/devInfo/getById/${id}`, + method: 'get', + }) +} + +export function devselect(data: any) { + return request({ + url: '/devInfo/all', + method: 'get', + params: data, + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/tb/devparam.ts b/rc_autoplc_front/src/api/tb/devparam.ts new file mode 100644 index 0000000..75d0e18 --- /dev/null +++ b/rc_autoplc_front/src/api/tb/devparam.ts @@ -0,0 +1,47 @@ +import request from '@/utils/request' + +export function devparamadd(data: any) { + return request({ + url: '/devParam/add', + method: 'post', + data, + }) +} + +export function devparamdel(id: string | number) { + return request({ + url: `/devParam/del/${id}`, + method: 'delete', + }) +} + +export function devparamupd(data: any) { + return request({ + url: '/devParam/update', + method: 'put', + data, + }) +} + +export function devparamlist(data: any) { + return request({ + url: '/devParam/listPage', + method: 'get', + params: data, + }) +} + +export function devparambyid(id: string | number) { + return request({ + url: `/devParam/getById/${id}`, + method: 'get', + }) +} + +export function devparamselect(data: any) { + return request({ + url: '/devParam/list', + method: 'get', + params: data, + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/api/tb/islandinfo.ts b/rc_autoplc_front/src/api/tb/islandinfo.ts new file mode 100644 index 0000000..fbd1bae --- /dev/null +++ b/rc_autoplc_front/src/api/tb/islandinfo.ts @@ -0,0 +1,39 @@ +import request from '@/utils/request' + +export function islandInfoadd(data: any) { + return request({ + url: '/islandInfo/add', + method: 'post', + data, + }) +} + +export function islandInfodel(id: string | number) { + return request({ + url: `/islandInfo/del/${id}`, + method: 'delete', + }) +} + +export function islandInfoupd(data: any) { + return request({ + url: '/islandInfo/update', + method: 'put', + data, + }) +} + +export function islandInfolist(data: any) { + return request({ + url: '/islandInfo/listPage', + method: 'get', + params: data, + }) +} + +export function islandInfobyid(id: string | number) { + return request({ + url: `/islandInfo/getById/${id}`, + method: 'get', + }) +} \ No newline at end of file diff --git a/rc_autoplc_front/src/assets/base.css b/rc_autoplc_front/src/assets/base.css new file mode 100644 index 0000000..8816868 --- /dev/null +++ b/rc_autoplc_front/src/assets/base.css @@ -0,0 +1,86 @@ +/* color palette from */ +:root { + --vt-c-white: #ffffff; + --vt-c-white-soft: #f8f8f8; + --vt-c-white-mute: #f2f2f2; + + --vt-c-black: #181818; + --vt-c-black-soft: #222222; + --vt-c-black-mute: #282828; + + --vt-c-indigo: #2c3e50; + + --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); + --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); + --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); + --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); + + --vt-c-text-light-1: var(--vt-c-indigo); + --vt-c-text-light-2: rgba(60, 60, 60, 0.66); + --vt-c-text-dark-1: var(--vt-c-white); + --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); +} + +/* semantic color variables for this project */ +:root { + --color-background: var(--vt-c-white); + --color-background-soft: var(--vt-c-white-soft); + --color-background-mute: var(--vt-c-white-mute); + + --color-border: var(--vt-c-divider-light-2); + --color-border-hover: var(--vt-c-divider-light-1); + + --color-heading: var(--vt-c-text-light-1); + --color-text: var(--vt-c-text-light-1); + + --section-gap: 160px; +} + +@media (prefers-color-scheme: dark) { + :root { + --color-background: var(--vt-c-black); + --color-background-soft: var(--vt-c-black-soft); + --color-background-mute: var(--vt-c-black-mute); + + --color-border: var(--vt-c-divider-dark-2); + --color-border-hover: var(--vt-c-divider-dark-1); + + --color-heading: var(--vt-c-text-dark-1); + --color-text: var(--vt-c-text-dark-2); + } +} + +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + font-weight: normal; +} + +body { + min-height: 100vh; + color: var(--color-text); + background: var(--color-background); + transition: + color 0.5s, + background-color 0.5s; + line-height: 1.6; + font-family: + Inter, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + sans-serif; + font-size: 15px; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} diff --git a/rc_autoplc_front/src/assets/image/right.png b/rc_autoplc_front/src/assets/image/right.png new file mode 100644 index 0000000..0237eb9 Binary files /dev/null and b/rc_autoplc_front/src/assets/image/right.png differ diff --git a/rc_autoplc_front/src/assets/logo.svg b/rc_autoplc_front/src/assets/logo.svg new file mode 100644 index 0000000..7565660 --- /dev/null +++ b/rc_autoplc_front/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/rc_autoplc_front/src/assets/main.css b/rc_autoplc_front/src/assets/main.css new file mode 100644 index 0000000..36fb845 --- /dev/null +++ b/rc_autoplc_front/src/assets/main.css @@ -0,0 +1,35 @@ +@import './base.css'; + +#app { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + font-weight: normal; +} + +a, +.green { + text-decoration: none; + color: hsla(160, 100%, 37%, 1); + transition: 0.4s; + padding: 3px; +} + +@media (hover: hover) { + a:hover { + background-color: hsla(160, 100%, 37%, 0.2); + } +} + +@media (min-width: 1024px) { + body { + display: flex; + place-items: center; + } + + #app { + display: grid; + grid-template-columns: 1fr 1fr; + padding: 0 2rem; + } +} diff --git a/rc_autoplc_front/src/components/HelloWorld.vue b/rc_autoplc_front/src/components/HelloWorld.vue new file mode 100644 index 0000000..d174cf8 --- /dev/null +++ b/rc_autoplc_front/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/rc_autoplc_front/src/components/TheWelcome.vue b/rc_autoplc_front/src/components/TheWelcome.vue new file mode 100644 index 0000000..8b731d9 --- /dev/null +++ b/rc_autoplc_front/src/components/TheWelcome.vue @@ -0,0 +1,95 @@ + + + diff --git a/rc_autoplc_front/src/components/WelcomeItem.vue b/rc_autoplc_front/src/components/WelcomeItem.vue new file mode 100644 index 0000000..6d7086a --- /dev/null +++ b/rc_autoplc_front/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/rc_autoplc_front/src/components/icons/IconCommunity.vue b/rc_autoplc_front/src/components/icons/IconCommunity.vue new file mode 100644 index 0000000..2dc8b05 --- /dev/null +++ b/rc_autoplc_front/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/rc_autoplc_front/src/components/icons/IconDocumentation.vue b/rc_autoplc_front/src/components/icons/IconDocumentation.vue new file mode 100644 index 0000000..6d4791c --- /dev/null +++ b/rc_autoplc_front/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/rc_autoplc_front/src/components/icons/IconEcosystem.vue b/rc_autoplc_front/src/components/icons/IconEcosystem.vue new file mode 100644 index 0000000..c3a4f07 --- /dev/null +++ b/rc_autoplc_front/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/rc_autoplc_front/src/components/icons/IconSupport.vue b/rc_autoplc_front/src/components/icons/IconSupport.vue new file mode 100644 index 0000000..7452834 --- /dev/null +++ b/rc_autoplc_front/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/rc_autoplc_front/src/components/icons/IconTooling.vue b/rc_autoplc_front/src/components/icons/IconTooling.vue new file mode 100644 index 0000000..660598d --- /dev/null +++ b/rc_autoplc_front/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/rc_autoplc_front/src/main.ts b/rc_autoplc_front/src/main.ts new file mode 100644 index 0000000..ce0adbf --- /dev/null +++ b/rc_autoplc_front/src/main.ts @@ -0,0 +1,23 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' + +import App from './App.vue' +import router from './router' +import ElementPlus from 'element-plus' +import 'element-plus/dist/index.css' +import zhCn from 'element-plus/es/locale/lang/zh-cn' + +const app = createApp(App) + +// 创建 Pinia 实例并配置持久化插件 +const pinia = createPinia() +pinia.use(piniaPluginPersistedstate) + +app.use(ElementPlus, { + locale: zhCn, +}) +app.use(pinia) +app.use(router) + +app.mount('#app') diff --git a/rc_autoplc_front/src/router/index.ts b/rc_autoplc_front/src/router/index.ts new file mode 100644 index 0000000..3604ca3 --- /dev/null +++ b/rc_autoplc_front/src/router/index.ts @@ -0,0 +1,71 @@ +import { createRouter, createWebHistory } from 'vue-router' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + component: () => import('../views/Layout.vue'), + children: [ + { + path: '/user', + name: 'user', + component: () => import('../views/user/index.vue'), + }, + { + path: '/role', + name: 'role', + component: () => import('../views/role/index.vue'), + }, + { + path: '/department', + name: 'department', + component: () => import('../views/department/index.vue'), + }, + { + path: '/position', + name: 'position', + component: () => import('../views/position/index.vue'), + }, + { + path: '/manage-log', + name: 'manage-log', + component: () => import('../views/manage-log/index.vue'), + }, + { + path: '/user-role', + name: 'user-role', + component: () => import('../views/user-role/index.vue'), + }, + { + path: '/island-info', + name: 'island-info', + component: () => import('../views/islandInfo/index.vue'), + }, + { + path: '/devinfo', + name: 'devinfo', + component: () => import('../views/devinfo/index.vue'), + }, + { + path: '/plc-devinfo', + name: 'plc-devinfo', + component: () => import('../views/devinfo/plc.vue'), + }, + ], + }, + ], +}) + +// 添加全局路由守卫 +// router.beforeEach((to, from, next) => { +// const token = localStorage.getItem('token') + +// if (to.path !== '/login' && !token) { +// next('/login') +// } else { +// next() +// } +// }) + +export default router diff --git a/rc_autoplc_front/src/router/permission.ts b/rc_autoplc_front/src/router/permission.ts new file mode 100644 index 0000000..0968c2e --- /dev/null +++ b/rc_autoplc_front/src/router/permission.ts @@ -0,0 +1,38 @@ +// import router from './index' // 导入你的路由实例(与index.ts对应) +// import { ElMessage } from 'element-plus' +// import { useAuthStore } from '@/stores/auth' // 你的Pinia auth store路径 + +// // 路由前置守卫:每次路由跳转前执行 +// router.beforeEach((to, from, next) => { +// const authStore = useAuthStore() // 获取auth store实例 +// const token = authStore.getToken() // 调用你的getToken()方法获取token + +// // 1. 如果访问登录页 +// if (to.path === '/login') { +// // 已登录状态下访问登录页,自动跳转到首页/dashboard +// if (token) { +// next('/dashboard') +// ElMessage.success('已登录,自动跳转') +// } else { +// // 未登录,正常进入登录页 +// next() +// } +// return +// } + +// // 2. 访问非登录页,但未登录(无token) +// if (!token) { +// ElMessage.warning('请先登录') +// next('/login') // 强制跳转到登录页 +// return +// } + +// // 3. 访问根路径,自动跳转到dashboard +// if (to.path === '/') { +// next('/dashboard') +// return +// } + +// // 4. 已登录且访问合法页面,正常放行 +// next() +// }) \ No newline at end of file diff --git a/rc_autoplc_front/src/stores/auth.ts b/rc_autoplc_front/src/stores/auth.ts new file mode 100644 index 0000000..c2d911f --- /dev/null +++ b/rc_autoplc_front/src/stores/auth.ts @@ -0,0 +1,27 @@ +import { ref } from 'vue' +import { defineStore } from 'pinia' + +export const useAuthStore = defineStore('auth', () => { + const token = ref('') + + function setToken(newToken: string) { + token.value = newToken + } + + function getToken(): string { + return token.value + } + + function removeToken() { + token.value = '' + } + + return { + token, + setToken, + getToken, + removeToken, + } +}, { + persist: true, +}) diff --git a/rc_autoplc_front/src/utils/request.ts b/rc_autoplc_front/src/utils/request.ts new file mode 100644 index 0000000..8dcb4f3 --- /dev/null +++ b/rc_autoplc_front/src/utils/request.ts @@ -0,0 +1,91 @@ +import axios from 'axios' +import type { AxiosInstance, InternalAxiosRequestConfig, AxiosResponse } from 'axios' +import { ElMessage } from 'element-plus' +import router from '@/router' +import { useAuthStore } from '@/stores/auth' + +// 创建 axios 实例 +const request: AxiosInstance = axios.create({ + baseURL: import.meta.env.VITE_API_URL, // 从环境变量读取 + timeout: 10000, // 10秒超时 +}) + +// Token 管理器(使用 Pinia) +const TokenManager = { + setToken(token: string) { + const authStore = useAuthStore() + authStore.setToken(token) + // 同时设置默认请求头 + request.defaults.headers.common['Authorization'] = `Bearer ${token}` + }, + + getToken(): string { + const authStore = useAuthStore() + return authStore.getToken() + }, + + removeToken() { + const authStore = useAuthStore() + authStore.removeToken() + // 删除默认请求头 + delete request.defaults.headers.common['Authorization'] + }, +} + +// 请求拦截器 +request.interceptors.request.use( + (config: InternalAxiosRequestConfig) => { + const token = TokenManager.getToken() + if (token) { + // .NET Core API使用标准的Bearer认证 + config.headers['Authorization'] = `Bearer ${token}` + } + return config + }, + (error) => { + return Promise.reject(error) + } +) + +// 响应拦截器 +request.interceptors.response.use( + (response: AxiosResponse) => { + const { data } = response + + // 如果返回 code 为 0 且有新 token,更新 token + if (data.code === 0 && data.token) { + TokenManager.setToken(data.token) + } + + console.log('data*--', data) + + // 处理业务错误码 + if (data.code === 302) { + // 清除token + TokenManager.removeToken() + // 跳转到登录页 + router.replace('/login') + return Promise.reject(data) + } + + // 其他错误码 + if (data.code !== 0 && data.code !== undefined) { + ElMessage.error(data.message || data.msg || '请求失败') + return Promise.reject(data) + } + + return data + }, + (error) => { + // 网络错误或其他错误 + ElMessage.error( + error.response?.data?.message || + error.response?.data?.msg || + '请求失败' + ) + return Promise.reject(error) + } +) + +export default request + diff --git a/rc_autoplc_front/src/views/Layout.vue b/rc_autoplc_front/src/views/Layout.vue new file mode 100644 index 0000000..44daf7b --- /dev/null +++ b/rc_autoplc_front/src/views/Layout.vue @@ -0,0 +1,213 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/department/index.vue b/rc_autoplc_front/src/views/department/index.vue new file mode 100644 index 0000000..25c0e66 --- /dev/null +++ b/rc_autoplc_front/src/views/department/index.vue @@ -0,0 +1,673 @@ + + + + + + + diff --git a/rc_autoplc_front/src/views/devinfo/index.vue b/rc_autoplc_front/src/views/devinfo/index.vue new file mode 100644 index 0000000..d68f9d6 --- /dev/null +++ b/rc_autoplc_front/src/views/devinfo/index.vue @@ -0,0 +1,1061 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/devinfo/plc.vue b/rc_autoplc_front/src/views/devinfo/plc.vue new file mode 100644 index 0000000..e954c0d --- /dev/null +++ b/rc_autoplc_front/src/views/devinfo/plc.vue @@ -0,0 +1,583 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/islandInfo/index.vue b/rc_autoplc_front/src/views/islandInfo/index.vue new file mode 100644 index 0000000..3d55250 --- /dev/null +++ b/rc_autoplc_front/src/views/islandInfo/index.vue @@ -0,0 +1,1091 @@ + + + + + + + diff --git a/rc_autoplc_front/src/views/manage-log/index.vue b/rc_autoplc_front/src/views/manage-log/index.vue new file mode 100644 index 0000000..d0969b4 --- /dev/null +++ b/rc_autoplc_front/src/views/manage-log/index.vue @@ -0,0 +1,461 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/position/index.vue b/rc_autoplc_front/src/views/position/index.vue new file mode 100644 index 0000000..ab692ac --- /dev/null +++ b/rc_autoplc_front/src/views/position/index.vue @@ -0,0 +1,407 @@ + + + + + + + + + + + + + diff --git a/rc_autoplc_front/src/views/role/index.vue b/rc_autoplc_front/src/views/role/index.vue new file mode 100644 index 0000000..5de6a59 --- /dev/null +++ b/rc_autoplc_front/src/views/role/index.vue @@ -0,0 +1,334 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/user-role/index.vue b/rc_autoplc_front/src/views/user-role/index.vue new file mode 100644 index 0000000..2e939c9 --- /dev/null +++ b/rc_autoplc_front/src/views/user-role/index.vue @@ -0,0 +1,527 @@ + + + + + + diff --git a/rc_autoplc_front/src/views/user/index.vue b/rc_autoplc_front/src/views/user/index.vue new file mode 100644 index 0000000..300e624 --- /dev/null +++ b/rc_autoplc_front/src/views/user/index.vue @@ -0,0 +1,844 @@ + + + + + + diff --git a/rc_autoplc_front/tsconfig.app.json b/rc_autoplc_front/tsconfig.app.json new file mode 100644 index 0000000..ba6658c --- /dev/null +++ b/rc_autoplc_front/tsconfig.app.json @@ -0,0 +1,13 @@ +{ + + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/rc_autoplc_front/tsconfig.json b/rc_autoplc_front/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/rc_autoplc_front/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/rc_autoplc_front/tsconfig.node.json b/rc_autoplc_front/tsconfig.node.json new file mode 100644 index 0000000..822562d --- /dev/null +++ b/rc_autoplc_front/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node24/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/rc_autoplc_front/vite.config.ts b/rc_autoplc_front/vite.config.ts new file mode 100644 index 0000000..4217010 --- /dev/null +++ b/rc_autoplc_front/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueDevTools from 'vite-plugin-vue-devtools' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + }, + }, +})