소스 검색

玛尔挡水温监测平台

lamphua 2 주 전
커밋
d40c74bcb7
100개의 변경된 파일22000개의 추가작업 그리고 0개의 파일을 삭제
  1. 25
    0
      cmc-temperature-back/.gitignore
  2. 201
    0
      cmc-temperature-back/LICENSE
  3. 95
    0
      cmc-temperature-back/README.md
  4. 22
    0
      cmc-temperature-back/docs/ruoyi-docs/.editorconfig
  5. 14
    0
      cmc-temperature-back/docs/ruoyi-docs/.gitignore
  6. 43
    0
      cmc-temperature-back/docs/ruoyi-docs/README.md
  7. 42
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/config.js
  8. 9
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/enhanceApp.js
  9. 32
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/nav.js
  10. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/boot/gradle_settings.png
  11. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/boot/mysql.png
  12. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/cloud.png
  13. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/common.png
  14. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/mysql.png
  15. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/nacos1.png
  16. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/nacos2.png
  17. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/nacos3.png
  18. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/namespace.png
  19. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/coding.gif
  20. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/favicon.ico
  21. BIN
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/logo.png
  22. 9
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/sidebar.js
  23. 16
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/README.md
  24. 49
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/adumbrate/README.md
  25. 14
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/adumbrate.md
  26. 279
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/backend.md
  27. 127
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/before.md
  28. 8
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/front.md
  29. 252
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/ops.md
  30. 160
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/adumbrate.md
  31. 574
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/backend.md
  32. 97
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/before.md
  33. 79
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/front.md
  34. 138
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/ops.md
  35. 8
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/uplog.md
  36. 198
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/adumbrate.md
  37. 602
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/backend.md
  38. 135
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/before.md
  39. 79
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/front.md
  40. 211
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/ops.md
  41. 8
    0
      cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/uplog.md
  42. 13401
    0
      cmc-temperature-back/docs/ruoyi-docs/package-lock.json
  43. 20
    0
      cmc-temperature-back/docs/ruoyi-docs/package.json
  44. 95
    0
      cmc-temperature-back/pom.xml
  45. BIN
      cmc-temperature-back/qun.png
  46. 62
    0
      cmc-temperature-back/ruoyi-admin/pom.xml
  47. 28
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
  48. 35
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
  49. 61
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/LoginController.java
  50. 163
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
  51. 109
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/UserOnlineController.java
  52. 128
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
  53. 119
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
  54. 129
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
  55. 119
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
  56. 102
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginLogController.java
  57. 124
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
  58. 87
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
  59. 90
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOperLogController.java
  60. 117
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
  61. 177
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
  62. 234
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  63. 32
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/FileController.java
  64. 150
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/GenTableController.java
  65. 186
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/JobController.java
  66. 90
    0
      cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SysJobLogController.java
  67. 240
    0
      cmc-temperature-back/ruoyi-admin/src/main/resources/app-dev.yml
  68. 235
    0
      cmc-temperature-back/ruoyi-admin/src/main/resources/app-prod.yml
  69. 7
    0
      cmc-temperature-back/ruoyi-admin/src/main/resources/app.yml
  70. 1
    0
      cmc-temperature-back/ruoyi-admin/src/main/resources/banner.txt
  71. 90
    0
      cmc-temperature-back/ruoyi-admin/src/main/resources/logback-solon.xml
  72. 30
    0
      cmc-temperature-back/ruoyi-admin/src/main/resources/quartz.properties
  73. BIN
      cmc-temperature-back/ruoyi-admin/src/main/resources/static/cmc-temperature.db
  74. 86
    0
      cmc-temperature-back/ruoyi-common/pom.xml
  75. 43
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/CacheConstant.java
  76. 20
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/DataSourceConstant.java
  77. 117
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/GenConstant.java
  78. 50
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/HttpConstant.java
  79. 68
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/UserConstant.java
  80. 57
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
  81. 27
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java
  82. 77
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/DictEnum.java
  83. 24
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/RateLimitType.java
  84. 56
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/ContextUtil.java
  85. 53
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/CryptoUtil.java
  86. 47
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExcelUtil.java
  87. 87
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/FileUtil.java
  88. 332
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtil.java
  89. 171
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtil.java
  90. 143
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/XssUtil.java
  91. 86
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/controller/BaseController.java
  92. 39
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/BaseEntity.java
  93. 27
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/PageData.java
  94. 33
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/TreeEntity.java
  95. 40
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/Cache.java
  96. 69
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/SysDept.java
  97. 87
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/SysRole.java
  98. 105
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/SysUser.java
  99. 69
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/UserOnline.java
  100. 0
    0
      cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/model/LoginBody.java

+ 25
- 0
cmc-temperature-back/.gitignore 파일 보기

@@ -0,0 +1,25 @@
1
+target/
2
+!.mvn/wrapper/maven-wrapper.jar
3
+
4
+### STS ###
5
+.apt_generated
6
+.classpath
7
+.factorypath
8
+.project
9
+.settings
10
+.springBeans
11
+
12
+### IntelliJ IDEA ###
13
+.idea
14
+*.iws
15
+*.iml
16
+*.ipr
17
+*.log
18
+*.flattened-pom.xml
19
+
20
+### NetBeans ###
21
+dist/
22
+logs/
23
+
24
+### Mac files ###
25
+.DS_Store

+ 201
- 0
cmc-temperature-back/LICENSE 파일 보기

@@ -0,0 +1,201 @@
1
+                                 Apache License
2
+                           Version 2.0, January 2004
3
+                        http://www.apache.org/licenses/
4
+
5
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+   1. Definitions.
8
+
9
+      "License" shall mean the terms and conditions for use, reproduction,
10
+      and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+      "Licensor" shall mean the copyright owner or entity authorized by
13
+      the copyright owner that is granting the License.
14
+
15
+      "Legal Entity" shall mean the union of the acting entity and all
16
+      other entities that control, are controlled by, or are under common
17
+      control with that entity. For the purposes of this definition,
18
+      "control" means (i) the power, direct or indirect, to cause the
19
+      direction or management of such entity, whether by contract or
20
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+      outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+      "You" (or "Your") shall mean an individual or Legal Entity
24
+      exercising permissions granted by this License.
25
+
26
+      "Source" form shall mean the preferred form for making modifications,
27
+      including but not limited to software source code, documentation
28
+      source, and configuration files.
29
+
30
+      "Object" form shall mean any form resulting from mechanical
31
+      transformation or translation of a Source form, including but
32
+      not limited to compiled object code, generated documentation,
33
+      and conversions to other media types.
34
+
35
+      "Work" shall mean the work of authorship, whether in Source or
36
+      Object form, made available under the License, as indicated by a
37
+      copyright notice that is included in or attached to the work
38
+      (an example is provided in the Appendix below).
39
+
40
+      "Derivative Works" shall mean any work, whether in Source or Object
41
+      form, that is based on (or derived from) the Work and for which the
42
+      editorial revisions, annotations, elaborations, or other modifications
43
+      represent, as a whole, an original work of authorship. For the purposes
44
+      of this License, Derivative Works shall not include works that remain
45
+      separable from, or merely link (or bind by name) to the interfaces of,
46
+      the Work and Derivative Works thereof.
47
+
48
+      "Contribution" shall mean any work of authorship, including
49
+      the original version of the Work and any modifications or additions
50
+      to that Work or Derivative Works thereof, that is intentionally
51
+      submitted to Licensor for inclusion in the Work by the copyright owner
52
+      or by an individual or Legal Entity authorized to submit on behalf of
53
+      the copyright owner. For the purposes of this definition, "submitted"
54
+      means any form of electronic, verbal, or written communication sent
55
+      to the Licensor or its representatives, including but not limited to
56
+      communication on electronic mailing lists, source code control systems,
57
+      and issue tracking systems that are managed by, or on behalf of, the
58
+      Licensor for the purpose of discussing and improving the Work, but
59
+      excluding communication that is conspicuously marked or otherwise
60
+      designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+      "Contributor" shall mean Licensor and any individual or Legal Entity
63
+      on behalf of whom a Contribution has been received by Licensor and
64
+      subsequently incorporated within the Work.
65
+
66
+   2. Grant of Copyright License. Subject to the terms and conditions of
67
+      this License, each Contributor hereby grants to You a perpetual,
68
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+      copyright license to reproduce, prepare Derivative Works of,
70
+      publicly display, publicly perform, sublicense, and distribute the
71
+      Work and such Derivative Works in Source or Object form.
72
+
73
+   3. Grant of Patent License. Subject to the terms and conditions of
74
+      this License, each Contributor hereby grants to You a perpetual,
75
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+      (except as stated in this section) patent license to make, have made,
77
+      use, offer to sell, sell, import, and otherwise transfer the Work,
78
+      where such license applies only to those patent claims licensable
79
+      by such Contributor that are necessarily infringed by their
80
+      Contribution(s) alone or by combination of their Contribution(s)
81
+      with the Work to which such Contribution(s) was submitted. If You
82
+      institute patent litigation against any entity (including a
83
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+      or a Contribution incorporated within the Work constitutes direct
85
+      or contributory patent infringement, then any patent licenses
86
+      granted to You under this License for that Work shall terminate
87
+      as of the date such litigation is filed.
88
+
89
+   4. Redistribution. You may reproduce and distribute copies of the
90
+      Work or Derivative Works thereof in any medium, with or without
91
+      modifications, and in Source or Object form, provided that You
92
+      meet the following conditions:
93
+
94
+      (a) You must give any other recipients of the Work or
95
+          Derivative Works a copy of this License; and
96
+
97
+      (b) You must cause any modified files to carry prominent notices
98
+          stating that You changed the files; and
99
+
100
+      (c) You must retain, in the Source form of any Derivative Works
101
+          that You distribute, all copyright, patent, trademark, and
102
+          attribution notices from the Source form of the Work,
103
+          excluding those notices that do not pertain to any part of
104
+          the Derivative Works; and
105
+
106
+      (d) If the Work includes a "NOTICE" text file as part of its
107
+          distribution, then any Derivative Works that You distribute must
108
+          include a readable copy of the attribution notices contained
109
+          within such NOTICE file, excluding those notices that do not
110
+          pertain to any part of the Derivative Works, in at least one
111
+          of the following places: within a NOTICE text file distributed
112
+          as part of the Derivative Works; within the Source form or
113
+          documentation, if provided along with the Derivative Works; or,
114
+          within a display generated by the Derivative Works, if and
115
+          wherever such third-party notices normally appear. The contents
116
+          of the NOTICE file are for informational purposes only and
117
+          do not modify the License. You may add Your own attribution
118
+          notices within Derivative Works that You distribute, alongside
119
+          or as an addendum to the NOTICE text from the Work, provided
120
+          that such additional attribution notices cannot be construed
121
+          as modifying the License.
122
+
123
+      You may add Your own copyright statement to Your modifications and
124
+      may provide additional or different license terms and conditions
125
+      for use, reproduction, or distribution of Your modifications, or
126
+      for any such Derivative Works as a whole, provided Your use,
127
+      reproduction, and distribution of the Work otherwise complies with
128
+      the conditions stated in this License.
129
+
130
+   5. Submission of Contributions. Unless You explicitly state otherwise,
131
+      any Contribution intentionally submitted for inclusion in the Work
132
+      by You to the Licensor shall be under the terms and conditions of
133
+      this License, without any additional terms or conditions.
134
+      Notwithstanding the above, nothing herein shall supersede or modify
135
+      the terms of any separate license agreement you may have executed
136
+      with Licensor regarding such Contributions.
137
+
138
+   6. Trademarks. This License does not grant permission to use the trade
139
+      names, trademarks, service marks, or product names of the Licensor,
140
+      except as required for reasonable and customary use in describing the
141
+      origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+   7. Disclaimer of Warranty. Unless required by applicable law or
144
+      agreed to in writing, Licensor provides the Work (and each
145
+      Contributor provides its Contributions) on an "AS IS" BASIS,
146
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+      implied, including, without limitation, any warranties or conditions
148
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+      PARTICULAR PURPOSE. You are solely responsible for determining the
150
+      appropriateness of using or redistributing the Work and assume any
151
+      risks associated with Your exercise of permissions under this License.
152
+
153
+   8. Limitation of Liability. In no event and under no legal theory,
154
+      whether in tort (including negligence), contract, or otherwise,
155
+      unless required by applicable law (such as deliberate and grossly
156
+      negligent acts) or agreed to in writing, shall any Contributor be
157
+      liable to You for damages, including any direct, indirect, special,
158
+      incidental, or consequential damages of any character arising as a
159
+      result of this License or out of the use or inability to use the
160
+      Work (including but not limited to damages for loss of goodwill,
161
+      work stoppage, computer failure or malfunction, or any and all
162
+      other commercial damages or losses), even if such Contributor
163
+      has been advised of the possibility of such damages.
164
+
165
+   9. Accepting Warranty or Additional Liability. While redistributing
166
+      the Work or Derivative Works thereof, You may choose to offer,
167
+      and charge a fee for, acceptance of support, warranty, indemnity,
168
+      or other liability obligations and/or rights consistent with this
169
+      License. However, in accepting such obligations, You may act only
170
+      on Your own behalf and on Your sole responsibility, not on behalf
171
+      of any other Contributor, and only if You agree to indemnify,
172
+      defend, and hold each Contributor harmless for any liability
173
+      incurred by, or claims asserted against, such Contributor by reason
174
+      of your accepting any such warranty or additional liability.
175
+
176
+   END OF TERMS AND CONDITIONS
177
+
178
+   APPENDIX: How to apply the Apache License to your work.
179
+
180
+      To apply the Apache License to your work, attach the following
181
+      boilerplate notice, with the fields enclosed by brackets "[]"
182
+      replaced with your own identifying information. (Don't include
183
+      the brackets!)  The text should be enclosed in the appropriate
184
+      comment syntax for the file format. We also recommend that a
185
+      file or class name and description of purpose be included on the
186
+      same "printed page" as the copyright notice for easier
187
+      identification within third-party archives.
188
+
189
+   Copyright [yyyy] [name of copyright owner]
190
+
191
+   Licensed under the Apache License, Version 2.0 (the "License");
192
+   you may not use this file except in compliance with the License.
193
+   You may obtain a copy of the License at
194
+
195
+       http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+   Unless required by applicable law or agreed to in writing, software
198
+   distributed under the License is distributed on an "AS IS" BASIS,
199
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+   See the License for the specific language governing permissions and
201
+   limitations under the License.

+ 95
- 0
cmc-temperature-back/README.md 파일 보기

@@ -0,0 +1,95 @@
1
+<p align="center">
2
+    <img src="https://gitee.com/opensolon/ruoyi-solon/raw/master/ruoyi-solon-ui/src/assets/images/logo/logo.png" alt="" />
3
+</p>
4
+
5
+<h1 align="center">RuoYi-Solon</h1>
6
+<h3 align="center">v2.1.1</h3>
7
+
8
+<h4 align="center">基于 Solon 和 Vue 前后端分离的Java快速开发框架</h4>
9
+
10
+<p align="center">
11
+    <a href="https://gitee.com/opensolon/ruoyi-solon/stargazers">
12
+        <img src="https://gitee.com/opensolon/ruoyi-solon/badge/star.svg?theme=dark" alt="" />
13
+    </a>
14
+	<a href="https://gitee.com/opensolon/ruoyi-solon/blob/master/LICENSE">
15
+	    <img src="https://img.shields.io/badge/License-Apache 2.0-green" alt="" />
16
+	</a>
17
+</p>
18
+
19
+## 平台简介
20
+若依是一套开源的快速开发平台。
21
+
22
+* 采用前后端分离的模式,单体架构。
23
+* 后端技术栈:Solon、HikariCP、Mybatis-Flex、Redis、Sa-Token、Hutool等。
24
+* 前端技术栈:Vue、Vue-Router、Vuex/Pinia、Element-UI/Element-Plus、Axios等。
25
+* 微服务版请移步 [RuoYi-Cloud-Solon](https://gitee.com/opensolon/ruoyi-cloud-solon)。
26
+
27
+## 框架对比
28
+与基于`SpringBoot`开发的版本对比:
29
+
30
+|    |  Solon版  |  SpringBoot版  |
31
+|  :--:  |  :--:  |  :--:  |
32
+|  打包体积(MB)  |  46.64  |  72.15  |
33
+|  启动速度(s)  |  1.4  |  4.6  |
34
+|  内存占用(%)  |  4.1  |  8.1  |
35
+
36
+## 版本分支
37
+* 默认`master`分支,后端采用`Maven`作为构建工具。
38
+* `gradle`分支,后端采用`Gradle`作为构建工具。
39
+> 不建议直接`clone`分支代码,推荐下载`发行版`或`标签`中的最新版本。
40
+
41
+## 系统模块
42
+~~~
43
+com.ruoyi
44
+├── ruoyi-admin                        // 接口模块 [8080]
45
+├── ruoyi-common                       // 通用模块
46
+├── ruoyi-framework                    // 框架核心
47
+├── ruoyi-gen                          // 代码生成
48
+├── ruoyi-schedule                     // 任务调度
49
+├── ruoyi-solon-ui                     // 前端框架 [80](Vue2)
50
+├── ruoyi-solon-ui-vue3                // 前端框架 [80](Vue3)
51
+├── ruoyi-system                       // 系统模块
52
+├── pom.xml                            // 公共依赖
53
+~~~
54
+
55
+## 内置功能
56
+1.  用户管理:用户是系统操作者,该功能主要完成系统用户配置。
57
+2.  部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
58
+3.  岗位管理:配置系统用户所属担任职务。
59
+4.  菜单管理:配置系统菜单,操作权限,按钮权限标识等。
60
+5.  角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
61
+6.  字典管理:对系统中经常使用的一些较为固定的数据进行维护。
62
+7.  参数管理:对系统动态配置常用参数。
63
+8.  通知公告:系统通知公告信息发布维护。
64
+9.  操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
65
+10. 登录日志:系统登录日志记录查询包含登录异常。
66
+11. 在线构建:拖动表单元素生成相应的HTML代码。
67
+12. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载。
68
+13. 定时任务:任务调度及调度日志记录。
69
+14. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
70
+15. 系统接口:根据业务代码自动生成相关的api接口文档。
71
+16. 在线用户:当前系统中活跃用户状态监控。
72
+17. 缓存监控:对系统的缓存信息查询。
73
+
74
+## 版本要求
75
+|    |  要求  |  推荐  |
76
+|  :--:  |  :--:  |  :--:  |
77
+|  JDK  |  >= 1.8  |  1.8  |
78
+|  Maven  |  >= 3.6.3  |  3.6.3  |
79
+|  Node |  >= 14  |  14.21.3  |
80
+|  MySQL |  >= 5.6  |  5.6.36  |
81
+|  Redis |  >= 3  |  3.2.100  |
82
+
83
+## 在线体验
84
+演示地址:[http://123.57.166.12](http://123.57.166.12)  
85
+账密:admin/Admin@123
86
+
87
+在线文档:[http://123.57.166.12:90](http://123.57.166.12:90)
88
+
89
+>演示地址和在线文档将于`2025年底`到期
90
+
91
+## 捐赠支持
92
+<img src="https://gitee.com/opensolon/ruoyi-solon/raw/master/ruoyi-solon-ui/src/assets/images/pay.jpg" alt="" />
93
+
94
+## 群
95
+<img src="https://gitee.com/opensolon/ruoyi-solon/raw/master/qun.png" alt="" />

+ 22
- 0
cmc-temperature-back/docs/ruoyi-docs/.editorconfig 파일 보기

@@ -0,0 +1,22 @@
1
+# 告诉EditorConfig插件,这是根文件,不用继续往上查找
2
+root = true
3
+
4
+# 匹配全部文件
5
+[*]
6
+# 设置字符集
7
+charset = utf-8
8
+# 缩进风格,可选space、tab
9
+indent_style = tab
10
+# 缩进的空格数
11
+indent_size = 2
12
+# 结尾换行符,可选lf、cr、crlf
13
+end_of_line = lf
14
+# 在文件结尾插入新行
15
+insert_final_newline = true
16
+# 删除一行中的前后空格
17
+trim_trailing_whitespace = true
18
+
19
+# 匹配md结尾的文件
20
+[*.md]
21
+insert_final_newline = false
22
+trim_trailing_whitespace = false

+ 14
- 0
cmc-temperature-back/docs/ruoyi-docs/.gitignore 파일 보기

@@ -0,0 +1,14 @@
1
+node_modules/
2
+dist/
3
+
4
+# Editor directories and files
5
+.idea
6
+.vscode
7
+*.suo
8
+*.ntvs*
9
+*.njsproj
10
+*.sln
11
+*.local
12
+
13
+# package-lock.json
14
+yarn.lock

+ 43
- 0
cmc-temperature-back/docs/ruoyi-docs/README.md 파일 보기

@@ -0,0 +1,43 @@
1
+## 轻舟文档中心
2
+基于 VuePress 编写 Markdown(也就是.md文件) 来生成在线文档
3
+
4
+# VuePress官网
5
+https://v1.vuepress.vuejs.org/zh
6
+
7
+
8
+### 运行指南
9
+```bash
10
+# 进入项目目录
11
+cd ruoyi-docs
12
+
13
+# 安装依赖
14
+npm install
15
+
16
+# 启动服务
17
+npm run dev
18
+```
19
+
20
+### 开发指南
21
+1、在 /docs 目录下创建文件夹 a ,并在 a 中创建文件 b.md\
22
+2、在 /docs/.vuepress/sidebar.js 中增加侧边栏配置
23
+
24
+```javascript
25
+// 侧边栏
26
+module.exports = [
27
+  {
28
+    title: '文档a',
29
+    sidebarDepth: 0,  // 可选的, 默认值是 1
30
+    children: [ '/a/b' ]
31
+  }
32
+]
33
+```
34
+
35
+### 打包指南
36
+```bash
37
+# 构建生产环境
38
+npm run build
39
+```
40
+
41
+
42
+# Markdown在线编写地址
43
+https://markdown.com.cn/editor/

+ 42
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/config.js 파일 보기

@@ -0,0 +1,42 @@
1
+
2
+module.exports = {
3
+  // 部署站点的基础路径
4
+  base: '/',
5
+  title: 'RuoYi',
6
+  // 注入到当前页面的 HTML <head> 中的标签
7
+  head: [
8
+    ['link', { rel: 'icon', href: '/favicon.ico' }], // 网页标签的图标
9
+  ],
10
+  host: '0.0.0.0',
11
+  port: 80,
12
+  devServer: {
13
+    useLocalIp: true, // 避免打开浏览器为0.0.0.0,需手动改IP的情况
14
+    open: true,  // 自动打开浏览器
15
+  },
16
+  // 指定 vuepress build 的输出目录
17
+  dest: 'dist',
18
+  // 多语言支持
19
+  locales: {
20
+    '/': {
21
+      lang: 'zh-CN'
22
+    }
23
+  },
24
+  // 你可以监听任何想监听的文件,文件变动将会触发 vuepress 重新构建,并实时更新。
25
+  extraWatchFiles: [
26
+    '.vuepress/nav.js',
27
+    '.vuepress/sidebar.js'
28
+  ],
29
+  // 主题配置
30
+  themeConfig: {
31
+    logo: '/favicon.ico', // 导航栏左侧logo
32
+    lastUpdated: '最后更新时间', // 文档更新时间:每个文件git最后提交的时间
33
+    // 右上角导航栏
34
+    nav: require("./nav.js"),
35
+    // 侧边栏
36
+    sidebar: require("./sidebar.js")
37
+  },
38
+  // 插件
39
+  plugins: [
40
+
41
+  ]
42
+}

+ 9
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/enhanceApp.js 파일 보기

@@ -0,0 +1,9 @@
1
+/*
2
+ * main.js
3
+ */
4
+
5
+import Vue from 'vue';
6
+import ElementUI from 'element-ui';
7
+import 'element-ui/lib/theme-chalk/index.css';
8
+
9
+Vue.use(ElementUI);

+ 32
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/nav.js 파일 보기

@@ -0,0 +1,32 @@
1
+// 右上角导航栏
2
+module.exports = [
3
+  {
4
+    text: '首页',
5
+    link: '/'  // 内部链接,以docs为根目录
6
+  },
7
+  {
8
+    text: '概述',
9
+    link: '/guide/adumbrate/'  // 内部链接(以 / 开头并结尾,默认读取文件夹下的 README.md)
10
+  },
11
+  {
12
+    text: '单体版',
13
+    link: '/guide/boot/adumbrate'  // 内部链接(以 / 开头,不写 .md 后缀,默认读取文件夹下对应的 .md 文件)
14
+  },
15
+  {
16
+    text: '微服务版',
17
+    link: '/guide/cloud/adumbrate'
18
+  },
19
+  {
20
+    text: '移动端版',
21
+    link: '/guide/app/adumbrate'
22
+  },
23
+  {
24
+    text: 'Gitee',
25
+    // 下拉列表
26
+    items: [
27
+      { text: '单体版', link: 'https://gitee.com/opensolon/ruoyi-solon' },
28
+      { text: '微服务版', link: 'https://gitee.com/opensolon/ruoyi-cloud-solon' },
29
+      { text: '移动端版', link: '/' }
30
+    ]
31
+  }
32
+]

BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/boot/gradle_settings.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/boot/mysql.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/cloud.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/common.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/mysql.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/nacos1.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/nacos2.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/nacos3.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/cloud/namespace.png 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/coding.gif 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/favicon.ico 파일 보기


BIN
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/public/logo.png 파일 보기


+ 9
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/.vuepress/sidebar.js 파일 보기

@@ -0,0 +1,9 @@
1
+// 侧边栏
2
+module.exports = {
3
+  '/guide/boot/': [
4
+    'adumbrate', 'before', 'backend', 'front', 'ops', 'uplog'
5
+  ],
6
+  '/guide/cloud/': [
7
+    'adumbrate', 'before', 'backend', 'front', 'ops', 'uplog'
8
+  ]
9
+}

+ 16
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/README.md 파일 보기

@@ -0,0 +1,16 @@
1
+---
2
+home: true
3
+heroImage: /logo.png
4
+heroText: RuoYi
5
+tagline: 使用若依快速构建应用程序
6
+actionText: 快速上手 →
7
+actionLink: /guide/adumbrate/
8
+features:
9
+- title: 单体版
10
+  details: 前后端分离的版本:前端技术有 Vue、ElementUi 等,后端技术有 Solon、Sa-Token、Mybatis-Flex 等。
11
+- title: 微服务版
12
+  details: 前后端分离的微服务架构版本:前端技术有 Vue、ElementUi 等,后端技术有 Solon Cloud、Nacos、Sa-Token、Mybatis-Flex 等。
13
+- title: 移动端版
14
+  details: 前后端分离的APP版本
15
+footer: Copyright © 2023-2025 ruoyi All rights reserved.
16
+---

+ 49
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/adumbrate/README.md 파일 보기

@@ -0,0 +1,49 @@
1
+## 概述
2
+<h1 align="center">RuoYi</h1>
3
+
4
+<h4 align="center">基于 Solon、Vue 的权限后台管理系统</h4>
5
+
6
+<p align="center">
7
+  <a href="#">
8
+    <img src="https://img.shields.io/badge/License-Apache 2.0-green" />
9
+  </a>
10
+</p>
11
+
12
+### 若依是什么?
13
+本项目属于 [若依](https://www.ruoyi.vip) 系统的 Solon 版本,具备与若依相同的系统功能。如果您有若依系统的开发经验,可轻松上手。
14
+
15
+> 若依是 SpringBoot + Vue  
16
+本项目是 Solon + Vue  
17
+前端是一样的,区别在后端。
18
+
19
+### Solon 是什么?
20
+为什么要重写若依?因为 [Solon](https://solon.noear.org)。  
21
+若依后端是基于 SpringBoot 开发的,而 Solon 与 SpringBoot 同属于 Java 语言开发框架。优势在于其构建的应用,打包体积更小,启动速度更快,内存占用更低,并发更高。
22
+
23
+***看下对比:***
24
+|    |  Solon版  |  SpringBoot版  |
25
+|  :--:  |  :--:  |  :--:  |
26
+|  打包体积(MB)  |  46.64  |  72.15  |
27
+|  启动速度(s)  |  1.4  |  4.6  |
28
+|  内存占用(%)  |  4.1  |  8.1  |
29
+
30
+> 参与过运维的同学都知道,SpringBoot 项目打包动辄几百兆,跑起来内存占用轻松达到 GB 级别。  
31
+用了 Solon ,内存和存储预算直接减半,在云原生时代岂不是很香?
32
+
33
+### 版本
34
+目前提供了2个版本:
35
+* 单体版:[RuoYi-Solon](https://gitee.com/opensolon/ruoyi-solon)
36
+* 微服务版:[RuoYi-Cloud-Solon](https://gitee.com/opensolon/ruoyi-cloud-solon)
37
+
38
+### 在线体验
39
+[http://123.57.166.12](http://123.57.166.12)  
40
+账密:admin/Admin@123
41
+
42
+>演示地址将于`2025年底`到期
43
+
44
+## 声明
45
+本项目采用`Apache-2.0`开源协议。
46
+
47
+无担保声明:Apache 许可证明确声明开源项目是以 “AS IS” 的方式提供的,即不提供任何形式的明示或暗示的担保,包括但不限于对项目的适用性、完整性、准确性、安全性等方面的担保。使用者在使用项目时需自行承担由此可能带来的风险。
48
+
49
+责任限制:在任何情况下,开源项目的作者或版权所有者对使用者因使用该项目而产生的任何直接、间接、特殊、偶然或后果性的损害,包括但不限于数据丢失、业务中断、利润损失等,均不承担任何责任。

+ 14
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/adumbrate.md 파일 보기

@@ -0,0 +1,14 @@
1
+---
2
+title: 简介(移动端版)
3
+prev: false
4
+# next: ./before
5
+---
6
+
7
+<el-alert
8
+  title="开发中..."
9
+  type="warning"
10
+  effect="dark"
11
+  :closable="false">
12
+</el-alert>
13
+
14
+![开发中...](../../.vuepress/public/coding.gif)

+ 279
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/backend.md 파일 보기

@@ -0,0 +1,279 @@
1
+---
2
+title: 后端手册
3
+prev: false
4
+# next: ./front
5
+---
6
+
7
+::: danger 注意
8
+请牢记您是在写 Solon 项目,而不是 SpringBoot 项目。
9
+:::
10
+::: warning 注意
11
+微服务版和单体版的很多功能都是一致的。这里只列举出有区别的功能说明。未列举的功能请前往 [单体版文档](../boot/dev.md)。
12
+:::
13
+
14
+## 演示模块
15
+`qingzhou-modules-demo`是演示模块。如果您想创建新的服务模块,请参照此演示模块进行创建,您也可以直接改造演示模块。
16
+
17
+## 配置自动刷新
18
+所有服务模块的配置文件都在`Nacos`中,以下配置支持自动刷新(autoRefreshed = true):
19
+* 验证码配置:qingzhou.auth.*
20
+* 文件配置:qingzhou.file.*
21
+* 代码生成配置:qingzhou.gen.*
22
+::: warning 注意
23
+由于 Solon 内部机制的设计,如果您在`Nacos`中配置了数组类型的配置,然后在后端使用数组或List接收,并开启配置自动刷新,当配置变化后,会导致接收的配置参数重复导致混乱。
24
+
25
+因此如果您想实现数组类型的配置自动刷新,请配置为字符串形式,并在后端使用字符串切割为数组(参考文件配置或代码生成配置的自动刷新)。
26
+:::
27
+
28
+## 上传下载
29
+* 上传
30
+  * 前端采用`ElementUI`的上传组件 Upload。
31
+  * 后端支持本地文件上传及云存储(`qingzhou-modules-file`模块)。
32
+  ::: warning 注意
33
+  * 文件上传针对文件类型和文件大小在前端和后端都做了限制。
34
+    * 后端文件上传配置示例
35
+    ```yaml
36
+    qingzhou:
37
+      file:
38
+        # 使用的文件服务类型: s3 本地文件存储、aliyun 阿里云对象存储、qiniu 七牛云对象存储、minio
39
+        # 请前往 file 模块的 pom.xml 注释掉不用的文件服务依赖
40
+        type: s3
41
+        # 允许上传的文件大小(单位:MB,设为-1不限制)
42
+        maxSize: 2
43
+        # 允许上传的文件类型
44
+        fileType: jpg, jpeg, png, doc, docx, xls, xlsx, ppt, txt, pdf, zip
45
+
46
+    solon:
47
+      cloud:
48
+        # 本地文件 
49
+        file:
50
+          s3:
51
+            file:
52
+              default: local_bucket
53
+              buckets:
54
+                local_bucket:
55
+                  endpoint: C:\Users\xiaoming\Desktop
56
+                  requestPrefix: http://localhost:90/qingzhou-file
57
+                # more_bucket:
58
+                #   regionId: cn-east-1
59
+                #   endpoint: http://s3.ladydaily.com
60
+                #   accessKey: iWeU7cOoPLRokg2Hdat0jGQC
61
+                #   secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
62
+        # 阿里云 OSS
63
+        aliyun:
64
+          oss:
65
+            file:
66
+              endpoint: oss-cn-xxx.aliyuncs.com
67
+              bucket: world-data-dev
68
+              accessKey: iWeU7cOoPLRokg2Hdat0jGQC
69
+              secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
70
+        # 七牛云 OSS
71
+        qiniu:
72
+          kodo:
73
+            file:
74
+              regionId: cn-east-1
75
+              endpoint: https://xxx.yyy.zzz
76
+              requestPrefix: https://aaa.bbb.ccc
77
+              bucket: world-data-dev
78
+              accessKey: iWeU7cOoPLRokg2Hdat0jGQC
79
+              secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
80
+        # minio
81
+        minio:
82
+          file:
83
+            regionId: cn-east-1
84
+            endpoint: https://play.min.io
85
+            bucket: asiatrip
86
+            accessKey: iWeU7cOoPLRokg2Hdat0jGQC
87
+            secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
88
+    ```
89
+    * 默认使用本地文书上传。如果您想更换为其他上传方式(比如阿里云OSS),请先前往`qingzhou-modules-file`模块的`pom.xml`文件或`build.gradle`文件,打开阿里云OSS的注释,并注释掉其它的;并且修改上方文件上传配置:`qingzhou.file.type: aliyun`,重启`qingzhou-modules-file`服务。
90
+    ```xml
91
+    <!-- Maven 版 -->
92
+    <dependencies>
93
+      <!-- 本地文件 -->
94
+      <!--<dependency>-->
95
+        <!--<groupId>org.noear</groupId>-->
96
+        <!--<artifactId>file-s3-solon-cloud-plugin</artifactId>-->
97
+      <!--</dependency>-->
98
+
99
+      <!-- 阿里云 OSS -->
100
+      <dependency>
101
+        <groupId>org.noear</groupId>
102
+        <artifactId>aliyun-oss-solon-cloud-plugin</artifactId>
103
+      </dependency>
104
+
105
+      <!-- 七牛云 OSS -->
106
+      <!--<dependency>-->
107
+        <!--<groupId>org.noear</groupId>-->
108
+        <!--<artifactId>qiniu-kodo-solon-cloud-plugin</artifactId>-->
109
+      <!--</dependency>-->
110
+
111
+      <!-- minio(minio基于 minio8 sdk,minio7基于 minio7 sdk) -->
112
+      <!--<dependency>-->
113
+        <!--<groupId>org.noear</groupId>-->
114
+        <!--<artifactId>minio-solon-cloud-plugin</artifactId>-->
115
+      <!--</dependency>-->
116
+      <!--<dependency>-->
117
+        <!--<groupId>org.noear</groupId>-->
118
+        <!--<artifactId>minio7-solon-cloud-plugin</artifactId>-->
119
+      <!--</dependency>-->
120
+    </dependencies>
121
+    ```
122
+    ```gradle
123
+    //  Gradle 版
124
+    dependencies {
125
+      ...
126
+      //  implementation 'org.noear:file-s3-solon-cloud-plugin'
127
+      implementation 'org.noear:aliyun-oss-solon-cloud-plugin'
128
+      //  implementation 'org.noear:qiniu-kodo-solon-cloud-plugin'
129
+      //  implementation 'org.noear:minio-solon-cloud-plugin'
130
+      //  implementation 'org.noear:minio7-solon-cloud-plugin'
131
+    }
132
+    ```
133
+  * 如果您使用的是本地文件上传,您需要搭配工具来实现本地文件的访问(例如 Nginx)。
134
+    * Nginx配置示例
135
+    ```
136
+    server {
137
+      listen       90;
138
+      server_name  localhost;
139
+
140
+      location /qingzhou-file {
141
+        alias   C:/Users/xiaoming/Desktop/;
142
+        autoindex on;
143
+      }
144
+    }
145
+    ```
146
+  :::
147
+  * 文件上传大小受以下几处限制:
148
+    * 前端上传组件
149
+    * 后端Web服务器的请求体大小:server.request.maxFileSize: 2mb
150
+    * 后端文件上传配置:qingzhou.file.maxSize: 2
151
+    * 前端部署到服务器后(例如 Nginx),Nginx限制的请求体大小
152
+* 下载\
153
+数据导出即采用了文件下载,您可以参照数据导出的实现。
154
+
155
+## 权限注解
156
+与单体版的不同之处在于,微服务有单独的安全模块`qingzhou-common-security`。所有的微服务模块都应引入此安全模块。
157
+
158
+## 统一返回结果 & 异常处理
159
+同样的,微服务有单独的统一返回模块`qingzhou-common-result`。所有的微服务模块都应引入此统一返回模块。
160
+
161
+## 熔断限流
162
+使用`sentinel`实现。
163
+* 配置示例(share-config-dev.yml)
164
+```yaml
165
+solon:
166
+  cloud:
167
+    local:
168
+      # 限流
169
+      breaker:
170
+        # 根断路器的阀值(即默认阀值,必须大于0)
171
+        root: 1000
172
+        # global 为断路器名称(不配置或配置0,则取根断路器的阀值)
173
+        # global: 100
174
+```
175
+* 全局限流:`com.ruoyi.common.security.filter.GlobalFilter`
176
+* [Solon熔断限流](https://solon.noear.org/article/160)
177
+
178
+## 系统接口文档
179
+从`v2.5.0`版本开始增加了文档模块,使用`knife4j`实现。\
180
+* 接口文档配置(位于 nacos 的 share-config-dev.yml 中)
181
+  ```yaml
182
+  knife4j:
183
+    # 开启增强配置
184
+    enable: true
185
+    # 开启生产环境屏蔽
186
+    production: false
187
+    # 签权
188
+    # basic:
189
+    #   enable: true
190
+    #   username: admin
191
+    #   password: 123456
192
+    # 前端UI的个性化配置
193
+    setting:
194
+      enableVersion: true
195
+      enableOpenApi: false
196
+      enableFooter: false
197
+  ```
198
+* 为服务模块引入文档模块
199
+  ```xml
200
+  <!-- 接口文档模块 -->
201
+  <dependency>
202
+      <groupId>com.ruoyi</groupId>
203
+      <artifactId>qingzhou-common-swagger</artifactId>
204
+  </dependency>
205
+  ```
206
+* 接口文档摘要:基于配置文件构建(在服务模块的配置文件中增加下方配置)
207
+  ```yaml
208
+  solon:
209
+    # 接口文档
210
+    docs:
211
+      routes:
212
+        - id: openapi  # 固定值
213
+          # groupName: group-name
214
+          info:
215
+            title: 接口文档
216
+            description: 在线API文档
217
+  #          termsOfService: https://gitee.com/noear/solon
218
+            contact:
219
+              name: xm
220
+            version: 1.0
221
+          schemes:
222
+            - HTTP
223
+            - HTTPS
224
+          globalResponseInData: true
225
+          globalResult: org.noear.solon.core.handle.Result
226
+          apis:
227
+            - basePackage: com.ruoyi.system.controller
228
+  ```
229
+* 给接口添加注解
230
+  ```java {1,6}
231
+  @Api("系统参数配置")
232
+  @Controller
233
+  @Mapping("system/config")
234
+  public class SysConfigController extends BaseController {
235
+
236
+    @ApiOperation("列表查询")
237
+    @Get
238
+    @Mapping("list")
239
+    public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
240
+      QueryWrapper qw = getQW(sysConfig);
241
+      Page<SysConfig> result = sysConfigService.page(page, qw);
242
+      return getPageData(result);
243
+    }
244
+
245
+  }
246
+  ```
247
+* 启动`QingZhouDocsApplication`,登录系统(系统工具 -> 系统接口),使用接口文档配置中的签权的账号密码登录
248
+* 如果不需要某个服务模块出现在文档中,可以在`QingZhouDocsApplication`的配置文件中配置忽略该服务
249
+  ```yaml{15-16}
250
+  solon:
251
+    # 接口文档
252
+    docs:
253
+      # 自动发现配置
254
+      discover:
255
+        # 是否启用自动发现
256
+        enabled: true
257
+        # 目标服务的文档接口路径模式(要么带变量 {service},要么用统一固定值)
258
+        uriPattern: swagger/v2?group=openapi
259
+        # 同步目标服务上下线状态(如果下线,则文档不显示)
260
+        syncStatus: false
261
+        # 签权
262
+        basicAuth:
263
+          admin: 123456
264
+        # 排除目标服务名
265
+        excludedServices:
266
+          - qingzhou-auth
267
+          - qingzhou-docs
268
+          - qingzhou-file
269
+          - qingzhou-gen
270
+          - qingzhou-schedule
271
+          - qingzhou-monitor
272
+  ```
273
+
274
+## 系统监控
275
+系统监控分为服务端和客户端,服务端有单独的模块`qingzhou-visual-monitor`,其它每个服务模块作为客户端。
276
+* 您需要先启动`qingzhou-visual-monitor`服务模块
277
+* 打开每个服务模块主启动类上的`@EnableAdminClient`注解的注释
278
+* 监控配置的服务端配置在`qingzhou-monitor-dev.yml`中,客户端配置在`share-config-dev.yml`中。
279
+* 登录系统(系统工具 -> Admin控制台),使用监控配置中的基础签权的账号密码登录

+ 127
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/before.md 파일 보기

@@ -0,0 +1,127 @@
1
+---
2
+title: 项目运行
3
+prev: false
4
+# next: ./backend
5
+---
6
+
7
+## 后端
8
+::: tip 请确认您已有以下运行环境
9
+1. JDK 1.8 及以上
10
+2. Maven 版需要安装 Maven 3.x 及以上(v2.5.1 版本开始要求 Maven 3.6.3 及以上),Gradle 版无需安装 Maven 及 Gradle
11
+:::
12
+
13
+::: warning 另外您还需要安装以下中间件并启动
14
+1. MySQL 5.6.x 及以上
15
+2. Redis 3.x 及以上
16
+3. Nacos 2.x
17
+:::
18
+
19
+### 1、Nacos
20
+您需要向 Nacos 中导入所有微服务模块的配置文件。
21
+* 首先在 Nacos 中创建命名空间:qingzhou
22
+  ::: danger 特别注意
23
+  您需要保证创建的`命名空间id`与后端项目每个微服务模块的配置文件 app.yml 中配置的`nacos.namespace`保持一致!
24
+  :::
25
+  ![namespace](../../.vuepress/public/cloud/namespace.png)
26
+  * 您可以在创建命名空间时将 app.yml 中配置的`nacos.namespace`作为`命名空间id`填入
27
+  * 您也可以在创建命名空间后,将生成的`命名空间id`配置到每个微服务模块的配置文件 app.yml 中的`nacos.namespace`
28
+* 在创建的命名空间 qingzhou 中导入配置文件:
29
+  ![namespace](../../.vuepress/public/cloud/nacos1.png)
30
+  ![namespace](../../.vuepress/public/cloud/nacos2.png)\
31
+  选择 sql 目录下的压缩包 qingzhou-cloud/sql/nacos_config_export_*.zip
32
+* 导入成功:
33
+  ![namespace](../../.vuepress/public/cloud/nacos3.png)
34
+
35
+### 2、数据库
36
+* 在 MySQL 中创建数据库:qingzhou_cloud
37
+  ![mysql](../../.vuepress/public/cloud/mysql.png)
38
+* 向数据库 qingzhou_boot 中导入表:qingzhou-cloud/sql/qingzhou_cloud.sql
39
+* 修改 Nacos 中每个配置文件的数据库连接配置:
40
+  ```yaml {6-8}
41
+  # Redis配置
42
+  redis:
43
+    cache_source:
44
+      config: |
45
+        singleServerConfig:
46
+          address: redis://127.0.0.1:6379
47
+          password:
48
+          database: 7
49
+  ```
50
+  > 请确保 Redis 指定库中没有缓存数据
51
+  ```yaml {10-12}
52
+  # 动态数据源(这是截至 v2.5.0 版本的配置写法)
53
+  ds:
54
+    data_source:
55
+      type: com.zaxxer.hikari.HikariDataSource
56
+      # 严格模式(指定的源不存时,严格模式会抛异常;非严格模式用默认源)
57
+      strict: true
58
+      # default 或 master ,会做为动态源的默认源
59
+      master:
60
+        driverClassName: com.mysql.cj.jdbc.Driver
61
+        jdbcUrl: jdbc:mysql://127.0.0.1:3306/qingzhou_cloud?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
62
+        username: root
63
+        password:
64
+  ```
65
+  ```yaml {12-14}
66
+  # 动态数据源(这是从 v2.5.1 版本开始的配置写法)
67
+  solon:
68
+    dataSources:
69
+      data_source!:
70
+        class: org.noear.solon.data.dynamicds.DynamicDataSource
71
+        # 严格模式(指定的源不存时,严格模式会抛异常;非严格模式用默认源)
72
+        strict: true
73
+        # default 或 master ,会做为动态源的默认源
74
+        master:
75
+          dataSourceClassName: com.zaxxer.hikari.HikariDataSource
76
+          driverClassName: com.mysql.cj.jdbc.Driver
77
+          jdbcUrl: jdbc:mysql://127.0.0.1:3306/qingzhou_cloud?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
78
+          username: root
79
+          password:
80
+  ```
81
+
82
+### 3、运行后端
83
+* 启动:
84
+  * QingZhouGatewayApplication *必要(v1.x)*
85
+  * QingZhouAuthApplication *必要*
86
+  * QingZhouSystemApplication *必要*
87
+  * QingZhouGenApplication
88
+  * QingZhouFileApplication
89
+  * QingZhouScheduleApplication
90
+  * QingZhouDemoApplication
91
+  * QingZhouDocsApplication
92
+::: warning 注意
93
+如果是`Gradle`版,并且您的`IDEA`版本较旧(比如`2018.3`版),启动后访问系统可能会报错:
94
+> Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found.
95
+
96
+或者在账号密码确实输入正确,但依旧提示密码错误。\
97
+这是由于`Gradle`版本与`IDEA`版本兼容性导致的编译参数`-parameters`没生效。\
98
+您需要在`File -> Settings -> Build,Execution,Deployment -> Compiler -> Java Compiler`中的`Javac Options`下的`Additional command line parameters`中添加`-parameters`。
99
+
100
+![gradle_settings](../../.vuepress/public/boot/gradle_settings.png)
101
+添加后`clean`,重新编译。
102
+
103
+`IDEA`推荐使用`2021.3`及以上版本。
104
+:::
105
+
106
+## 前端
107
+::: tip 请确认您已有以下运行环境
108
+1. Node.js 10.x 及以上(vue3 版需要 Node.js 14.x 及以上)
109
+:::
110
+
111
+### 1、运行前端
112
+```bash
113
+# 进入前端项目目录,在终端中运行命令
114
+cd qingzhou-cloud-ui
115
+# cd qingzhou-cloud-ui-vue3
116
+
117
+# 安装依赖
118
+npm install
119
+
120
+# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
121
+# npm install --registry=https://registry.taobao.com
122
+
123
+# 启动服务
124
+npm run dev
125
+```
126
+
127
+浏览器访问 http://localhost:80

+ 8
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/front.md 파일 보기

@@ -0,0 +1,8 @@
1
+---
2
+title: 前端手册
3
+prev: false
4
+# next: ./ops
5
+---
6
+
7
+## 前端手册
8
+由于前端与若依框架的前端没有太大区别,您可以直接参考 [若依前端手册](https://doc.ruoyi.vip/ruoyi-vue/document/qdsc.html)。

+ 252
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/app/ops.md 파일 보기

@@ -0,0 +1,252 @@
1
+---
2
+title: 项目部署
3
+prev: false
4
+# next: ./uplog
5
+---
6
+
7
+## 后端
8
+### 1、打包
9
+* Maven 版
10
+  ```bash
11
+  mvn clean package
12
+  ```
13
+
14
+  ::: tip 默认打 jar 包
15
+  打包后会在每个微服务模块的 target 目录下生成 jar 包文件 qingzhou-*.jar
16
+  :::
17
+
18
+* Gradle 版\
19
+  双击:`Gradle插件/qingzhou-cloud/Tasks/build`下的`clean`和`build`。
20
+  ::: tip 默认打 jar 包
21
+  打包后会在每个微服务模块的 build/libs 目录下生成 jar 包文件 qingzhou-*.jar
22
+  :::
23
+
24
+### 2、运行
25
+```bash
26
+java –jar qingzhou-*.jar
27
+
28
+# 按需运行 jar 包,用到哪个运行哪个
29
+```
30
+
31
+::: tip 支持添加启动参数
32
+```bash
33
+java –jar qingzhou-admin.jar --server.port=8081
34
+
35
+java –jar qingzhou-admin.jar --solon.env=dev
36
+
37
+java –jar qingzhou-admin.jar --nacos.namespace=ceb00317-a8b0-4a9a-a695-2274b7b53b5a
38
+```
39
+详见 [Solon 配置](https://solon.noear.org/article/482)
40
+:::
41
+
42
+### 3、jar包加密
43
+如果您不希望 jar 包被反编译导致泄露源码,您可以对 jar 包进行加密(目前仅支持`Maven`版)。\
44
+加密工具:[ClassFinal](https://gitee.com/lcm742320521/class-final)\
45
+加密只需一步:在每个需要打包的微服务模块添加加密插件(`qingzhou-auth/pom.xml`、`qingzhou-modules/qingzhou-modules-system/pom.xml`等)
46
+
47
+```xml
48
+<!-- pom.xml -->
49
+<build>
50
+  <finalName>${project.artifactId}</finalName>
51
+  <plugins>
52
+    <plugin>
53
+      <groupId>org.noear</groupId>
54
+      <artifactId>solon-maven-plugin</artifactId>
55
+    </plugin>
56
+
57
+    <!-- jar包加密 -->
58
+    <plugin>
59
+      <groupId>com.gitee.lcm742320521</groupId>
60
+      <artifactId>classfinal-maven-plugin</artifactId>
61
+      <version>1.4.0</version>
62
+      <configuration>
63
+        <libjars>qingzhou-*.jar</libjars><!-- jar包lib下要加密jar文件名(可为空,多个用","分割) -->
64
+        <packages>com.ruoyicom.ruoyi</packages><!-- 加密的包名(可为空,多个用","分割。应包含所有需要加密的类的包名) -->
65
+        <cfgfiles>*.yml</cfgfiles><!-- 需要加密的配置文件,一般是resources目录下的yml或properties文件(可为空,多个用","分割) -->
66
+        <password>#</password><!-- 加密密码,如果是#号,则使用无密码模式加密 -->
67
+      </configuration>
68
+      <executions>
69
+        <execution>
70
+          <phase>package</phase>
71
+          <goals>
72
+            <goal>classFinal</goal>
73
+          </goals>
74
+        </execution>
75
+      </executions>
76
+    </plugin>
77
+  </plugins>
78
+</build>
79
+```
80
+添加以上打包加密插件后,正常打包即可(打包方式不变)。打包成功后可在每个微服务模块的 target 目录下看到两个 jar 包:
81
+  * qingzhou-*.jar
82
+  * qingzhou-*-encrypted.jar *加密后的*
83
+
84
+请运行加密后的 jar 包,运行命令为:
85
+```bash
86
+java -javaagent:qingzhou-*-encrypted.jar -jar qingzhou-*-encrypted.jar
87
+```
88
+
89
+
90
+## 前端
91
+### 1、打包
92
+```bash
93
+npm run build:prod
94
+```
95
+
96
+::: tip 提示
97
+打包成功之后,会在根目录生成 dist 文件夹,通常是 .js 、.css、index.html 等静态文件。\
98
+将 dist 文件夹发布到你的 Nginx 或者静态服务器即可,其中的 index.html 是后台服务的入口页面。
99
+:::
100
+
101
+### 2、Nginx 配置参考(v1.x)
102
+~~~
103
+worker_processes  1;
104
+
105
+events {
106
+  worker_connections  1024;
107
+}
108
+
109
+http {
110
+  include            mime.types;
111
+  default_type       application/octet-stream;
112
+  sendfile           on;
113
+  keepalive_timeout  65;
114
+
115
+  server {
116
+    listen       80;
117
+    server_name  localhost;
118
+    charset      utf-8;
119
+
120
+    location / {
121
+      root  /home/qingzhou/ui;
122
+      try_files $uri $uri/ /index.html;
123
+      index  index.html index.htm;
124
+    }
125
+
126
+    location /prod-api/ {
127
+      proxy_set_header Host $http_host;
128
+      proxy_set_header X-Real-IP $remote_addr;
129
+      proxy_set_header REMOTE-HOST $remote_addr;
130
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
131
+      proxy_pass http://localhost:8080/;
132
+    }
133
+
134
+    error_page  500 502 503 504  /50x.html;
135
+    location = /50x.html {
136
+      root  html;
137
+    }
138
+  }
139
+}
140
+~~~
141
+
142
+### 3、Nginx 配置参考(v2.x)
143
+::: warning 注意
144
+`v2.x`版本使用 Nginx 进行请求分发。
145
+
146
+配置文件:qingzhou-cloud/sql/nginx.conf
147
+:::
148
+
149
+~~~
150
+worker_processes  1;
151
+
152
+events {
153
+  worker_connections  1024;
154
+}
155
+
156
+http {
157
+  include            mime.types;
158
+  default_type       application/octet-stream;
159
+  sendfile           on;
160
+  keepalive_timeout  65;
161
+
162
+  server {
163
+    listen       80;
164
+    server_name  localhost;
165
+    charset      utf-8;
166
+
167
+    location / {
168
+      root  /home/qingzhou/ui;
169
+      try_files $uri $uri/ /index.html;
170
+      index  index.html index.htm;
171
+    }
172
+
173
+    location /prod-api/auth/ {
174
+      proxy_set_header Host $http_host;
175
+      proxy_set_header X-Real-IP $remote_addr;
176
+      proxy_set_header REMOTE-HOST $remote_addr;
177
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
178
+      proxy_pass http://qingzhou-auth/;
179
+    }
180
+
181
+    location /prod-api/system/ {
182
+      proxy_set_header Host $http_host;
183
+      proxy_set_header X-Real-IP $remote_addr;
184
+      proxy_set_header REMOTE-HOST $remote_addr;
185
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
186
+      proxy_pass http://qingzhou-system/;
187
+    }
188
+
189
+    location /prod-api/file/ {
190
+      proxy_set_header Host $http_host;
191
+      proxy_set_header X-Real-IP $remote_addr;
192
+      proxy_set_header REMOTE-HOST $remote_addr;
193
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
194
+      proxy_pass http://qingzhou-file/;
195
+    }
196
+
197
+    location /prod-api/gen/ {
198
+      proxy_set_header Host $http_host;
199
+      proxy_set_header X-Real-IP $remote_addr;
200
+      proxy_set_header REMOTE-HOST $remote_addr;
201
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
202
+      proxy_pass http://qingzhou-gen/;
203
+    }
204
+
205
+    location /prod-api/schedule/ {
206
+      proxy_set_header Host $http_host;
207
+      proxy_set_header X-Real-IP $remote_addr;
208
+      proxy_set_header REMOTE-HOST $remote_addr;
209
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
210
+      proxy_pass http://qingzhou-schedule/;
211
+    }
212
+
213
+    location /prod-api/demo/ {
214
+      proxy_set_header Host $http_host;
215
+      proxy_set_header X-Real-IP $remote_addr;
216
+      proxy_set_header REMOTE-HOST $remote_addr;
217
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
218
+      proxy_pass http://qingzhou-demo/;
219
+    }
220
+
221
+    error_page  500 502 503 504  /50x.html;
222
+    location = /50x.html {
223
+      root  html;
224
+    }
225
+  }
226
+
227
+  upstream qingzhou-auth {
228
+    server localhost:8101;
229
+  }
230
+
231
+  upstream qingzhou-system {
232
+    server localhost:8102;
233
+  }
234
+
235
+  upstream qingzhou-file {
236
+    server localhost:8091;
237
+  }
238
+
239
+  upstream qingzhou-gen {
240
+    server localhost:8092;
241
+  }
242
+
243
+  upstream qingzhou-schedule {
244
+    server localhost:8093;
245
+  }
246
+
247
+  upstream qingzhou-demo {
248
+    server localhost:8103;
249
+  }
250
+
251
+}
252
+~~~

+ 160
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/adumbrate.md 파일 보기

@@ -0,0 +1,160 @@
1
+---
2
+title: 简介(单体版)
3
+prev: false
4
+# next: ./before
5
+---
6
+
7
+<el-alert
8
+  title="当前为 RuoYi-Solon v2.1.0+ 版本的文档"
9
+  description="更低版本的文档请前往每个版本下的 docs 目录中查看"
10
+  type="warning"
11
+  effect="dark"
12
+  show-icon>
13
+</el-alert>
14
+
15
+### 简介
16
+[RuoYi-Solon](https://gitee.com/opensolon/ruoyi-solon) 是一款基于 Solon + Vue 的前后端分离的快速开发脚手架,属于若依系统的 Solon 版本。
17
+
18
+### 内置功能
19
+* 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
20
+* 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
21
+* 岗位管理:配置系统用户所属担任职务。
22
+* 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
23
+* 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
24
+* 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
25
+* 参数管理:对系统动态配置常用参数。
26
+* 通知公告:系统通知公告信息发布维护。
27
+* 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
28
+* 登录日志:系统登录日志记录查询包含登录异常。
29
+* 在线构建:拖动表单元素生成相应的HTML代码。
30
+* 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载。
31
+* 定时任务:任务调度及调度日志记录。
32
+* 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
33
+* 系统接口:根据业务代码自动生成相关的api接口文档。
34
+* 在线用户:当前系统中活跃用户状态监控。
35
+* 缓存监控:对系统的缓存信息查询。
36
+
37
+### 技术选型
38
+- 后端
39
+  - Solon
40
+  - HikariCP
41
+  - Mybatis-Flex
42
+  - Redis
43
+  - Sa-Token
44
+  - Hutool
45
+  - ···
46
+- 前端
47
+  - Vue
48
+  - Vue-Router
49
+  - Vuex / Pinia
50
+  - Element-UI / Element-Plus
51
+  - Axios
52
+  - Js-Cookie
53
+  - ···
54
+
55
+### 版本分支
56
+* 默认`master`分支,后端采用`Maven`作为构建工具。
57
+* `gradle`分支,后端采用`Gradle`作为构建工具。
58
+> 不建议直接`clone`分支代码,推荐下载标签中的最新版本。
59
+
60
+### 项目结构
61
+~~~
62
+ruoyi-solon(Maven版)
63
+├── docs                                  // 文档目录
64
+│   ├── ruoyi-docs                        // 项目配套文档
65
+├── ruoyi-admin                           // 接口模块 [8080]
66
+├── ruoyi-common                          // 通用模块
67
+├── ruoyi-framework                       // 框架核心
68
+├── ruoyi-gen                             // 代码生成
69
+├── ruoyi-schedule                        // 任务调度
70
+├── ruoyi-solon-ui                        // 前端框架 [80](Vue2)
71
+├── ruoyi-solon-ui-vue3                   // 前端框架 [80](Vue3)
72
+├── ruoyi-system                          // 系统模块
73
+├── sql                                   // sql目录
74
+│   ├── ry-vue.sql                        // 项目配套数据库文件
75
+├── .gitignore                            // git 忽略项
76
+├── LICENSE                               // 许可证
77
+├── pom.xml                               // 公共依赖
78
+├── README.md                             // README说明
79
+~~~
80
+~~~
81
+ruoyi-solon(Gradle版)
82
+├── gradle                                // gradle包装器
83
+├── ruoyi-admin                           // 接口模块 [8080]
84
+├── ruoyi-common                          // 通用模块
85
+├── ruoyi-framework                       // 框架核心
86
+├── ruoyi-gen                             // 代码生成
87
+├── ruoyi-schedule                        // 任务调度
88
+├── ruoyi-system                          // 系统模块
89
+├── sql                                   // sql目录
90
+│   ├── ry-vue.sql                        // 项目配套数据库文件
91
+├── .gitignore                            // git 忽略项
92
+├── build.gradle                          // gradle构建脚本
93
+├── gradlew                               // Linux脚本
94
+├── gradlew.bat                           // Windows脚本
95
+├── LICENSE                               // 许可证
96
+├── README.md                             // README说明
97
+├── settings.gradle                       // gradle项目配置
98
+~~~
99
+~~~
100
+ruoyi-solon-ui 前端项目(Vue2)
101
+├── build                                 // 构建相关
102
+├── public                                // 公共文件
103
+│   ├── favicon.ico                       // favicon图标
104
+│   └── index.html                        // html模板
105
+│   └── robots.txt                        // 反爬虫
106
+├── src                                   // 源代码
107
+│   ├── api                               // 所有请求(后台接口)
108
+│   ├── assets                            // 图片 样式等静态资源
109
+│   ├── components                        // 全局公用组件
110
+│   ├── directive                         // 自定义指令
111
+│   ├── layout                            // 布局
112
+│   ├── plugins                           // 插件(功能增强:比如全局方法挂载、全局组件挂载等)
113
+│   ├── router                            // 路由
114
+│   ├── store                             // Vuex
115
+│   ├── utils                             // 全局公用方法
116
+│   ├── views                             // 所有页面
117
+│   ├── App.vue                           // 入口页面
118
+│   ├── main.js                           // 入口 初始化Vue
119
+├── .editorconfig                         // EditorConfig插件配置
120
+├── .env.development                      // 开发环境配置
121
+├── .env.production                       // 生产环境配置
122
+├── .eslintignore                         // 忽略语法检查
123
+├── .eslintrc.js                          // eslint 配置项
124
+├── .gitignore                            // git 忽略项
125
+├── babel.config.js                       // babel.config.js
126
+├── package-lock.json                     // 包版本锁定
127
+├── package.json                          // 包管理
128
+├── README.md                             // README说明
129
+└── vue.config.js                         // vue.config.js
130
+~~~
131
+~~~
132
+ruoyi-solon-ui-vue3 前端项目(Vue3)
133
+├── public                                // 公共文件
134
+│   ├── favicon.ico                       // favicon图标
135
+├── src                                   // 源代码
136
+│   ├── api                               // 所有请求(后台接口)
137
+│   ├── assets                            // 图片 样式等静态资源
138
+│   ├── components                        // 全局公用组件
139
+│   ├── directive                         // 自定义指令
140
+│   ├── layout                            // 布局
141
+│   ├── plugins                           // 插件(功能增强:比如全局方法挂载、全局组件挂载等)
142
+│   ├── router                            // 路由
143
+│   ├── store                             // Pinia
144
+│   ├── utils                             // 全局公用方法
145
+│   ├── views                             // 所有页面
146
+│   ├── App.vue                           // 入口页面
147
+│   ├── main.js                           // 入口 初始化Vue
148
+├── .editorconfig                         // EditorConfig插件配置
149
+├── .env.development                      // 开发环境配置
150
+├── .env.production                       // 生产环境配置
151
+├── .eslintignore                         // 忽略语法检查
152
+├── .eslintrc-auto-import.json            // 忽略自动导入的语法检查
153
+├── .eslintrc.js                          // eslint 配置项
154
+├── .gitignore                            // git 忽略项
155
+├── index.html                            // html模板
156
+├── package-lock.json                     // 包版本锁定
157
+├── package.json                          // 包管理
158
+├── README.md                             // README说明
159
+└── vite.config.js                        // vite.config.js
160
+~~~

+ 574
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/backend.md 파일 보기

@@ -0,0 +1,574 @@
1
+---
2
+title: 后端手册
3
+prev: false
4
+# next: ./front
5
+---
6
+
7
+::: danger 注意
8
+请牢记您是在写 Solon 项目,而不是 SpringBoot 项目。
9
+:::
10
+
11
+## 常用注解
12
+注解与 SpringBoot 的注解还是有区别的,详见 [常用注解比较](https://solon.noear.org/article/compare-springboot)。  
13
+常用注解替换:
14
+|  SpringBoot  |  Solon  |
15
+|  :--:  |  :--:  |
16
+|  @Autowired  |  @Inject  |
17
+|  @RestController + @RequestMapping("url")  |  @Controller + @Mapping("url")  |
18
+|  @GetMapping("url")等等  |  @Get等等 + @Mapping("url")  |
19
+|  @Service  |  @Component  |
20
+|  @Value("${key}")  |  @Inject("${key}")  |
21
+
22
+## 统一返回结果
23
+项目中的请求(除了 Admin监控 和 接口文档 外),其返回结果都被处理为`org.noear.solon.core.handle.Result<T>`返回给前端。
24
+```json
25
+// 返回结果示例
26
+{
27
+  code: 200,
28
+  description: "操作成功",
29
+  data: null
30
+}
31
+```
32
+详见 全局路由拦截器`com.ruoyi.framework.interceptor.GlobalRouterInterceptor`
33
+
34
+## 异常处理
35
+所有的异常统一由`全局过滤器`捕获,并且也会渲染为`Result<T>`返回给前端  
36
+如果您想手动抛出异常,请参照:
37
+```java {2}
38
+if(!StrUtil.isAllNotEmpty(username, password)) {
39
+  throw new ServiceException("账号/密码必须填写");
40
+}
41
+```
42
+详见 全局过滤器`com.ruoyi.framework.filter.GlobalFilter`
43
+
44
+## 分页实现
45
+* 前端采用`ElementUI`的分页组件 Pagination。
46
+* 后端采用`Mybatis-Flex`的分页查询,另外集成了轻量级分页插件 [PageHelper](https://github.com/pagehelper/Mybatis-PageHelper)(两种分页方式二选一即可)。
47
+  * `Mybatis-Flex`的分页查询示例
48
+  ```java {3,10}
49
+  @Controller
50
+  @Mapping("system/config")
51
+  public class SysConfigController extends BaseController {
52
+
53
+    @Get
54
+    @Mapping("list")
55
+    public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
56
+      QueryWrapper qw = QueryWrapper.create();
57
+      qw.and(SysConfig::getConfigName).like(sysConfig.getConfigName());
58
+      Page<SysConfig> result = sysConfigService.page(page, qw);
59
+      return getPageData(result);
60
+    }
61
+
62
+  }
63
+  ```
64
+  * `PageHelper`分页插件示例
65
+  ```java {3,8}
66
+  @Controller
67
+  @Mapping("tool/gen")
68
+  public class GenTableController extends BaseController {
69
+
70
+    @Get
71
+    @Mapping("tables")
72
+    public PageData tables(Page<GenTable> page, GenTable genTable) {
73
+      startPage(page);
74
+      List<GenTable> list = genTableService.tables(genTable);
75
+      return getPageData(list);
76
+    }
77
+
78
+  }
79
+  ```
80
+  ::: warning 注意
81
+  1、使用分页时,请将控制器`xxxController`继承控制器基类`BaseController`。  
82
+  2、`Pagehelper`只对`XML`的`SQL`分页有效,也就是说需要自己手写`SQL`,不能针对`flex`提供的快捷方法分页,比如`service.list()`。
83
+  :::
84
+
85
+## 数据导出
86
+::: warning 注意
87
+数据导出的底层使用的都是`Apache POI`来操作`Office`。  
88
+如果您不需要`poi`功能,可以将相关依赖和代码注释掉,这样打包的体积能减小 17~28 MB。
89
+:::
90
+后端使用`easy-poi`实现实体类数据的导出。在需要被导出的实体类属性添加`@Excel`注解即可。
91
+```java {6,11,15,19}
92
+@Table(value = "sys_config")
93
+public class SysConfig extends BaseEntity {
94
+  private static final long serialVersionUID = 1L;
95
+
96
+  /** 参数主键 */
97
+  @Excel(name = "参数主键")
98
+  @Id
99
+  private Long configId;
100
+
101
+  /** 参数名称 */
102
+  @Excel(name = "参数名称")
103
+  private String configName;
104
+
105
+  /** 系统内置(Y是 N否) */
106
+  @Excel(name = "系统内置", replace = { "是_Y", "否_N" })
107
+  private String configType;
108
+
109
+  /** 配置时间 */
110
+  @Excel(name = "配置时间", exportFormat = "yyyy年MM月dd日")
111
+  private Date configTime;
112
+
113
+}
114
+```
115
+::: tip 说明
116
+* `name`属性代表列名
117
+* `replace`属性用于值的替换:`configType`的值为`Y`或`N`,导出后将转换为`是`或`否`
118
+* `exportFormat`属性代表导出的时间格式
119
+* 如果需要忽略某一字段的导出,可以删除该字段上的`@Excel`注解,或者在该字段上添加`@ExcelIgnore`注解
120
+* 更多注解属性的使用,请参考`easy-poi`
121
+:::
122
+
123
+## 上传下载
124
+* 上传
125
+  * 前端采用`ElementUI`的上传组件 Upload。
126
+  * 后端采用本地文件上传。
127
+  ::: warning 注意
128
+  * 文件上传针对文件类型和文件大小在前端和后端都做了限制。
129
+    * 后端文件上传配置示例(app-xxx.yml)
130
+    ```yaml {8,10}
131
+    ruoyi:
132
+      file:
133
+        # 允许上传的文件大小(单位:MB,设为-1不限制)
134
+        maxSize: 2
135
+        # 允许上传的文件类型
136
+        fileType: [jpg, jpeg, png, doc, docx, xls, xlsx, ppt, txt, pdf, zip]
137
+        # 本地保存路径
138
+        savePath: C:\Users\ruoyi\Desktop
139
+        # 本地文件请求路径前缀
140
+        requestPrefix: http://localhost:90/ruoyi-file
141
+    ```
142
+  * 您需要搭配`代理服务器`来实现本地文件的访问(例如 Nginx)。
143
+    * Nginx配置示例
144
+    ``` {6}
145
+    server {
146
+      listen       90;
147
+      server_name  localhost;
148
+
149
+      location /ruoyi-file {
150
+        alias   C:/Users/ruoyi/Desktop/;
151
+        autoindex on;
152
+      }
153
+    }
154
+    ```
155
+  :::
156
+  * 文件上传大小受以下几处限制:
157
+    * 前端上传组件
158
+    * 后端Web服务器的请求体大小:server.request.maxFileSize: 2mb
159
+    * 后端文件上传配置:ruoyi.file.maxSize: 2
160
+    * 前端部署到服务器后(例如 Nginx),Nginx限制的请求体大小
161
+* 下载  
162
+数据导出即采用了文件下载,您可以参照数据导出的实现。
163
+
164
+## 参数验证
165
+数据校验能力,详见 [solon-security-validation](https://solon.noear.org/article/225)。
166
+* 控制器基类`BaseController`中已加`@Valid`注解(请将控制器`xxxController`继承控制器基类`BaseController`)
167
+  ```java
168
+  @Valid
169
+  public class BaseController {
170
+  }
171
+  ```
172
+* 在控制器接口的形参前加上`@Validated`注解
173
+  ```java
174
+  @Post
175
+  @Mapping
176
+  public Result add(@Body @Validated SysConfig sysConfig) {
177
+    return toResult(sysConfigService.add(sysConfig));
178
+  }
179
+  ```
180
+* 在实体类的属性上添加相应的校验注解(例如:`@NotBlank(message = "参数名称不能为空")`)
181
+  ```java {5-6}
182
+  @Table(value = "sys_config")
183
+  public class SysConfig extends BaseEntity {
184
+    private static final long serialVersionUID = 1L;
185
+
186
+    @NotBlank(message = "参数名称不能为空")
187
+    @Length(max = 100, message = "参数名称不能超过100个字符")
188
+    private String configName;
189
+  }
190
+  ```
191
+
192
+## 权限注解
193
+权限采用了 [solon-security-auth](https://solon.noear.org/article/59) & [Sa-Token](https://sa-token.cc/doc.html#/use/jur-auth) 的实现方式。
194
+
195
+`solon-security-auth`认证一览:
196
+|  方法  |  描述  |  是否用到  |
197
+|  :--:  |  :--:  |  :--:  |
198
+|  verifyIp()  |  验证客户端IP是否有权访问  |  :heavy_check_mark:  |
199
+|  verifyLogined()  |  验证用户是否登录  |  :heavy_check_mark:  |
200
+|  verifyPath()  |  验证用户是否可访问该路径  |  :x:  |
201
+|  verifyPermissions()  |  验证用户是否具有某字符权限,例如`system:config:list`  |  :heavy_check_mark:  |
202
+|  verifyRoles()  |  验证用户是否具有某角色  |  :x:  |
203
+
204
+* 在`SecurityConfig`中定义了鉴权规则,在`AuthProcessorImpl`中定义了鉴权的判定逻辑
205
+  * 首先,所有的请求,校验客户端IP是否在黑名单中(`verifyIp()`)。  
206
+    被拉黑的IP将无法访问任何后端接口。您可以在配置文件中配置IP黑名单(app-xxx.yml)。
207
+    ```yaml
208
+    ruoyi:
209
+      security:
210
+        ips:
211
+          - 1.1.1.1
212
+    ```
213
+  * 其次,所有的请求,校验登录的用户是否有(字符)权限调用接口(`verifyPermissions()`)。
214
+    ::: warning 注意
215
+    在`verifyPermissions()`方法校验(字符)权限前,先会去校验用户是否登录`verifyLogined()`。  
216
+    只有验证用户已经登录了,才会去校验用户是否有(字符)权限。  
217
+    如果您希望某个接口无需登录即可访问,需要配置放行白名单(app-xxx.yml):
218
+    ```xml {3}
219
+    ruoyi:
220
+      security:
221
+        whites:
222
+          - /captcha
223
+          - /login
224
+          - /logout
225
+          ...
226
+    ```
227
+    :::
228
+* 关于字符权限  
229
+  字符权限形如`system:config:list`,由后台接口上的`@AuthPermissions`注解和菜单中的`perms`权限字符字段共同实现。
230
+  * 带有`@AuthPermissions`注解的接口,说明登录用户需要有此字符权限才能调用该接口
231
+    ```java {1}
232
+    @AuthPermissions("system:config:list")
233
+    @Get
234
+    @Mapping("list")
235
+    public PageData list() {
236
+      ...
237
+    }
238
+    ```
239
+  * 想让某用户可访问上述接口,首先需要在前端创建菜单或按钮并将上述权限字符配置到`perms`权限字符字段  
240
+    而后在角色管理中,给角色A添加该菜单或按钮的权限,最后将角色A赋予此用户即可  
241
+    此用户登录后将只能看到他所拥有的角色所能看到的菜单和按钮
242
+
243
+    > 用户登录成功后,已将该用户的所有已有权限放入了登录信息中。  
244
+      由`Sa-Token`的`StpUtil.hasPermission()`方法判定登录用户是否具有接口需要的字符权限。
245
+
246
+::: warning 注意
247
+这里的权限指的是用户登录前端后所能看到的菜单和菜单下的操作按钮  
248
+下方的数据权限指的是用户所能查询到的数据范围,比如只能查看自己所在部门的数据
249
+:::
250
+
251
+## 数据权限
252
+在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。  
253
+数据权限是通过部门来实现的。
254
+* 在角色管理中设置数据权限,目前支持以下几种:
255
+  * 全部数据权限
256
+  * 本部门数据权限
257
+  * 本部门及以下数据权限
258
+  * 仅本人数据权限
259
+  * 自定义数据权限
260
+* 在需要数据权限控制的控制器接口上添加`@RyDataScope`注解
261
+  ```java {1}
262
+  @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
263
+  @AuthPermissions("system:user:list")
264
+  @Get
265
+  @Mapping("list")
266
+  public PageData list(Page<SysUser> page, SysUser sysUser) {
267
+    startPage(page);
268
+    List<SysUser> list = sysUserService.selectUserList(sysUser);
269
+    return getPageData(list);
270
+  }
271
+  ```
272
+::: tip 提示
273
+* 常量`UserConstant.DATA_SCOPE_ALIAS_DEPT`和`UserConstant.DATA_SCOPE_ALIAS_USER`表示表的别名
274
+* 实体类需要继承基类`BaseEntity`才会处理,处理后的拼接sql语句将存放到`BaseEntity`的`dataScopeSql`字段,然后在`xml`中通过`${参数名.dataScopeSql}`拼接sql语句
275
+* 实现逻辑参考`DataScopeAspect`
276
+:::
277
+
278
+## 动态数据源
279
+在实际开发中,经常可能遇到在一个应用中可能需要访问多个数据库的情况,在项目中使用注解来完成此项功能。
280
+* 首先配置文件中已经配置了一个多级数据源
281
+  ```yaml {5,11}
282
+  # mybatis-flex 数据源及 mybatis配置
283
+  mybatis-flex:
284
+    # 动态数据源
285
+    datasource:
286
+      master:
287
+        type: com.zaxxer.hikari.HikariDataSource
288
+        driverClassName: com.mysql.cj.jdbc.Driver
289
+        jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
290
+        username: root
291
+        password:
292
+      slave_1:
293
+        type: com.zaxxer.hikari.HikariDataSource
294
+        driverClassName: com.mysql.cj.jdbc.Driver
295
+        jdbcUrl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
296
+        username: root
297
+        password:
298
+  ```
299
+* 在`Controller`控制器层中通过`@UseDataSource`注解指定二级数据源
300
+  ```java {2}
301
+  @AuthPermissions("system:config:list")
302
+  @UseDataSource(DataSourceConstant.DATA_SOURCE_SLAVE_1)
303
+  @Get
304
+  @Mapping("list")
305
+  public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
306
+    ...
307
+  }
308
+  ```
309
+
310
+## 限流
311
+使用自定义注解`@RyRateLimit`实现。
312
+* 全局限流:针对于所有的请求(将注解加在全局过滤器的`doIntercept`方法上)
313
+  ```java {3}
314
+  @Component
315
+  public class GlobalRouterInterceptor implements RouterInterceptor {
316
+    @RyRateLimit()  // 全局限流
317
+    @Override
318
+    public void doIntercept(Context ctx, Handler mainHandler, RouterInterceptorChain chain) throws Throwable {
319
+      ...
320
+    }
321
+  }
322
+  ```
323
+* 单接口限流:针对与单个接口(将注解加在控制器上)
324
+  ```java {1}
325
+  @RyRateLimit(count = 10, type = RateLimitType.IP)
326
+  @Get
327
+  @Mapping
328
+  public Result<Map<String, Object>> captcha() {
329
+    return captchaService.getCaptcha();
330
+  }
331
+  ```
332
+::: tip 限流注解属性说明
333
+* `int count() default 100;` 单位时间内允许请求的次数
334
+* `int time() default 60;` 时间,单位:秒
335
+* `RateLimitType type() default RateLimitType.IP;` 限流类型(枚举):默认、token、ip
336
+* 以上默认配置的效果:从第一次请求开始的60秒内,同一个ip,只能请求100次。60秒内重复请求不会重置限流时间。60秒过后,下一次请求重新计数
337
+:::
338
+
339
+## 防重复提交
340
+使用注解`@NoRepeatSubmit`实现。在控制器上添加注解即可。
341
+```java {1}
342
+@NoRepeatSubmit(value = HttpPart.body, message = "请勿重复提交")
343
+@AuthPermissions("system:config:add")
344
+@Post
345
+@Mapping
346
+public Result<Void> add(@Body @Validated SysConfig sysConfig) {
347
+  return toResult(sysConfigService.add(sysConfig));
348
+}
349
+```
350
+::: tip 防重复提交注解属性说明
351
+* `value` 是否是重复提交的判断标准(3种:请求头、请求参数、请求体)
352
+* `seconds` 间隔时间,单位:秒
353
+:::
354
+
355
+## 多租户改造
356
+采用指定租户列的方案,基于 [MyBatis-Flex 多租户](https://mybatis-flex.com/zh/core/multi-tenancy.html)。
357
+* 全局配置多租户字段,修改配置文件(app-xxx.yml)
358
+  ```yaml {8-9}
359
+  # mybatis-flex 数据源及 mybatis配置
360
+  mybatis-flex:
361
+    # Mybatis-Flex 的全局配置
362
+    global-config:
363
+      printBanner: true
364
+      # 逻辑删除字段
365
+      logicDeleteColumn: del_flag
366
+      # 租户字段
367
+      tenantColumn: tenant_id
368
+      # 主键配置
369
+      keyConfig:
370
+        # Auto自增
371
+        keyType: Auto
372
+        # value:
373
+  ```
374
+* 在`MybatisFlexConfig`中配置`TenantFactory`
375
+  * `TenantFactory`是用于生产租户id的。实际开发中一般是指定某一字段作为租户的id,所以此处应返回当前租户的id
376
+  * 增删改查的操作将拼接上此处返回的租户id
377
+  ```java
378
+  @Configuration
379
+  public class MybatisFlexConfig {
380
+    ...
381
+    private void globalConfig() {
382
+      ...
383
+      TenantManager.setTenantFactory(new TenantFactory() {
384
+        @Override
385
+        public Object[] getTenantIds() {
386
+          // 通过这里返回当前租户 ID
387
+          return new Object[]{ SecurityUtil.getLoginUser().getTenantId() };
388
+        }
389
+      });
390
+    }
391
+    ...
392
+  }
393
+  ```
394
+::: warning 注意
395
+* 此处在登录用户信息`LoginUser`里设置了租户字段`tenantId`,用户登录的时候给字段赋值租户id
396
+* 这样,使用`IService`和`BaseMapper`提供的增删改查方法时,会在 SQL 中拼接上租户id条件
397
+  * 增:`xxxService.save()`、`xxxMapper.insert()`等方法会自动给租户字段`tenantId`赋值
398
+    ```sql
399
+    INSERT INTO 表名(..., tenant_id, ...) VALUES (..., ?, ...)
400
+    ```
401
+  * 改:`xxxService.update()`、`xxxMapper.update()`等方法会添加租户条件
402
+    ```sql
403
+    UPDATE 表名 SET ... WHERE id = ? AND del_flag = 0 AND tenant_id = ?
404
+    ```
405
+  * 删:`xxxService.remove()`、`xxxMapper.delete()`等方法会添加租户条件
406
+    ```sql
407
+    UPDATE 表名 SET del_flag = 1 WHERE id = ? AND del_flag = 0 AND tenant_id = ?
408
+    ```
409
+  * 查:`xxxService.list()`、`xxxService.page()`、`xxxService.getById()`、`xxxService.count()`、`xxxMapper.select...()`等方法会添加租户条件
410
+    ```sql
411
+    SELECT ... FROM 表名 WHERE tenant_id = ? AND del_flag = 0
412
+    ```
413
+* `TenantFactory`中要求返回一个数组,主要是针对多级租户的情况:  
414
+  假设有如下三级租户:`一级租户 -> 二级租户 -> 三级租户`,二级租户中存的是其所属一级租户的租户id,三级租户存的是其所属二级租户的租户id。  
415
+  那么当一级租户想查询其所拥有的所有三级租户时,查询结果将是空。因为三级租户并没有存一级租户的租户id。  
416
+  因此要想实现,需要先查询一级租户所拥有的所有二级租户的租户id,再用所有二级租户的租户id去查询所有三级租户。  
417
+  所以此时`TenantFactory`返回的应该是`所有二级租户的租户id组成的数组`。此时的 SQL 将变为:
418
+  ```sql
419
+  SELECT ... FROM 表名 WHERE tenant_id IN (?, ?) AND del_flag = 0
420
+  ```
421
+* 如果您需要忽略租户条件,使用`TenantManager.withoutTenantCondition()`:
422
+  ```java
423
+  TenantManager.withoutTenantCondition(() -> xxxService.list(QueryWrapper.create()));
424
+
425
+  TenantManager.withoutTenantCondition(() -> xxxMapper.selectListByQuery(QueryWrapper.create()));
426
+  ```
427
+:::
428
+::: danger 注意
429
+:exclamation: 以下情况并不会自动拼接租户条件:
430
+  * 您在`xxxMapper.xml`中手写的 SQL
431
+  * 您在`xxxMapper`中使用 MyBatis 原生功能手写的 SQL(使用`@Select`、`@Insert`、`@Delete`、`@Update`等注解写的 SQL)
432
+:::
433
+
434
+## 数据脱敏 & 字段权限
435
+参见 [MyBatis-Flex 数据脱敏](https://mybatis-flex.com/zh/core/mask.html),[MyBatis-Flex 字段权限](https://mybatis-flex.com/zh/core/columns-permission.html)
436
+
437
+## 定时任务 & 异步
438
+定时任务使用`quartz`实现。
439
+* 主启动类添加`@EnableScheduling`和`@EnableAsync`注解
440
+* 具体写法参照`com.ruoyi.schedule.task.RyTask`
441
+
442
+定时任务支持持久化:您需要在`ruoyi-admin/src/main/resources/quartz.properties`中配置数据源。
443
+> 注意将`quartz.properties`和`app-dev.yml`中配置为同一个数据库。  
444
+程序(后端)启动时会将`RyTask`中的定时任务写入数据库。  
445
+您可以通过定时任务管理页面对任务进行暂停、启动、删除等操作。
446
+::: warning 注意
447
+* 删除操作仅针对当次启动有效。下次程序(后端)启动时会重新将所有定时任务写入数据库
448
+* 暂停、启动永久生效
449
+* 如果您更改了`cron表达式`并重启,发现不生效,记得清空`quartz`相关的表(以`qrtz_`开头)
450
+:::
451
+
452
+使用异步:注入`RyTask`并调用其中的异步方法即可。
453
+
454
+## 代码生成
455
+提供了基础的增删查改代码生成功能。
456
+* 代码生成配置
457
+  ```yaml
458
+  ruoyi:
459
+    gen:
460
+      # 作者
461
+      author: ruoyi
462
+      # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
463
+      packageName: com.ruoyi.system
464
+      # 自动去除表前缀,默认是false
465
+      autoRemovePre: false
466
+      # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
467
+      tablePrefix: demo_
468
+      # 忽略的表前缀(不会查询这些前缀的表)
469
+      ignoreTablePrefix: [qrtz_, gen_, sys_]
470
+  ```
471
+* 登录系统(系统工具 -> 代码生成 -> 导入对应表)
472
+* 代码生成列表中找到需要的表(可预览、编辑、同步、删除生成配置)
473
+* 点击生成代码会得到一个`ruoyi.zip`压缩文件,按照包内目录结构复制到自己的项目中即可
474
+
475
+## 系统接口文档
476
+使用`knife4j`实现。
477
+* 接口文档配置(app-xxx.yml)
478
+  ```yaml
479
+  knife4j:
480
+    # 开启增强配置
481
+    enable: true
482
+    # 开启生产环境屏蔽
483
+    production: true
484
+    # 签权
485
+    basic:
486
+      enable: true
487
+      username: admin
488
+      password: 123456
489
+    # 前端UI的个性化配置
490
+    setting:
491
+      enableVersion: true
492
+      enableOpenApi: false
493
+      enableFooter: false
494
+  ```
495
+* 构建文档配置(app-xxx.yml)
496
+  ```yaml
497
+  solon:
498
+    # 接口文档
499
+    docs:
500
+      routes:
501
+        - id: openapi
502
+          groupName: 系统接口
503
+          info:
504
+            title: 接口文档
505
+            description: 在线API文档
506
+  #          termsOfService: https://gitee.com/noear/solon
507
+            contact:
508
+              name: ruoyi
509
+            version: 1.0
510
+          schemes:
511
+            - HTTP
512
+            - HTTPS
513
+          globalResponseInData: true
514
+          globalResult: org.noear.solon.core.handle.Result
515
+          apis:
516
+            - basePackage: com.ruoyi.web.controller
517
+  ```
518
+* 给接口添加注解
519
+  ```java {1,6}
520
+  @Api("系统参数配置")
521
+  @Controller
522
+  @Mapping("system/config")
523
+  public class SysConfigController extends BaseController {
524
+
525
+    @ApiOperation("列表查询")
526
+    @Get
527
+    @Mapping("list")
528
+    public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
529
+      QueryWrapper qw = getQW(sysConfig);
530
+      Page<SysConfig> result = sysConfigService.page(page, qw);
531
+      return getPageData(result);
532
+    }
533
+
534
+  }
535
+  ```
536
+* 登录系统(系统工具 -> 系统接口),使用接口文档配置中的签权的账号密码登录(knife4j.basic.username/password)
537
+
538
+## 系统监控
539
+* 主启动类添加`@EnableAdminServer`和`@EnableAdminClient`注解
540
+* 监控配置(app-xxx.yml)
541
+  ```yaml
542
+  solon:
543
+    # 监控服务端配置
544
+    admin:
545
+      server:
546
+        # 心跳速率,单位:毫秒
547
+        heartbeatInterval: 10000
548
+        # 客户端监控周期,单位:毫秒
549
+        clientMonitorPeriod: 5000
550
+        # 连接超时,单位:毫秒
551
+        connectTimeout: 5000
552
+        # 读取超时,单位:毫秒
553
+        readTimeout: 5000
554
+        # 界面路径(自定义时要以'/'结尾)
555
+        uiPath: /solon-admin/
556
+        # 基础签权(可以多个)
557
+        basicAuth:
558
+          admin: 123456
559
+    # 监控客户端配置
560
+    client:
561
+      # 令牌:监视接口的安全控制
562
+      token: 3C41D632-A070-060C-40D2-6D84B3C07094
563
+      # 连接超时,单位:毫秒
564
+      connectTimeout: 5000
565
+      # 读取超时,单位:毫秒
566
+      readTimeout: 5000
567
+      # 是否向服务端发送敏感信息,如环境变量等
568
+      showSecretInformation: false
569
+    # 监控项配置
570
+    health:
571
+      # 可选: *、disk、cpu、jvm、memory、os、qps(多个用,分隔)
572
+      detector: "*"
573
+  ```
574
+* 登录系统(系统工具 -> Admin控制台),使用监控配置中的基础签权的账号密码登录(solon.admin.server.basicAuth)

+ 97
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/before.md 파일 보기

@@ -0,0 +1,97 @@
1
+---
2
+title: 项目运行
3
+prev: false
4
+# next: ./backend
5
+---
6
+
7
+## 后端
8
+::: tip 请确认您已有以下运行环境
9
+1. JDK 1.8 及以上
10
+2. Maven 版需要安装 Maven 3.6.3 及以上,Gradle 版无需安装 Maven 及 Gradle
11
+:::
12
+
13
+::: warning 另外您还需要安装以下中间件并启动
14
+1. MySQL 5.6.x 及以上
15
+2. Redis 3.x 及以上
16
+:::
17
+
18
+### 1、数据库
19
+* 在 `MySQL` 中创建数据库:`ry-vue`
20
+  ![mysql](../../.vuepress/public/boot/mysql.png)
21
+* 向数据库`ry-vue`中导入表:ruoyi-solon/sql/ry-vue.sql
22
+* 修改项目中的数据库连接配置:ruoyi-solon/ruoyi-admin/src/main/resources/app-dev.yml
23
+  ```yaml {6-8}
24
+  # Redis配置
25
+  redis:
26
+    cache_source:
27
+      config: |
28
+        singleServerConfig:
29
+          address: redis://127.0.0.1:6379
30
+          password:
31
+          database: 7
32
+  ```
33
+  > 请确保 Redis 指定库中没有缓存数据
34
+  ```yaml {8-10}
35
+  # mybatis-flex 数据源及 mybatis配置
36
+  mybatis-flex:
37
+    # 动态数据源
38
+    datasource:
39
+      master:
40
+        type: com.zaxxer.hikari.HikariDataSource
41
+        driverClassName: com.mysql.cj.jdbc.Driver
42
+        jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
43
+        username: root
44
+        password:
45
+  ```
46
+  ::: warning 注意
47
+  您还需要配置`quartz定时任务持久化`:  
48
+  ruoyi-solon/ruoyi-admin/src/main/resources/quartz.properties  
49
+  配置为和`app-dev.yml`中同一个数据库即可。
50
+  :::
51
+  ```yaml {4-6}
52
+  # quartz定时任务持久化配置
53
+  org.quartz.dataSource.ryDS.provider=hikaricp
54
+  org.quartz.dataSource.ryDS.driver=com.mysql.cj.jdbc.Driver
55
+  org.quartz.dataSource.ryDS.URL=jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true
56
+  org.quartz.dataSource.ryDS.user=root
57
+  org.quartz.dataSource.ryDS.password=
58
+  ```
59
+
60
+### 2、运行后端
61
+* 使用`IDEA`打开`ruoyi-solon`,启动:
62
+  * ruoyi-solon/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication
63
+::: warning 注意
64
+如果是`Gradle`版,并且您的`IDEA`版本较旧(比如`2018.3`版),启动后访问系统可能会报错:
65
+> Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found.
66
+
67
+这是由于`Gradle`版本与`IDEA`版本兼容性导致的编译参数`-parameters`没生效。\
68
+您需要在`File -> Settings -> Build,Execution,Deployment -> Compiler -> Java Compiler`中的`Javac Options`下的`Additional command line parameters`中添加`-parameters`。
69
+
70
+![gradle_settings](../../.vuepress/public/boot/gradle_settings.png)
71
+添加后`clean`,重新编译。
72
+
73
+`IDEA`推荐使用`2021.3`及以上版本。
74
+:::
75
+
76
+## 前端
77
+::: tip 请确认您已有以下运行环境
78
+1. Node.js 14.x 及以上
79
+:::
80
+
81
+### 1、运行前端
82
+```bash
83
+# 进入前端项目目录,在终端中运行命令
84
+cd ruoyi-solon-ui
85
+# cd ruoyi-solon-ui-vue3
86
+
87
+# 安装依赖
88
+npm install
89
+
90
+# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过指定镜像源解决 npm 下载速度慢的问题
91
+# npm install --registry=https://registry.npmmirror.com
92
+
93
+# 启动服务
94
+npm run dev
95
+```
96
+
97
+浏览器访问 http://localhost:80

+ 79
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/front.md 파일 보기

@@ -0,0 +1,79 @@
1
+---
2
+title: 前端手册
3
+prev: false
4
+# next: ./ops
5
+---
6
+
7
+## 说明
8
+* 前端手册不一定全面,您也可以参考 [若依前端手册](https://doc.ruoyi.vip/ruoyi-vue/document/qdsc.html)。
9
+* 先看一看`简介(单体版)`中的`项目结构`,帮助理解。
10
+* `Vue2`版本和`Vue3`版本的前端,目录结构几乎一致(除了`Vue3`版本的`index.html`从`public`目录下移到了根目录)。
11
+* `Vue2`版本的`store`使用的是`Vuex`,`Vue3`版本的`store`使用的是`Pinia`。
12
+* `Vue2`版本使用的是`Element-UI`,`Vue3`版本使用的是`Element-Plus`。
13
+* `Vue3`版本已经安装了`unplugin-auto-import`和`unplugin-vue-setup-extend-plus`,因此您可以在组件文件的`script`标签中定义组件名称`name`,例如`<script name="User" setup>`,
14
+以及您在组件文件中无需手动导入`ref`、`computed`、`toRefs`、`defineProps`等等。
15
+
16
+## 项目首页
17
+项目运行后,输入账密登录后的首页,默认是项目简介。  
18
+另外准备好了一个由echarts图表实现的统计页面,在`src/views/index_v1.vue`。  
19
+将`src/views/index_v1.vue`和`src/views/index.vue`内容对换即可。
20
+
21
+## 全局
22
+为了使用方便,注册了一些全局的方法、组件、自定义指令等,您可以在`src/plugins/index.js`中看到。  
23
+全局的方法、组件、自定义指令等,全局可以直接使用,无需再单独注册。
24
+|  全局方法  |  功能  |
25
+|  :--:  |  :--:  |
26
+|  $parseTime  |  格式化时间  |
27
+|  $download  |  下载文件  |
28
+|  $modal  |  模态框对象  |
29
+|  $tab  |  页签操作  |
30
+|  $resetForm  |  表单重置  |
31
+|  $selectDictLabel  |  回显数据字典  |
32
+|  $handleTree  |  构造树型结构数据  |
33
+> 全局方法统一使用`$`开头。  
34
+`Vue2`中使用`this.$xxx`,`Vue3`中使用`proxy.$xxx`。
35
+
36
+|  全局组件  |  功能  |
37
+|  :--:  |  :--:  |
38
+|  DictTag  |  字典标签组件  |
39
+|  Editor  |  富文本组件  |
40
+|  FileUpload  |  文件上传组件  |
41
+|  ImagePreview  |  图片预览组件  |
42
+|  ImageUpload  |  图片上传组件  |
43
+|  selectDictLabel  |  分页组件  |
44
+|  RightToolbar  |  自定义表格工具组件  |
45
+> 直接在模板中使用`<xxx-xxx />`。  
46
+推荐全小写 + 短横线的方式,比如:`<dict-tag />`
47
+
48
+|  全局指令  |  功能  |
49
+|  :--:  |  :--:  |
50
+|  v-clipboard  |  复制文本  |
51
+|  v-has-permi  |  字符权限  |
52
+|  v-has-role  |  角色权限  |
53
+|  v-dialog-drag  |  弹窗拖拽(Vue2版)  |
54
+> 直接在元素标签中使用`<el-button v-has-permi="['system:user:remove']" />`。  
55
+此时该按钮只能被拥有`system:user:remove`字符权限的用户看到并操作。
56
+
57
+## ESlint
58
+想使用`ESlint`,打开前端项目根目录下的`.eslintignore`,把配置的目录或通配符文件所在行注释掉即可。
59
+``` {2,4,6,8,10}
60
+# 忽略build目录下类型为js的文件的语法检查
61
+# build/*.js
62
+# 忽略src/assets目录下文件的语法检查
63
+# src/assets
64
+# 忽略public目录下文件的语法检查
65
+# public
66
+# 忽略当前目录下为js的文件的语法检查
67
+# *.js
68
+# 忽略当前目录下为vue的文件的语法检查
69
+# *.vue
70
+```
71
+> `ESlint`相关配置在前端项目根目录下的`.eslintrc.js`。
72
+
73
+## 组件
74
+`src/components`目录下已提供了很多组件。  
75
+包括但不限于:echarts图表、全屏等等。
76
+
77
+## utils工具
78
+`src/utils`目录下已提供了很多常用的方法。  
79
+包括但不限于:缓存、浮点型运算、日期格式化、文件下载、非对称加解密、校验、防抖等等。

+ 138
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/ops.md 파일 보기

@@ -0,0 +1,138 @@
1
+---
2
+title: 项目部署
3
+prev: false
4
+# next: ./uplog
5
+---
6
+
7
+## 后端
8
+### 1、打包
9
+* Maven 版
10
+  ```bash
11
+  mvn clean package
12
+  ```
13
+
14
+  ::: tip 默认打 jar 包
15
+  打包后会在 ruoyi-boot/ruoyi-admin/target 目录下生成 jar 包文件 ruoyi-admin.jar
16
+  :::
17
+
18
+* Gradle 版  
19
+  双击:`Gradle插件/ruoyi-boot/Tasks/build`下的`clean`和`build`。
20
+
21
+  ::: tip 默认打 jar 包
22
+  打包后会在 ruoyi-boot/ruoyi-admin/build/libs 目录下生成 jar 包文件 ruoyi-admin.jar
23
+  :::
24
+
25
+### 2、运行
26
+```bash
27
+java –jar ruoyi-admin.jar
28
+```
29
+
30
+::: tip 支持添加启动参数以及加载外部配置文件
31
+```bash
32
+java –jar ruoyi-admin.jar --server.port=8081
33
+
34
+java –jar ruoyi-admin.jar --solon.env=dev
35
+
36
+java –jar ruoyi-admin.jar --solon.config.add=./app.yml
37
+```
38
+详见 [Solon 配置](https://solon.noear.org/article/482)
39
+:::
40
+
41
+### 3、jar包加密
42
+如果您不希望 jar 包被反编译导致泄露源码,您可以对 jar 包进行加密(目前仅支持`Maven`版的`solon-maven-plugin`打包方式)。  
43
+加密工具:[ClassFinal](https://gitee.com/lcm742320521/class-final)  
44
+加密只需一步:添加加密插件
45
+
46
+```xml
47
+<!-- ruoyi-boot/ruoyi-admin/pom.xml -->
48
+<build>
49
+  <finalName>${project.artifactId}</finalName>
50
+  <plugins>
51
+    <plugin>
52
+      <groupId>org.noear</groupId>
53
+      <artifactId>solon-maven-plugin</artifactId>
54
+    </plugin>
55
+
56
+    <!-- jar包加密 -->
57
+    <plugin>
58
+      <groupId>com.gitee.lcm742320521</groupId>
59
+      <artifactId>classfinal-maven-plugin</artifactId>
60
+      <version>1.4.1</version>
61
+      <configuration>
62
+        <libjars>ruoyi-*.jar</libjars><!-- jar包lib下要加密jar文件名(可为空,多个用","分割) -->
63
+        <packages>com.ruoyi</packages><!-- 加密的包名(可为空,多个用","分割。应包含所有需要加密的类的包名) -->
64
+        <cfgfiles>*.yml</cfgfiles><!-- 需要加密的配置文件,一般是resources目录下的yml或properties文件(可为空,多个用","分割) -->
65
+        <password>#</password><!-- 加密密码,如果是#号,则使用无密码模式加密 -->
66
+      </configuration>
67
+      <executions>
68
+        <execution>
69
+          <phase>package</phase>
70
+          <goals>
71
+            <goal>classFinal</goal>
72
+          </goals>
73
+        </execution>
74
+      </executions>
75
+    </plugin>
76
+  </plugins>
77
+</build>
78
+```
79
+添加以上打包加密插件后,正常打包即可(打包方式不变)。打包成功后可在 ruoyi-boot/ruoyi-admin/target 目录下看到两个 jar 包:
80
+  * ruoyi-admin.jar
81
+  * ruoyi-admin-encrypted.jar *加密后的*
82
+
83
+请运行加密后的 jar 包,运行命令为:
84
+```bash
85
+java -javaagent:ruoyi-admin-encrypted.jar -jar ruoyi-admin-encrypted.jar
86
+```
87
+
88
+## 前端
89
+### 1、打包
90
+```bash
91
+npm run build:prod
92
+```
93
+
94
+::: tip 提示
95
+打包成功之后,会在根目录生成 dist 文件夹,通常是 .js 、.css、index.html 等静态文件。  
96
+将 dist 文件夹发布到你的 Nginx 或者静态服务器即可,其中的 index.html 是后台服务的入口页面。
97
+:::
98
+
99
+### 2、Nginx 配置参考
100
+~~~
101
+worker_processes  1;
102
+
103
+events {
104
+  worker_connections  1024;
105
+}
106
+
107
+http {
108
+  include            mime.types;
109
+  default_type       application/octet-stream;
110
+  sendfile           on;
111
+  keepalive_timeout  65;
112
+
113
+  server {
114
+    listen       80;
115
+    server_name  localhost;
116
+    charset      utf-8;
117
+
118
+    location / {
119
+      root  /home/ruoyi/ui;
120
+      try_files $uri $uri/ /index.html;
121
+      index  index.html index.htm;
122
+    }
123
+
124
+    location /prod-api/ {
125
+      proxy_set_header Host $http_host;
126
+      proxy_set_header X-Real-IP $remote_addr;
127
+      proxy_set_header REMOTE-HOST $remote_addr;
128
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
129
+      proxy_pass http://localhost:8080/;
130
+    }
131
+
132
+    error_page  500 502 503 504  /50x.html;
133
+    location = /50x.html {
134
+      root  html;
135
+    }
136
+  }
137
+}
138
+~~~

+ 8
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/boot/uplog.md 파일 보기

@@ -0,0 +1,8 @@
1
+---
2
+title: 更新日志
3
+prev: false
4
+# next: ./uplog
5
+---
6
+
7
+## 更新日志
8
+参见 [发行版](https://gitee.com/opensolon/ruoyi-solon/releases)

+ 198
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/adumbrate.md 파일 보기

@@ -0,0 +1,198 @@
1
+---
2
+title: 简介(微服务版)
3
+prev: false
4
+# next: ./before
5
+---
6
+
7
+<el-alert
8
+  title="当前为 RuoYi-Cloud-Solon v3.1.0+ 版本的文档"
9
+  description="更低版本的文档请前往每个版本下的 docs 目录中查看"
10
+  type="warning"
11
+  effect="dark"
12
+  show-icon>
13
+</el-alert>
14
+
15
+### 简介
16
+[RuoYi-Cloud-Solon](https://gitee.com/opensolon/ruoyi-cloud-solon) 是基于 Solon + Vue 的前后端分离的快速开发脚手架,采用微服务架构,属于若依系统的 Solon 版本。
17
+
18
+**来看下架构图**
19
+![k8s](../../.vuepress/public/cloud/cloud.png)
20
+
21
+### 内置功能
22
+* 用户管理:用户是系统操作者,该功能主要完成系统用户配置。
23
+* 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。
24
+* 岗位管理:配置系统用户所属担任职务。
25
+* 菜单管理:配置系统菜单,操作权限,按钮权限标识等。
26
+* 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。
27
+* 字典管理:对系统中经常使用的一些较为固定的数据进行维护。
28
+* 参数管理:对系统动态配置常用参数。
29
+* 通知公告:系统通知公告信息发布维护。
30
+* 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。
31
+* 登录日志:系统登录日志记录查询包含登录异常。
32
+* 在线构建:拖动表单元素生成相应的HTML代码。
33
+* 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载。
34
+* 定时任务:任务调度及调度日志记录。
35
+* 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。
36
+* 系统接口:根据业务代码自动生成相关的api接口文档。
37
+* 在线用户:当前系统中活跃用户状态监控。
38
+* 缓存监控:对系统的缓存信息查询。
39
+
40
+### 技术选型
41
+- 后端
42
+  - Solon
43
+  - Solon Cloud
44
+  - HikariCP
45
+  - Mybatis-Flex
46
+  - Redis
47
+  - Sa-Token
48
+  - Hutool
49
+  - ···
50
+- 前端
51
+  - Vue
52
+  - Vue-Router
53
+  - Vuex / Pinia
54
+  - Element-UI / Element-Plus
55
+  - Axios
56
+  - Js-Cookie
57
+  - ···
58
+
59
+### 版本分支
60
+* 默认`master`分支,后端采用`Maven`作为构建工具。
61
+* `gradle`分支,后端采用`Gradle`作为构建工具。
62
+> 不建议直接`clone`分支代码,推荐下载标签中的最新版本。
63
+
64
+### 项目结构
65
+~~~
66
+ruoyi-cloud-solon(Maven版)
67
+├── docs                                  // 文档目录
68
+│   ├── ruoyi-docs                        // 项目配套文档
69
+├── ruoyi-api                             // 接口模块
70
+│       └── ruoyi-api-system              // 系统接口
71
+├── ruoyi-auth                            // 认证中心 [8101]
72
+├── ruoyi-cloud-ui                        // 前端框架 [80](Vue2)
73
+├── ruoyi-cloud-ui-vue3                   // 前端框架 [80](Vue3)
74
+├── ruoyi-common                          // 通用模块
75
+│       └── ruoyi-common-core             // 核心模块
76
+│       └── ruoyi-common-datasource       // 多数据源
77
+│       └── ruoyi-common-log              // 日志记录
78
+│       └── ruoyi-common-redis            // 缓存服务
79
+│       └── ruoyi-common-security         // 安全模块
80
+│       └── ruoyi-common-swagger          // 文档模块
81
+├── ruoyi-modules                         // 业务模块
82
+│       └── ruoyi-modules-demo            // 演示服务 [8103]
83
+│       └── ruoyi-modules-docs            // 文档服务 [8095]
84
+│       └── ruoyi-modules-file            // 文件服务 [8091]
85
+│       └── ruoyi-modules-gen             // 代码生成 [8092]
86
+│       └── ruoyi-modules-schedule        // 任务调度 [8093]
87
+│       └── ruoyi-modules-system          // 系统服务 [8102]
88
+├── ruoyi-visual                          // 图形化管理模块
89
+│       └── ruoyi-visual-monitor          // 监控中心 [8094]
90
+├── sql                                   // sql目录
91
+│   ├── K8S                               // 项目配套K8S配置参考
92
+│   ├── nacos_config_export_xxx.zip       // 项目配套服务配置文件(Nacos)
93
+│   ├── nginx.conf                        // 项目配套Nginx配置参考文件
94
+│   ├── ry-cloud.sql                      // 项目配套数据库文件
95
+│   ├── ry-cloud-schedule.sql             // 项目配套数据库文件(定时任务相关)
96
+├── .gitignore                            // git 忽略项
97
+├── LICENSE                               // 许可证
98
+├── pom.xml                               // 公共依赖
99
+├── README.md                             // README说明
100
+~~~
101
+~~~
102
+ruoyi-cloud-solon(Gradle版)
103
+├── gradle                                // gradle包装器
104
+├── ruoyi-api                             // 接口模块
105
+│       └── ruoyi-api-system              // 系统接口
106
+├── ruoyi-auth                            // 认证中心 [8101]
107
+├── ruoyi-common                          // 通用模块
108
+│       └── ruoyi-common-core             // 核心模块
109
+│       └── ruoyi-common-datasource       // 多数据源
110
+│       └── ruoyi-common-log              // 日志记录
111
+│       └── ruoyi-common-redis            // 缓存服务
112
+│       └── ruoyi-common-security         // 安全模块
113
+│       └── ruoyi-common-swagger          // 文档模块
114
+├── ruoyi-modules                         // 业务模块
115
+│       └── ruoyi-modules-demo            // 演示服务 [8103]
116
+│       └── ruoyi-modules-docs            // 文档服务 [8095]
117
+│       └── ruoyi-modules-file            // 文件服务 [8091]
118
+│       └── ruoyi-modules-gen             // 代码生成 [8092]
119
+│       └── ruoyi-modules-schedule        // 任务调度 [8093]
120
+│       └── ruoyi-modules-system          // 系统服务 [8102]
121
+├── ruoyi-visual                          // 图形化管理模块
122
+│       └── ruoyi-visual-monitor          // 监控中心 [8094]
123
+├── sql                                   // sql目录
124
+│   ├── K8S                               // 项目配套K8S配置参考
125
+│   ├── nacos_config_export_xxx.zip       // 项目配套服务配置文件(Nacos)
126
+│   ├── nginx.conf                        // 项目配套Nginx配置参考文件
127
+│   ├── ry-cloud.sql                      // 项目配套数据库文件
128
+│   ├── ry-cloud-schedule.sql             // 项目配套数据库文件(定时任务相关)
129
+├── .gitignore                            // git 忽略项
130
+├── build.gradle                          // gradle构建脚本
131
+├── gradlew                               // Linux脚本
132
+├── gradlew.bat                           // Windows脚本
133
+├── LICENSE                               // 许可证
134
+├── README.md                             // README说明
135
+├── settings.gradle                       // gradle项目配置
136
+~~~
137
+~~~
138
+ruoyi-cloud-solon-ui 前端项目(vue2版)
139
+├── build                                 // 构建相关
140
+├── public                                // 公共文件
141
+│   ├── favicon.ico                       // favicon图标
142
+│   └── index.html                        // html模板
143
+│   └── robots.txt                        // 反爬虫
144
+├── src                                   // 源代码
145
+│   ├── api                               // 所有请求(后台接口)
146
+│   ├── assets                            // 图片 样式等静态资源
147
+│   ├── components                        // 全局公用组件
148
+│   ├── directive                         // 自定义指令
149
+│   ├── layout                            // 布局
150
+│   ├── plugins                           // 插件(功能增强:比如全局方法挂载、全局组件挂载等)
151
+│   ├── router                            // 路由
152
+│   ├── store                             // Vuex
153
+│   ├── utils                             // 全局公用方法
154
+│   ├── views                             // 所有页面
155
+│   ├── App.vue                           // 入口页面
156
+│   ├── main.js                           // 入口 初始化Vue
157
+├── .editorconfig                         // EditorConfig插件配置
158
+├── .env.development                      // 开发环境配置
159
+├── .env.production                       // 生产环境配置
160
+├── .eslintignore                         // 忽略语法检查
161
+├── .eslintrc.js                          // eslint 配置项
162
+├── .gitignore                            // git 忽略项
163
+├── babel.config.js                       // babel.config.js
164
+├── package-lock.json                     // 包版本锁定
165
+├── package.json                          // 包管理
166
+├── README.md                             // README说明
167
+└── vue.config.js                         // vue.config.js
168
+~~~
169
+~~~
170
+ruoyi-cloud-solon-ui-vue3 前端项目(vue3版)
171
+├── public                                // 公共文件
172
+│   ├── favicon.ico                       // favicon图标
173
+├── src                                   // 源代码
174
+│   ├── api                               // 所有请求(后台接口)
175
+│   ├── assets                            // 图片 样式等静态资源
176
+│   ├── components                        // 全局公用组件
177
+│   ├── directive                         // 自定义指令
178
+│   ├── layout                            // 布局
179
+│   ├── plugins                           // 插件(功能增强:比如全局方法挂载、全局组件挂载等)
180
+│   ├── router                            // 路由
181
+│   ├── store                             // Pinia
182
+│   ├── utils                             // 全局公用方法
183
+│   ├── views                             // 所有页面
184
+│   ├── App.vue                           // 入口页面
185
+│   ├── main.js                           // 入口 初始化Vue
186
+├── .editorconfig                         // EditorConfig插件配置
187
+├── .env.development                      // 开发环境配置
188
+├── .env.production                       // 生产环境配置
189
+├── .eslintignore                         // 忽略语法检查
190
+├── .eslintrc-auto-import.json            // 忽略自动导入的语法检查
191
+├── .eslintrc.js                          // eslint 配置项
192
+├── .gitignore                            // git 忽略项
193
+├── index.html                            // html模板
194
+├── package-lock.json                     // 包版本锁定
195
+├── package.json                          // 包管理
196
+├── README.md                             // README说明
197
+└── vite.config.js                        // vite.config.js
198
+~~~

+ 602
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/backend.md 파일 보기

@@ -0,0 +1,602 @@
1
+---
2
+title: 后端手册
3
+prev: false
4
+# next: ./front
5
+---
6
+
7
+::: danger 注意
8
+请牢记您是在写 Solon 项目,而不是 SpringBoot 项目。
9
+:::
10
+
11
+## 依赖关系
12
+先来看一下基础模块间的依赖关系。
13
+![common](../../.vuepress/public/cloud/common.png)
14
+* 图中蓝色块为`ruoyi-common`下的模块,橙色块为`ruoyi-api`下的模块。
15
+* 图中箭头的含义是:例如`datasource`指向了`security`,说明`datasource`中引入了`security`。  
16
+  根据依赖的传递原则,当您引入了`datasource`后,就无需再引入`security`。  
17
+  `log`和`swagger`真正独立,不引入其它模块,也不被其它模块引入。
18
+* 您在创建可启动的微服务模块时,应当按需引入图中的部分基础模块。可选择引入的基础模块有:`log`、`datasource`、`swagger`、`security`。
19
+  * 其中必须引入的模块是`security`。因为它实现了鉴权、全局路由拦截器、全局过滤器等。
20
+  * 为了打印日志,您也应当引入`log`。
21
+  * `datasource`和`swagger`按需引入。
22
+* 新建的服务模块按照`是否需要数据源`,分为:
23
+  * 需要数据源:您应该引入`datasource`、`log`
24
+  * 不需要数据源:您应该引入`security`、`log`
25
+
26
+## 演示模块
27
+`ruoyi-modules-demo`是演示模块。如果您想创建新的服务模块,请参照此演示模块进行创建,您也可以直接改造演示模块。
28
+
29
+## 配置自动刷新
30
+所有服务模块的配置文件都在`Nacos`中,以下配置支持自动刷新(autoRefreshed = true):
31
+* 验证码配置:ruoyi.auth.*
32
+* 文件配置:ruoyi.file.*
33
+* 代码生成配置:ruoyi.gen.*
34
+::: warning 注意
35
+由于 Solon 内部机制的设计,如果您在`Nacos`中配置了数组类型的配置,然后在后端使用数组或List接收,并开启配置自动刷新,当配置变化后,会导致接收的配置参数重复导致混乱。
36
+
37
+因此如果您想实现数组类型的配置自动刷新,请配置为字符串形式,并在后端使用字符串切割为数组(参考文件配置或代码生成配置的自动刷新)。
38
+:::
39
+
40
+## 常用注解
41
+注解与 SpringBoot 的注解还是有区别的,详见 [常用注解比较](https://solon.noear.org/article/compare-springboot)。  
42
+常用注解替换:
43
+|  SpringBoot  |  Solon  |
44
+|  :--:  |  :--:  |
45
+|  @Autowired  |  @Inject  |
46
+|  @RestController + @RequestMapping("url")  |  @Controller + @Mapping("url")  |
47
+|  @GetMapping("url")等等  |  @Get等等 + @Mapping("url")  |
48
+|  @Service  |  @Component  |
49
+|  @Value("${key}")  |  @Inject("${key}")  |
50
+
51
+## 统一返回结果
52
+项目中的请求(除了 Admin监控 和 接口文档 外),其返回结果都被处理为`org.noear.solon.core.handle.Result<T>`返回给前端。
53
+```json
54
+// 返回结果示例
55
+{
56
+  code: 200,
57
+  description: "操作成功",
58
+  data: null
59
+}
60
+```
61
+详见 全局路由拦截器`com.ruoyi.common.security.interceptor.GlobalRouterInterceptor`
62
+
63
+## 异常处理
64
+所有的异常统一由`全局过滤器`捕获,并且也会渲染为`Result<T>`返回给前端  
65
+如果您想手动抛出异常,请参照:
66
+```java {2}
67
+if(!StrUtil.isAllNotEmpty(username, password)) {
68
+  throw new ServiceException("账号/密码必须填写");
69
+}
70
+```
71
+详见 全局过滤器`com.ruoyi.common.security.filter.GlobalFilter`
72
+
73
+## 分页实现
74
+* 前端采用`ElementUI`的分页组件 Pagination。
75
+* 后端采用`Mybatis-Flex`的分页查询,另外集成了轻量级分页插件 [PageHelper](https://github.com/pagehelper/Mybatis-PageHelper)(两种分页方式二选一即可)。
76
+  * `Mybatis-Flex`的分页查询示例
77
+  ```java {3,10}
78
+  @Controller
79
+  @Mapping("config")
80
+  public class SysConfigController extends BaseController {
81
+
82
+    @Get
83
+    @Mapping("list")
84
+    public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
85
+      QueryWrapper qw = QueryWrapper.create();
86
+      qw.and(SysConfig::getConfigName).like(sysConfig.getConfigName());
87
+      Page<SysConfig> result = sysConfigService.page(page, qw);
88
+      return getPageData(result);
89
+    }
90
+
91
+  }
92
+  ```
93
+  * `PageHelper`分页插件示例
94
+  ```java {3,8}
95
+  @Controller
96
+  @Mapping("table")
97
+  public class GenTableController extends BaseController {
98
+
99
+    @Get
100
+    @Mapping("tables")
101
+    public PageData tables(Page<GenTable> page, GenTable genTable) {
102
+      startPage(page);
103
+      List<GenTable> list = genTableService.tables(genTable);
104
+      return getPageData(list);
105
+    }
106
+
107
+  }
108
+  ```
109
+  ::: warning 注意
110
+  1、使用分页时,请将控制器`xxxController`继承控制器基类`BaseController`。  
111
+  2、`Pagehelper`只对`XML`的`SQL`分页有效,也就是说需要自己手写`SQL`,不能针对`flex`提供的快捷方法分页,比如`service.list()`。
112
+  :::
113
+
114
+## 数据导出
115
+::: warning 注意
116
+数据导出的底层使用的都是`Apache POI`来操作`Office`。  
117
+如果您不需要`poi`功能,可以将相关依赖和代码注释掉,这样打包的体积能减小 17~28 MB。
118
+:::
119
+后端使用`easy-poi`实现实体类数据的导出。在需要被导出的实体类属性添加`@Excel`注解即可。
120
+```java {6,11,15,19}
121
+@Table(value = "sys_config")
122
+public class SysConfig extends BaseEntity {
123
+  private static final long serialVersionUID = 1L;
124
+
125
+  /** 参数主键 */
126
+  @Excel(name = "参数主键")
127
+  @Id
128
+  private Long configId;
129
+
130
+  /** 参数名称 */
131
+  @Excel(name = "参数名称")
132
+  private String configName;
133
+
134
+  /** 系统内置(Y是 N否) */
135
+  @Excel(name = "系统内置", replace = { "是_Y", "否_N" })
136
+  private String configType;
137
+
138
+  /** 配置时间 */
139
+  @Excel(name = "配置时间", exportFormat = "yyyy年MM月dd日")
140
+  private Date configTime;
141
+
142
+}
143
+```
144
+::: tip 说明
145
+* `name`属性代表列名
146
+* `replace`属性用于值的替换:`configType`的值为`Y`或`N`,导出后将转换为`是`或`否`
147
+* `exportFormat`属性代表导出的时间格式
148
+* 如果需要忽略某一字段的导出,可以删除该字段上的`@Excel`注解,或者在该字段上添加`@ExcelIgnore`注解
149
+* 更多注解属性的使用,请参考`easy-poi`
150
+:::
151
+
152
+## 上传下载
153
+* 上传
154
+  * 前端采用`ElementUI`的上传组件 Upload。
155
+  * 后端支持本地文件上传及云存储(`ruoyi-modules-file`模块)。
156
+  ::: warning 注意
157
+  * 文件上传针对文件类型和文件大小在前端和后端都做了限制。
158
+    * 后端文件上传配置示例
159
+    ```yaml
160
+    ruoyi:
161
+      file:
162
+        # 使用的文件服务类型: s3 本地文件存储、aliyun 阿里云对象存储、qiniu 七牛云对象存储、minio
163
+        # 请前往 file 模块的 pom.xml 注释掉不用的文件服务依赖
164
+        type: s3
165
+        # 允许上传的文件大小(单位:MB,设为-1不限制)
166
+        maxSize: 2
167
+        # 允许上传的文件类型
168
+        fileType: jpg, jpeg, png, doc, docx, xls, xlsx, ppt, txt, pdf, zip
169
+
170
+    solon:
171
+      cloud:
172
+        # 本地文件 
173
+        file:
174
+          s3:
175
+            file:
176
+              default: local_bucket
177
+              buckets:
178
+                local_bucket:
179
+                  endpoint: C:\Users\ruoyi\Desktop
180
+                  requestPrefix: http://localhost:90/ruoyi-file
181
+                # more_bucket:
182
+                #   regionId: cn-east-1
183
+                #   endpoint: http://s3.ladydaily.com
184
+                #   accessKey: iWeU7cOoPLRokg2Hdat0jGQC
185
+                #   secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
186
+        # 阿里云 OSS
187
+        aliyun:
188
+          oss:
189
+            file:
190
+              endpoint: oss-cn-xxx.aliyuncs.com
191
+              bucket: world-data-dev
192
+              accessKey: iWeU7cOoPLRokg2Hdat0jGQC
193
+              secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
194
+        # 七牛云 OSS
195
+        qiniu:
196
+          kodo:
197
+            file:
198
+              regionId: cn-east-1
199
+              endpoint: https://xxx.yyy.zzz
200
+              requestPrefix: https://aaa.bbb.ccc
201
+              bucket: world-data-dev
202
+              accessKey: iWeU7cOoPLRokg2Hdat0jGQC
203
+              secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
204
+        # minio
205
+        minio:
206
+          file:
207
+            regionId: cn-east-1
208
+            endpoint: https://play.min.io
209
+            bucket: asiatrip
210
+            accessKey: iWeU7cOoPLRokg2Hdat0jGQC
211
+            secretKey: ZZIH6mT4VLAy68mVP80F7LiB5SpSEM7N
212
+    ```
213
+    * 默认使用本地文书上传。如果您想更换为其他上传方式(比如阿里云OSS),请先前往`ruoyi-modules-file`模块的`pom.xml`文件或`build.gradle`文件,打开阿里云OSS的注释,并注释掉其它的;并且修改上方文件上传配置:`ruoyi.file.type: aliyun`,重启`ruoyi-modules-file`服务。
214
+    ```xml
215
+    <!-- Maven 版 -->
216
+    <dependencies>
217
+      <!-- 本地文件 -->
218
+      <!--<dependency>-->
219
+        <!--<groupId>org.noear</groupId>-->
220
+        <!--<artifactId>file-s3-solon-cloud-plugin</artifactId>-->
221
+      <!--</dependency>-->
222
+
223
+      <!-- 阿里云 OSS -->
224
+      <dependency>
225
+        <groupId>org.noear</groupId>
226
+        <artifactId>aliyun-oss-solon-cloud-plugin</artifactId>
227
+      </dependency>
228
+
229
+      <!-- 七牛云 OSS -->
230
+      <!--<dependency>-->
231
+        <!--<groupId>org.noear</groupId>-->
232
+        <!--<artifactId>qiniu-kodo-solon-cloud-plugin</artifactId>-->
233
+      <!--</dependency>-->
234
+
235
+      <!-- minio(minio基于 minio8 sdk,minio7基于 minio7 sdk) -->
236
+      <!--<dependency>-->
237
+        <!--<groupId>org.noear</groupId>-->
238
+        <!--<artifactId>minio-solon-cloud-plugin</artifactId>-->
239
+      <!--</dependency>-->
240
+      <!--<dependency>-->
241
+        <!--<groupId>org.noear</groupId>-->
242
+        <!--<artifactId>minio7-solon-cloud-plugin</artifactId>-->
243
+      <!--</dependency>-->
244
+    </dependencies>
245
+    ```
246
+    ```gradle
247
+    //  Gradle 版
248
+    dependencies {
249
+      ...
250
+      //  implementation 'org.noear:file-s3-solon-cloud-plugin'
251
+      implementation 'org.noear:aliyun-oss-solon-cloud-plugin'
252
+      //  implementation 'org.noear:qiniu-kodo-solon-cloud-plugin'
253
+      //  implementation 'org.noear:minio-solon-cloud-plugin'
254
+      //  implementation 'org.noear:minio7-solon-cloud-plugin'
255
+    }
256
+    ```
257
+  * 如果您使用的是本地文件上传,您需要搭配`代理服务器`来实现本地文件的访问(例如 Nginx)。
258
+    * Nginx配置示例
259
+    ```
260
+    server {
261
+      listen       90;
262
+      server_name  localhost;
263
+
264
+      location /ruoyi-file {
265
+        alias   C:/Users/ruoyi/Desktop/;
266
+        autoindex on;
267
+      }
268
+    }
269
+    ```
270
+  :::
271
+  * 文件上传大小受以下几处限制:
272
+    * 前端上传组件
273
+    * 后端Web服务器的请求体大小:server.request.maxFileSize: 2mb
274
+    * 后端文件上传配置:ruoyi.file.maxSize: 2
275
+    * 前端部署到服务器后(例如 Nginx),Nginx限制的请求体大小
276
+* 下载  
277
+数据导出即采用了文件下载,您可以参照数据导出的实现。
278
+
279
+## 参数验证
280
+数据校验能力,详见 [solon-security-validation](https://solon.noear.org/article/225)。
281
+* 控制器基类`BaseController`中已加`@Valid`注解(请将控制器`xxxController`继承控制器基类`BaseController`)
282
+  ```java
283
+  @Valid
284
+  public class BaseController {
285
+  }
286
+  ```
287
+* 在控制器接口的形参前加上`@Validated`注解
288
+  ```java
289
+  @Post
290
+  @Mapping
291
+  public Result add(@Body @Validated SysConfig sysConfig) {
292
+    return toResult(sysConfigService.add(sysConfig));
293
+  }
294
+  ```
295
+* 在实体类的属性上添加相应的校验注解(例如:`@NotBlank(message = "参数名称不能为空")`)
296
+  ```java {5-6}
297
+  @Table(value = "sys_config")
298
+  public class SysConfig extends BaseEntity {
299
+    private static final long serialVersionUID = 1L;
300
+
301
+    @NotBlank(message = "参数名称不能为空")
302
+    @Length(max = 100, message = "参数名称不能超过100个字符")
303
+    private String configName;
304
+  }
305
+  ```
306
+
307
+## 权限注解
308
+权限采用了 [solon-security-auth](https://solon.noear.org/article/59) & [Sa-Token](https://sa-token.cc/doc.html#/use/jur-auth) 的实现方式。
309
+
310
+`solon-security-auth`认证一览:
311
+|  方法  |  描述  |  是否用到  |
312
+|  :--:  |  :--:  |  :--:  |
313
+|  verifyIp()  |  验证客户端IP是否有权访问  |  :heavy_check_mark:  |
314
+|  verifyLogined()  |  验证用户是否登录  |  :heavy_check_mark:  |
315
+|  verifyPath()  |  验证用户是否可访问该路径  |  :x:  |
316
+|  verifyPermissions()  |  验证用户是否具有某字符权限,例如`system:config:list`  |  :heavy_check_mark:  |
317
+|  verifyRoles()  |  验证用户是否具有某角色  |  :x:  |
318
+
319
+* 在`SecurityConfig`中定义了鉴权规则,在`AuthProcessorImpl`中定义了鉴权的判定逻辑
320
+  * 首先,所有的请求,校验客户端IP是否在黑名单中(`verifyIp()`)。  
321
+    被拉黑的IP将无法访问任何后端接口。您可以在配置文件中配置IP黑名单(share-config-dev.yml)。
322
+    ```yaml
323
+    ruoyi:
324
+      security:
325
+        ips:
326
+          - 1.1.1.1
327
+    ```
328
+  * 其次,所有的请求,校验登录的用户是否有(字符)权限调用接口(`verifyPermissions()`)。
329
+    ::: warning 注意
330
+    在`verifyPermissions()`方法校验(字符)权限前,先会去校验用户是否登录`verifyLogined()`。  
331
+    只有验证用户已经登录了,才会去校验用户是否有(字符)权限。  
332
+    如果您希望某个接口无需登录即可访问,需要配置放行白名单(share-config-dev.yml):
333
+    ```xml {3}
334
+    ruoyi:
335
+      security:
336
+        whites:
337
+          - /captcha
338
+          - /login
339
+          - /logout
340
+          ...
341
+    ```
342
+    :::
343
+* 关于字符权限  
344
+  字符权限形如`system:config:list`,由后台接口上的`@AuthPermissions`注解和菜单中的`perms`权限字符字段共同实现。
345
+  * 带有`@AuthPermissions`注解的接口,说明登录用户需要有此字符权限才能调用该接口
346
+    ```java {1}
347
+    @AuthPermissions("system:config:list")
348
+    @Get
349
+    @Mapping("list")
350
+    public PageData list() {
351
+      ...
352
+    }
353
+    ```
354
+  * 想让某用户可访问上述接口,首先需要在前端创建菜单或按钮并将上述权限字符配置到`perms`权限字符字段  
355
+    而后在角色管理中,给角色A添加该菜单或按钮的权限,最后将角色A赋予此用户即可  
356
+    此用户登录后将只能看到他所拥有的角色所能看到的菜单和按钮
357
+
358
+    > 用户登录成功后,已将该用户的所有已有权限放入了登录信息中。  
359
+      由`Sa-Token`的`StpUtil.hasPermission()`方法判定登录用户是否具有接口需要的字符权限。
360
+
361
+::: warning 注意
362
+这里的权限指的是用户登录前端后所能看到的菜单和菜单下的操作按钮  
363
+下方的数据权限指的是用户所能查询到的数据范围,比如只能查看自己所在部门的数据
364
+:::
365
+
366
+## 数据权限
367
+在实际开发中,需要设置用户只能查看哪些部门的数据,这种情况一般称为数据权限。  
368
+数据权限是通过部门来实现的。
369
+* 在角色管理中设置数据权限,目前支持以下几种:
370
+  * 全部数据权限
371
+  * 本部门数据权限
372
+  * 本部门及以下数据权限
373
+  * 仅本人数据权限
374
+  * 自定义数据权限
375
+* 在需要数据权限控制的控制器接口上添加`@RyDataScope`注解
376
+  ```java {1}
377
+  @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
378
+  @AuthPermissions("system:user:list")
379
+  @Get
380
+  @Mapping("list")
381
+  public PageData list(Page<SysUser> page, SysUser sysUser) {
382
+    startPage(page);
383
+    List<SysUser> list = sysUserService.selectUserList(sysUser);
384
+    return getPageData(list);
385
+  }
386
+  ```
387
+::: tip 提示
388
+* 常量`UserConstant.DATA_SCOPE_ALIAS_DEPT`和`UserConstant.DATA_SCOPE_ALIAS_USER`表示表的别名
389
+* 实体类需要继承基类`BaseEntity`才会处理,处理后的拼接sql语句将存放到`BaseEntity`的`dataScopeSql`字段,然后在`xml`中通过`${参数名.dataScopeSql}`拼接sql语句
390
+* 实现逻辑参考`DataScopeAspect`
391
+:::
392
+
393
+## 动态数据源
394
+在实际开发中,经常可能遇到在一个应用中可能需要访问多个数据库的情况,在项目中使用注解来完成此项功能。
395
+* 首先配置文件中已经配置了一个多级数据源
396
+  ```yaml {5,11}
397
+  # mybatis-flex 数据源及 mybatis配置
398
+  mybatis-flex:
399
+    # 动态数据源
400
+    datasource:
401
+      master:
402
+        type: com.zaxxer.hikari.HikariDataSource
403
+        driverClassName: com.mysql.cj.jdbc.Driver
404
+        jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
405
+        username: root
406
+        password:
407
+      slave_1:
408
+        type: com.zaxxer.hikari.HikariDataSource
409
+        driverClassName: com.mysql.cj.jdbc.Driver
410
+        jdbcUrl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
411
+        username: root
412
+        password:
413
+  ```
414
+* 在`Controller`控制器层中通过`@UseDataSource`注解指定二级数据源
415
+  ```java {2}
416
+  @AuthPermissions("system:config:list")
417
+  @UseDataSource(DataSourceConstant.DATA_SOURCE_SLAVE_1)
418
+  @Get
419
+  @Mapping("list")
420
+  public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
421
+    ...
422
+  }
423
+  ```
424
+
425
+## 熔断限流
426
+使用`sentinel`实现。
427
+* 配置示例(share-config-dev.yml)
428
+```yaml
429
+solon:
430
+  cloud:
431
+    local:
432
+      # 限流
433
+      breaker:
434
+        # 根断路器的阀值(即默认阀值,必须大于0)
435
+        root: 1000
436
+        # global 为断路器名称(不配置或配置0,则取根断路器的阀值)
437
+        # global: 100
438
+```
439
+* 全局限流:`com.ruoyi.common.security.filter.GlobalFilter`
440
+* [Solon熔断限流](https://solon.noear.org/article/160)
441
+
442
+## 防重复提交
443
+使用注解`@NoRepeatSubmit`实现。在控制器上添加注解即可。
444
+```java {1}
445
+@NoRepeatSubmit(value = HttpPart.body, message = "请勿重复提交")
446
+@AuthPermissions("system:config:add")
447
+@Post
448
+@Mapping
449
+public Result<Void> add(@Body @Validated SysConfig sysConfig) {
450
+  return toResult(sysConfigService.add(sysConfig));
451
+}
452
+```
453
+::: tip 防重复提交注解属性说明
454
+* `value` 是否是重复提交的判断标准(3种:请求头、请求参数、请求体)
455
+* `seconds` 间隔时间,单位:秒
456
+:::
457
+
458
+## 多租户改造
459
+参考`单体版`文档的多租户改造。
460
+
461
+## 数据脱敏 & 字段权限
462
+参见 [MyBatis-Flex 数据脱敏](https://mybatis-flex.com/zh/core/mask.html),[MyBatis-Flex 字段权限](https://mybatis-flex.com/zh/core/columns-permission.html)
463
+
464
+## 定时任务 & 异步
465
+定时任务使用`quartz`实现。
466
+* 具体写法参照`ruoyi-modules-schedule`任务调度模块的`com.ruoyi.schedule.task.RyTask`
467
+
468
+定时任务支持持久化:您需要在`ruoyi-modules-schedule/src/main/resources/quartz.properties`中及`Nacos`中任务调度模块的配置文件`ruoyi-schedule-dev.yml`中配置数据源。  
469
+创建数据库`ry-cloud-schedule`并导入表:ruoyi-cloud-solon/sql/ry-cloud-schedule.sql
470
+> 注意将`quartz.properties`和`Nacos`中任务调度模块的配置文件配置为同一个数据库。  
471
+程序(后端)启动时会将`RyTask`中的定时任务写入数据库。  
472
+您可以通过定时任务管理页面对任务进行暂停、启动、删除等操作。
473
+::: warning 注意
474
+* 删除操作仅针对当次启动有效。下次程序(后端)启动时会重新将所有定时任务写入数据库
475
+* 暂停、启动永久生效
476
+* 如果您更改了`cron表达式`并重启,发现不生效,记得清空`quartz`相关的表(以`qrtz_`开头)
477
+:::
478
+
479
+## 代码生成
480
+提供了基础的增删查改代码生成功能。
481
+* 代码生成配置
482
+  ```yaml
483
+  ruoyi:
484
+    gen:
485
+      # 作者
486
+      author: ruoyi
487
+      # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
488
+      packageName: com.ruoyi.system
489
+      # 自动去除表前缀,默认是false
490
+      autoRemovePre: false
491
+      # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
492
+      tablePrefix: demo_
493
+      # 忽略的表前缀(不会查询这些前缀的表)
494
+      ignoreTablePrefix: [qrtz_, gen_, sys_]
495
+  ```
496
+* 登录系统(系统工具 -> 代码生成 -> 导入对应表)
497
+* 代码生成列表中找到需要的表(可预览、编辑、同步、删除生成配置)
498
+* 点击生成代码会得到一个`ruoyi.zip`压缩文件,按照包内目录结构复制到自己的项目的指定服务模块中即可
499
+
500
+## 系统接口文档
501
+使用`knife4j`实现。
502
+* 接口文档配置(位于 nacos 的 share-config-dev.yml 中)
503
+  ```yaml
504
+  knife4j:
505
+    # 开启增强配置
506
+    enable: true
507
+    # 开启生产环境屏蔽
508
+    production: false
509
+    # 签权
510
+    # basic:
511
+    #   enable: true
512
+    #   username: admin
513
+    #   password: 123456
514
+    # 前端UI的个性化配置
515
+    setting:
516
+      enableVersion: true
517
+      enableOpenApi: false
518
+      enableFooter: false
519
+  ```
520
+* 为服务模块引入文档模块
521
+  ```xml
522
+  <!-- 接口文档模块 -->
523
+  <dependency>
524
+      <groupId>com.ruoyi</groupId>
525
+      <artifactId>ruoyi-common-swagger</artifactId>
526
+  </dependency>
527
+  ```
528
+* 接口文档摘要:基于配置文件构建(在服务模块的配置文件中增加下方配置)
529
+  ```yaml
530
+  solon:
531
+    # 接口文档
532
+    docs:
533
+      routes:
534
+        - id: openapi  # 固定值
535
+          # groupName: group-name
536
+          info:
537
+            title: 接口文档
538
+            description: 在线API文档
539
+  #          termsOfService: https://gitee.com/noear/solon
540
+            contact:
541
+              name: ruoyi
542
+            version: 1.0
543
+          schemes:
544
+            - HTTP
545
+            - HTTPS
546
+          globalResponseInData: true
547
+          globalResult: org.noear.solon.core.handle.Result
548
+          apis:
549
+            - basePackage: com.ruoyi.system.controller
550
+  ```
551
+* 给接口添加注解
552
+  ```java {1,6}
553
+  @Api("系统参数配置")
554
+  @Controller
555
+  @Mapping("system/config")
556
+  public class SysConfigController extends BaseController {
557
+
558
+    @ApiOperation("列表查询")
559
+    @Get
560
+    @Mapping("list")
561
+    public PageData list(Page<SysConfig> page, SysConfig sysConfig) {
562
+      QueryWrapper qw = getQW(sysConfig);
563
+      Page<SysConfig> result = sysConfigService.page(page, qw);
564
+      return getPageData(result);
565
+    }
566
+
567
+  }
568
+  ```
569
+* 启动`RuoYiDocsApplication`,登录系统(系统工具 -> 系统接口),使用接口文档配置中的签权的账号密码登录
570
+* 如果不需要某个服务模块出现在文档中,可以在`RuoYiDocsApplication`的配置文件中配置忽略该服务
571
+  ```yaml{15-16}
572
+  solon:
573
+    # 接口文档
574
+    docs:
575
+      # 自动发现配置
576
+      discover:
577
+        # 是否启用自动发现
578
+        enabled: true
579
+        # 目标服务的文档接口路径模式(要么带变量 {service},要么用统一固定值)
580
+        uriPattern: swagger/v2?group=openapi
581
+        # 同步目标服务上下线状态(如果下线,则文档不显示)
582
+        syncStatus: false
583
+        # 签权
584
+        basicAuth:
585
+          admin: 123456
586
+        # 排除目标服务名
587
+        excludedServices:
588
+          - ruoyi-auth
589
+          - ruoyi-docs
590
+          - ruoyi-file
591
+          - ruoyi-gen
592
+          - ruoyi-schedule
593
+          - ruoyi-monitor
594
+  ```
595
+* 您应当最后启动`RuoYiDocsApplication`
596
+
597
+## 系统监控
598
+系统监控分为服务端和客户端,服务端有单独的模块`ruoyi-visual-monitor`,其它每个服务模块作为客户端。
599
+* 您需要先启动`ruoyi-visual-monitor`服务模块
600
+* 打开每个服务模块主启动类上的`@EnableAdminClient`注解的注释
601
+* 监控配置的服务端配置在`ruoyi-monitor-dev.yml`中,客户端配置在`share-config-dev.yml`中。
602
+* 登录系统(系统工具 -> Admin控制台),使用监控配置中的基础签权的账号密码登录

+ 135
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/before.md 파일 보기

@@ -0,0 +1,135 @@
1
+---
2
+title: 项目运行
3
+prev: false
4
+# next: ./backend
5
+---
6
+
7
+## 后端
8
+::: tip 请确认您已有以下运行环境
9
+1. JDK 1.8 及以上
10
+2. Maven 版需要安装 Maven 3.6.3 及以上,Gradle 版无需安装 Maven 及 Gradle
11
+:::
12
+
13
+::: warning 另外您还需要安装以下中间件并启动
14
+1. MySQL 5.6.x 及以上
15
+2. Redis 3.x 及以上
16
+3. Nacos 2.x
17
+:::
18
+
19
+### 1、Nacos
20
+您需要向`Nacos`中导入所有微服务模块的配置文件。
21
+* 首先在`Nacos`中创建命名空间:`ruoyi`
22
+  ::: danger 特别注意
23
+  您需要保证创建的`命名空间id`与后端项目每个微服务模块的配置文件`app.yml`中配置的`nacos.namespace`保持一致!
24
+  :::
25
+  ![namespace](../../.vuepress/public/cloud/namespace.png)
26
+  * 您可以在创建命名空间时将`app.yml`中配置的`nacos.namespace`作为`命名空间id`填入
27
+  * 您也可以在创建命名空间后,将`Nacos`自动生成的`命名空间id`配置到每个微服务模块的配置文件`app.yml`中的`nacos.namespace`
28
+* 在创建的命名空间`ruoyi`中导入配置文件:
29
+  ![namespace](../../.vuepress/public/cloud/nacos1.png)
30
+  ![namespace](../../.vuepress/public/cloud/nacos2.png)  
31
+  选择 sql 目录下的压缩包 ruoyi-cloud-solon/sql/nacos_config_export_xxx.zip
32
+* 导入成功:
33
+  ![namespace](../../.vuepress/public/cloud/nacos3.png)
34
+
35
+### 2、数据库
36
+* 在`MySQL`中创建数据库:`ry-cloud`
37
+  ![mysql](../../.vuepress/public/cloud/mysql.png)
38
+* 向数据库`ry-cloud`中导入表:ruoyi-cloud-solon/sql/ry-cloud.sql
39
+* 修改`Nacos`中每个配置文件的数据库连接配置:
40
+  ```yaml {6-8}
41
+  # Redis配置
42
+  redis:
43
+    cache_source:
44
+      config: |
45
+        singleServerConfig:
46
+          address: redis://127.0.0.1:6379
47
+          password:
48
+          database: 7
49
+  ```
50
+  > 请确保 Redis 指定库中没有缓存数据
51
+  ```yaml {8-10}
52
+  # mybatis-flex 数据源及 mybatis配置
53
+  mybatis-flex:
54
+    # 动态数据源
55
+    datasource:
56
+      master:
57
+        type: com.zaxxer.hikari.HikariDataSource
58
+        driverClassName: com.mysql.cj.jdbc.Driver
59
+        jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-cloud?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
60
+        username: root
61
+        password:
62
+  ```
63
+  ::: warning 注意
64
+  您在启动`RuoYiScheduleApplication`之前还需要配置`quartz定时任务持久化`:  
65
+  * 创建数据库`ry-cloud-schedule`并导入表:ruoyi-cloud-solon/sql/ry-cloud-schedule.sql  
66
+  * 修改数据库连接配置:
67
+    * `Nacos`中`RuoYiScheduleApplication`的配置文件:ruoyi-schedule-dev.yml
68
+    * 项目中:ruoyi-modules-schedule/src/main/resources/quartz.properties
69
+  :::
70
+  ```yaml {8-10}
71
+  # mybatis-flex 数据源及 mybatis配置
72
+  mybatis-flex:
73
+    # 动态数据源
74
+    datasource:
75
+      master:
76
+        type: com.zaxxer.hikari.HikariDataSource
77
+        driverClassName: com.mysql.cj.jdbc.Driver
78
+        jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-cloud-schedule?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
79
+        username: root
80
+        password:
81
+  ```
82
+  ```yaml {4-6}
83
+  # quartz定时任务持久化配置
84
+  org.quartz.dataSource.ryDS.provider=hikaricp
85
+  org.quartz.dataSource.ryDS.driver=com.mysql.cj.jdbc.Driver
86
+  org.quartz.dataSource.ryDS.URL=jdbc:mysql://127.0.0.1:3306/ry-cloud-schedule?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true
87
+  org.quartz.dataSource.ryDS.user=root
88
+  org.quartz.dataSource.ryDS.password=
89
+  ```
90
+
91
+### 3、运行后端
92
+* 启动:
93
+  * RuoYiAuthApplication *必要*
94
+  * RuoYiSystemApplication *必要*
95
+  * RuoYiGenApplication
96
+  * RuoYiFileApplication
97
+  * RuoYiScheduleApplication
98
+  * RuoYiDemoApplication
99
+  * RuoYiDocsApplication
100
+::: warning 注意
101
+如果是`Gradle`版,并且您的`IDEA`版本较旧(比如`2018.3`版),启动后访问系统可能会报错:
102
+> Error querying database. Cause: org.apache.ibatis.binding.BindingException: Parameter 'userName' not found.
103
+
104
+或者在账号密码确实输入正确,但依旧提示密码错误。  
105
+这是由于`Gradle`版本与`IDEA`版本兼容性导致的编译参数`-parameters`没生效。  
106
+您需要在`File -> Settings -> Build,Execution,Deployment -> Compiler -> Java Compiler`中的`Javac Options`下的`Additional command line parameters`中添加`-parameters`。
107
+
108
+![gradle_settings](../../.vuepress/public/boot/gradle_settings.png)
109
+添加后`clean`,重新编译。
110
+
111
+`IDEA`推荐使用`2021.3`及以上版本。
112
+:::
113
+
114
+## 前端
115
+::: tip 请确认您已有以下运行环境
116
+1. Node.js 14.x 及以上
117
+:::
118
+
119
+### 1、运行前端
120
+```bash
121
+# 进入前端项目目录,在终端中运行命令
122
+cd ruoyi-cloud-solon-ui
123
+# cd ruoyi-cloud-solon-ui-vue3
124
+
125
+# 安装依赖
126
+npm install
127
+
128
+# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过指定镜像源解决 npm 下载速度慢的问题
129
+# npm install --registry=https://registry.npmmirror.com
130
+
131
+# 启动服务
132
+npm run dev
133
+```
134
+
135
+浏览器访问 http://localhost:80

+ 79
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/front.md 파일 보기

@@ -0,0 +1,79 @@
1
+---
2
+title: 前端手册
3
+prev: false
4
+# next: ./ops
5
+---
6
+
7
+## 说明
8
+* 前端手册不一定全面,您也可以参考 [若依前端手册](https://doc.ruoyi.vip/ruoyi-vue/document/qdsc.html)。
9
+* 先看一看`简介(微服务版)`中的`项目结构`,帮助理解。
10
+* `Vue2`版本和`Vue3`版本的前端,目录结构几乎一致(除了`Vue3`版本的`index.html`从`public`目录下移到了根目录)。
11
+* `Vue2`版本的`store`使用的是`Vuex`,`Vue3`版本的`store`使用的是`Pinia`。
12
+* `Vue2`版本使用的是`Element-UI`,`Vue3`版本使用的是`Element-Plus`。
13
+* `Vue3`版本已经安装了`unplugin-auto-import`和`unplugin-vue-setup-extend-plus`,因此您可以在组件文件的`script`标签中定义组件名称`name`,例如`<script name="User" setup>`,
14
+以及您在组件文件中无需手动导入`ref`、`computed`、`toRefs`、`defineProps`等等。
15
+
16
+## 项目首页
17
+项目运行后,输入账密登录后的首页,默认是项目简介。  
18
+另外准备好了一个由echarts图表实现的统计页面,在`src/views/index_v1.vue`。  
19
+将`src/views/index_v1.vue`和`src/views/index.vue`内容对换即可。
20
+
21
+## 全局
22
+为了使用方便,注册了一些全局的方法、组件、自定义指令等,您可以在`src/plugins/index.js`中看到。  
23
+全局的方法、组件、自定义指令等,全局可以直接使用,无需再单独注册。
24
+|  全局方法  |  功能  |
25
+|  :--:  |  :--:  |
26
+|  $parseTime  |  格式化时间  |
27
+|  $download  |  下载文件  |
28
+|  $modal  |  模态框对象  |
29
+|  $tab  |  页签操作  |
30
+|  $resetForm  |  表单重置  |
31
+|  $selectDictLabel  |  回显数据字典  |
32
+|  $handleTree  |  构造树型结构数据  |
33
+> 全局方法统一使用`$`开头。  
34
+`Vue2`中使用`this.$xxx`,`Vue3`中使用`proxy.$xxx`。
35
+
36
+|  全局组件  |  功能  |
37
+|  :--:  |  :--:  |
38
+|  DictTag  |  字典标签组件  |
39
+|  Editor  |  富文本组件  |
40
+|  FileUpload  |  文件上传组件  |
41
+|  ImagePreview  |  图片预览组件  |
42
+|  ImageUpload  |  图片上传组件  |
43
+|  selectDictLabel  |  分页组件  |
44
+|  RightToolbar  |  自定义表格工具组件  |
45
+> 直接在模板中使用`<xxx-xxx />`。  
46
+推荐全小写 + 短横线的方式,比如:`<dict-tag />`
47
+
48
+|  全局指令  |  功能  |
49
+|  :--:  |  :--:  |
50
+|  v-clipboard  |  复制文本  |
51
+|  v-has-permi  |  字符权限  |
52
+|  v-has-role  |  角色权限  |
53
+|  v-dialog-drag  |  弹窗拖拽(Vue2版)  |
54
+> 直接在元素标签中使用`<el-button v-has-permi="['system:user:remove']" />`。  
55
+此时该按钮只能被拥有`system:user:remove`字符权限的用户看到并操作。
56
+
57
+## ESlint
58
+想使用`ESlint`,打开前端项目根目录下的`.eslintignore`,把配置的目录或通配符文件所在行注释掉即可。
59
+``` {2,4,6,8,10}
60
+# 忽略build目录下类型为js的文件的语法检查
61
+# build/*.js
62
+# 忽略src/assets目录下文件的语法检查
63
+# src/assets
64
+# 忽略public目录下文件的语法检查
65
+# public
66
+# 忽略当前目录下为js的文件的语法检查
67
+# *.js
68
+# 忽略当前目录下为vue的文件的语法检查
69
+# *.vue
70
+```
71
+> `ESlint`相关配置在前端项目根目录下的`.eslintrc.js`。
72
+
73
+## 组件
74
+`src/components`目录下已提供了很多组件。  
75
+包括但不限于:echarts图表、全屏等等。
76
+
77
+## utils工具
78
+`src/utils`目录下已提供了很多常用的方法。  
79
+包括但不限于:缓存、浮点型运算、日期格式化、文件下载、非对称加解密、校验、防抖等等。

+ 211
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/ops.md 파일 보기

@@ -0,0 +1,211 @@
1
+---
2
+title: 项目部署
3
+prev: false
4
+# next: ./uplog
5
+---
6
+
7
+## 后端
8
+### 1、打包
9
+* Maven 版
10
+  ```bash
11
+  mvn clean package
12
+  ```
13
+
14
+  ::: tip 默认打 jar 包
15
+  打包后会在每个微服务模块的 target 目录下生成 jar 包文件 ruoyi-*.jar
16
+  :::
17
+
18
+* Gradle 版  
19
+  双击:`Gradle插件/ruoyi-cloud-solon/Tasks/build`下的`clean`和`build`。
20
+  ::: tip 默认打 jar 包
21
+  打包后会在每个微服务模块的 build/libs 目录下生成 jar 包文件 ruoyi-*.jar
22
+  :::
23
+
24
+### 2、运行
25
+```bash
26
+java –jar ruoyi-*.jar
27
+
28
+# 按需运行 jar 包,用到哪个运行哪个
29
+```
30
+
31
+::: tip 支持添加启动参数
32
+```bash
33
+java –jar ruoyi-admin.jar --server.port=8081
34
+
35
+java –jar ruoyi-admin.jar --solon.env=dev
36
+
37
+java –jar ruoyi-admin.jar --nacos.namespace=ceb00317-a8b0-4a9a-a695-2274b7b53b5a
38
+```
39
+详见 [Solon 配置](https://solon.noear.org/article/482)
40
+:::
41
+
42
+### 3、jar包加密
43
+如果您不希望 jar 包被反编译导致泄露源码,您可以对 jar 包进行加密(目前仅支持`Maven`版的`solon-maven-plugin`打包方式)。  
44
+加密工具:[ClassFinal](https://gitee.com/lcm742320521/class-final)  
45
+加密只需一步:在每个需要打包的微服务模块添加加密插件(`ruoyi-auth/pom.xml`、`ruoyi-modules/ruoyi-modules-system/pom.xml`等)
46
+
47
+```xml
48
+<!-- pom.xml -->
49
+<build>
50
+  <finalName>${project.artifactId}</finalName>
51
+  <plugins>
52
+    <plugin>
53
+      <groupId>org.noear</groupId>
54
+      <artifactId>solon-maven-plugin</artifactId>
55
+    </plugin>
56
+
57
+    <!-- jar包加密 -->
58
+    <plugin>
59
+      <groupId>com.gitee.lcm742320521</groupId>
60
+      <artifactId>classfinal-maven-plugin</artifactId>
61
+      <version>1.4.1</version>
62
+      <configuration>
63
+        <libjars>ruoyi-*.jar</libjars><!-- jar包lib下要加密jar文件名(可为空,多个用","分割) -->
64
+        <packages>com.ruoyi</packages><!-- 加密的包名(可为空,多个用","分割。应包含所有需要加密的类的包名) -->
65
+        <cfgfiles>*.yml</cfgfiles><!-- 需要加密的配置文件,一般是resources目录下的yml或properties文件(可为空,多个用","分割) -->
66
+        <password>#</password><!-- 加密密码,如果是#号,则使用无密码模式加密 -->
67
+      </configuration>
68
+      <executions>
69
+        <execution>
70
+          <phase>package</phase>
71
+          <goals>
72
+            <goal>classFinal</goal>
73
+          </goals>
74
+        </execution>
75
+      </executions>
76
+    </plugin>
77
+  </plugins>
78
+</build>
79
+```
80
+添加以上打包加密插件后,正常打包即可(打包方式不变)。打包成功后可在每个微服务模块的 target 目录下看到两个 jar 包:
81
+  * ruoyi-*.jar
82
+  * ruoyi-*-encrypted.jar *加密后的*
83
+
84
+请运行加密后的 jar 包,运行命令为:
85
+```bash
86
+java -javaagent:ruoyi-*-encrypted.jar -jar ruoyi-*-encrypted.jar
87
+```
88
+
89
+
90
+## 前端
91
+### 1、打包
92
+```bash
93
+npm run build:prod
94
+```
95
+
96
+::: tip 提示
97
+打包成功之后,会在根目录生成 dist 文件夹,通常是 .js 、.css、index.html 等静态文件。  
98
+将 dist 文件夹发布到你的 Nginx 或者静态服务器即可,其中的 index.html 是后台服务的入口页面。
99
+:::
100
+
101
+### 2、Nginx 配置参考
102
+::: warning 注意
103
+由于没有使用`solon-cloud-gateway`,需要使用 Nginx 进行请求分发。
104
+
105
+参考配置文件:ruoyi-cloud-solon/sql/nginx.conf
106
+:::
107
+
108
+~~~
109
+worker_processes  1;
110
+
111
+events {
112
+  worker_connections  1024;
113
+}
114
+
115
+http {
116
+  include            mime.types;
117
+  default_type       application/octet-stream;
118
+  sendfile           on;
119
+  keepalive_timeout  65;
120
+
121
+  server {
122
+    listen       80;
123
+    server_name  localhost;
124
+    charset      utf-8;
125
+
126
+    location / {
127
+      root  /home/ruoyi/ui;
128
+      try_files $uri $uri/ /index.html;
129
+      index  index.html index.htm;
130
+    }
131
+
132
+    location /prod-api/auth/ {
133
+      proxy_set_header Host $http_host;
134
+      proxy_set_header X-Real-IP $remote_addr;
135
+      proxy_set_header REMOTE-HOST $remote_addr;
136
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
137
+      proxy_pass http://ruoyi-auth/;
138
+    }
139
+
140
+    location /prod-api/system/ {
141
+      proxy_set_header Host $http_host;
142
+      proxy_set_header X-Real-IP $remote_addr;
143
+      proxy_set_header REMOTE-HOST $remote_addr;
144
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
145
+      proxy_pass http://ruoyi-system/;
146
+    }
147
+
148
+    location /prod-api/file/ {
149
+      proxy_set_header Host $http_host;
150
+      proxy_set_header X-Real-IP $remote_addr;
151
+      proxy_set_header REMOTE-HOST $remote_addr;
152
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
153
+      proxy_pass http://ruoyi-file/;
154
+    }
155
+
156
+    location /prod-api/gen/ {
157
+      proxy_set_header Host $http_host;
158
+      proxy_set_header X-Real-IP $remote_addr;
159
+      proxy_set_header REMOTE-HOST $remote_addr;
160
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
161
+      proxy_pass http://ruoyi-gen/;
162
+    }
163
+
164
+    location /prod-api/schedule/ {
165
+      proxy_set_header Host $http_host;
166
+      proxy_set_header X-Real-IP $remote_addr;
167
+      proxy_set_header REMOTE-HOST $remote_addr;
168
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
169
+      proxy_pass http://ruoyi-schedule/;
170
+    }
171
+
172
+    location /prod-api/demo/ {
173
+      proxy_set_header Host $http_host;
174
+      proxy_set_header X-Real-IP $remote_addr;
175
+      proxy_set_header REMOTE-HOST $remote_addr;
176
+      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
177
+      proxy_pass http://ruoyi-demo/;
178
+    }
179
+
180
+    error_page  500 502 503 504  /50x.html;
181
+    location = /50x.html {
182
+      root  html;
183
+    }
184
+  }
185
+
186
+  upstream ruoyi-auth {
187
+    server localhost:8101;
188
+  }
189
+
190
+  upstream ruoyi-system {
191
+    server localhost:8102;
192
+  }
193
+
194
+  upstream ruoyi-file {
195
+    server localhost:8091;
196
+  }
197
+
198
+  upstream ruoyi-gen {
199
+    server localhost:8092;
200
+  }
201
+
202
+  upstream ruoyi-schedule {
203
+    server localhost:8093;
204
+  }
205
+
206
+  upstream ruoyi-demo {
207
+    server localhost:8103;
208
+  }
209
+
210
+}
211
+~~~

+ 8
- 0
cmc-temperature-back/docs/ruoyi-docs/docs/guide/cloud/uplog.md 파일 보기

@@ -0,0 +1,8 @@
1
+---
2
+title: 更新日志
3
+prev: false
4
+# next: ./uplog
5
+---
6
+
7
+## 更新日志
8
+参见 [发行版](https://gitee.com/opensolon/ruoyi-cloud-solon/releases)

+ 13401
- 0
cmc-temperature-back/docs/ruoyi-docs/package-lock.json
파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
파일 보기


+ 20
- 0
cmc-temperature-back/docs/ruoyi-docs/package.json 파일 보기

@@ -0,0 +1,20 @@
1
+{
2
+  "name": "ruoyi-docs",
3
+  "version": "1.0.0",
4
+  "description": "若依文档中心",
5
+  "main": "index.js",
6
+  "scripts": {
7
+    "dev": "vuepress dev docs",
8
+    "build": "vuepress build docs"
9
+  },
10
+  "keywords": [],
11
+  "author": "",
12
+  "license": "Apache 2.0",
13
+  "devDependencies": {
14
+    "vuepress": "1.9.10"
15
+  },
16
+  "dependencies": {
17
+    "async-validator": "^1.11.5",
18
+    "element-ui": "2.15.14"
19
+  }
20
+}

+ 95
- 0
cmc-temperature-back/pom.xml 파일 보기

@@ -0,0 +1,95 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+
7
+    <parent>
8
+        <groupId>org.noear</groupId>
9
+        <artifactId>solon-parent</artifactId>
10
+        <version>3.3.3</version>
11
+        <relativePath />
12
+    </parent>
13
+
14
+    <groupId>com.ruoyi</groupId>
15
+    <artifactId>ruoyi-solon</artifactId>
16
+    <version>${ruoyi-solon.version}</version>
17
+
18
+    <name>${project.artifactId}</name>
19
+    <packaging>pom</packaging>
20
+    <description>若依管理系统(Solon版)</description>
21
+
22
+    <modules>
23
+        <module>ruoyi-admin</module>
24
+        <module>ruoyi-common</module>
25
+        <module>ruoyi-framework</module>
26
+        <module>ruoyi-gen</module>
27
+        <module>ruoyi-schedule</module>
28
+        <module>ruoyi-system</module>
29
+    </modules>
30
+
31
+    <properties>
32
+        <ruoyi-solon.version>2.1.1</ruoyi-solon.version>
33
+        <mysql.connector.version>8.0.33</mysql.connector.version>
34
+    </properties>
35
+
36
+    <dependencyManagement>
37
+        <dependencies>
38
+            <!-- Mysql驱动包 -->
39
+            <dependency>
40
+                <groupId>mysql</groupId>
41
+                <artifactId>mysql-connector-java</artifactId>
42
+                <version>${mysql.connector.version}</version>
43
+            </dependency>
44
+
45
+            <!-- sqlite3驱动包 -->
46
+            <dependency>
47
+                <groupId>org.xerial</groupId>
48
+                <artifactId>sqlite-jdbc</artifactId>
49
+                <version>3.40.1.0</version>
50
+            </dependency>
51
+
52
+            <!-- hutool工具 -->
53
+            <dependency>
54
+                <groupId>cn.hutool</groupId>
55
+                <artifactId>hutool-bom</artifactId>
56
+                <version>${hutool.version}</version>
57
+                <type>pom</type>
58
+                <!-- 注意这里是import -->
59
+                <scope>import</scope>
60
+            </dependency>
61
+
62
+            <!-- 通用模块 -->
63
+            <dependency>
64
+                <groupId>com.ruoyi</groupId>
65
+                <artifactId>ruoyi-common</artifactId>
66
+                <version>${ruoyi-solon.version}</version>
67
+            </dependency>
68
+            <!-- 框架核心 -->
69
+            <dependency>
70
+                <groupId>com.ruoyi</groupId>
71
+                <artifactId>ruoyi-framework</artifactId>
72
+                <version>${ruoyi-solon.version}</version>
73
+            </dependency>
74
+            <!-- 代码生成 -->
75
+            <dependency>
76
+                <groupId>com.ruoyi</groupId>
77
+                <artifactId>ruoyi-gen</artifactId>
78
+                <version>${ruoyi-solon.version}</version>
79
+            </dependency>
80
+            <!-- 任务调度 -->
81
+            <dependency>
82
+                <groupId>com.ruoyi</groupId>
83
+                <artifactId>ruoyi-schedule</artifactId>
84
+                <version>${ruoyi-solon.version}</version>
85
+            </dependency>
86
+            <!-- 系统模块 -->
87
+            <dependency>
88
+                <groupId>com.ruoyi</groupId>
89
+                <artifactId>ruoyi-system</artifactId>
90
+                <version>${ruoyi-solon.version}</version>
91
+            </dependency>
92
+        </dependencies>
93
+    </dependencyManagement>
94
+
95
+</project>

BIN
cmc-temperature-back/qun.png 파일 보기


+ 62
- 0
cmc-temperature-back/ruoyi-admin/pom.xml 파일 보기

@@ -0,0 +1,62 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+
7
+    <parent>
8
+        <groupId>com.ruoyi</groupId>
9
+        <artifactId>ruoyi-solon</artifactId>
10
+        <version>${ruoyi-solon.version}</version>
11
+    </parent>
12
+
13
+    <artifactId>ruoyi-admin</artifactId>
14
+    <packaging>jar</packaging>
15
+    <description>服务入口</description>
16
+
17
+    <dependencies>
18
+        <!-- sqlite3驱动包 -->
19
+        <dependency>
20
+            <groupId>org.xerial</groupId>
21
+            <artifactId>sqlite-jdbc</artifactId>
22
+            <version>3.40.1.0</version>
23
+        </dependency>
24
+
25
+        <!-- 框架核心 -->
26
+        <dependency>
27
+            <groupId>com.ruoyi</groupId>
28
+            <artifactId>ruoyi-framework</artifactId>
29
+        </dependency>
30
+        <!-- 代码生成 -->
31
+        <dependency>
32
+            <groupId>com.ruoyi</groupId>
33
+            <artifactId>ruoyi-gen</artifactId>
34
+            <version>${ruoyi-solon.version}</version>
35
+        </dependency>
36
+        <!-- 任务调度 -->
37
+        <dependency>
38
+            <groupId>com.ruoyi</groupId>
39
+            <artifactId>ruoyi-schedule</artifactId>
40
+        </dependency>
41
+        <dependency>
42
+            <groupId>org.redisson</groupId>
43
+            <artifactId>redisson</artifactId>
44
+            <version>3.45.0</version>
45
+        </dependency>
46
+        <dependency>
47
+            <groupId>org.noear</groupId>
48
+            <artifactId>solon-security-auth</artifactId>
49
+        </dependency>
50
+    </dependencies>
51
+
52
+    <build>
53
+        <finalName>${project.artifactId}</finalName>
54
+        <plugins>
55
+            <plugin>
56
+                <groupId>org.noear</groupId>
57
+                <artifactId>solon-maven-plugin</artifactId>
58
+            </plugin>
59
+        </plugins>
60
+    </build>
61
+    
62
+</project>

+ 28
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java 파일 보기

@@ -0,0 +1,28 @@
1
+package com.ruoyi;
2
+
3
+import org.noear.solon.Solon;
4
+//import org.noear.solon.admin.client.annotation.EnableAdminClient;
5
+//import org.noear.solon.admin.server.annotation.EnableAdminServer;
6
+import org.noear.solon.annotation.SolonMain;
7
+import org.noear.solon.scheduling.annotation.EnableAsync;
8
+import org.noear.solon.scheduling.annotation.EnableScheduling;
9
+
10
+/**
11
+ * 启动程序
12
+ * @author ruoyi
13
+ */
14
+//@EnableAdminClient
15
+//@EnableAdminServer
16
+@EnableAsync
17
+@EnableScheduling
18
+@SolonMain
19
+public class RuoYiApplication {
20
+
21
+    public static void main(String[] args) {
22
+        long start = System.currentTimeMillis();
23
+        Solon.start(RuoYiApplication.class, args);
24
+        long times = System.currentTimeMillis() - start;
25
+        System.out.println("(♥◠‿◠)ノ゙  若依启动成功,耗时:【" + times + "ms】  ლ(´ڡ`ლ)゙");
26
+    }
27
+
28
+}

+ 35
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java 파일 보기

@@ -0,0 +1,35 @@
1
+package com.ruoyi.web.controller.common;
2
+
3
+import com.ruoyi.common.enums.RateLimitType;
4
+import com.ruoyi.framework.annotation.RyRateLimit;
5
+import com.ruoyi.framework.service.CaptchaService;
6
+import org.noear.solon.annotation.Controller;
7
+import org.noear.solon.annotation.Get;
8
+import org.noear.solon.annotation.Inject;
9
+import org.noear.solon.annotation.Mapping;
10
+import org.noear.solon.core.handle.Result;
11
+
12
+import java.util.Map;
13
+
14
+/**
15
+ * 验证码 操作处理
16
+ * @author ruoyi
17
+ */
18
+@Controller
19
+@Mapping("captcha")
20
+public class CaptchaController {
21
+
22
+    @Inject
23
+    CaptchaService captchaService;
24
+
25
+    /**
26
+     * 获取验证码
27
+     */
28
+    @RyRateLimit(count = 10, type = RateLimitType.IP)
29
+    @Get
30
+    @Mapping
31
+    public Result<Map<String, Object>> captcha() {
32
+        return captchaService.getCaptcha();
33
+    }
34
+
35
+}

+ 61
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/LoginController.java 파일 보기

@@ -0,0 +1,61 @@
1
+package com.ruoyi.web.controller.common;
2
+
3
+import com.ruoyi.common.enums.DeviceType;
4
+import com.ruoyi.common.web.domain.model.LoginBody;
5
+import com.ruoyi.common.web.domain.model.RegisterBody;
6
+import com.ruoyi.framework.service.LoginService;
7
+import org.noear.solon.annotation.*;
8
+import org.noear.solon.core.handle.Result;
9
+
10
+import java.util.Map;
11
+
12
+/**
13
+ * 登录 注册 操作处理
14
+ * @author ruoyi
15
+ */
16
+@Controller
17
+@Mapping
18
+public class LoginController {
19
+
20
+    @Inject
21
+    LoginService loginService;
22
+
23
+    /**
24
+     * 登录(PC端)
25
+     */
26
+    @Post
27
+    @Mapping("login")
28
+    public Map<String, Object> login(@Body LoginBody loginBody) {
29
+        return loginService.login(loginBody, DeviceType.PC.getCode());
30
+    }
31
+
32
+    /**
33
+     * 获取登录用户信息
34
+     */
35
+    @Get
36
+    @Mapping("getUserInfo")
37
+    public Map<String, Object> getUserInfo() {
38
+        return loginService.getUserInfo();
39
+    }
40
+
41
+    /**
42
+     * 登出
43
+     */
44
+    @Delete
45
+    @Mapping("logout")
46
+    public Result<Void> logout() {
47
+        loginService.logout();
48
+        return Result.succeed();
49
+    }
50
+
51
+    /**
52
+     * 注册
53
+     */
54
+    @Post
55
+    @Mapping("register")
56
+    public Result<Void> register(@Body RegisterBody registerBody) {
57
+        loginService.register(registerBody, DeviceType.PC.getCode());
58
+        return Result.succeed();
59
+    }
60
+
61
+}

+ 163
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java 파일 보기

@@ -0,0 +1,163 @@
1
+package com.ruoyi.web.controller.monitor;
2
+
3
+import cn.hutool.core.util.StrUtil;
4
+import com.mybatisflex.core.paginate.Page;
5
+import com.ruoyi.common.constants.CacheConstant;
6
+import com.ruoyi.common.enums.BusinessType;
7
+import com.ruoyi.common.utils.RedisUtil;
8
+import com.ruoyi.common.web.controller.BaseController;
9
+import com.ruoyi.common.web.domain.PageData;
10
+import com.ruoyi.common.web.domain.entity.Cache;
11
+import com.ruoyi.framework.annotation.RyLog;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+import org.redisson.api.RKeys;
16
+import org.redisson.api.RScript;
17
+import org.redisson.api.RedissonClient;
18
+import org.redisson.api.RType;
19
+
20
+import java.util.*;
21
+import java.util.stream.Collectors;
22
+
23
+/**
24
+ * 缓存监控
25
+ * @author ruoyi
26
+ */
27
+@Controller
28
+@Mapping("monitor/cache")
29
+public class CacheController extends BaseController {
30
+
31
+    @Inject
32
+    RedissonClient redissonClient;
33
+
34
+    @Inject
35
+    RedisUtil redisUtil;
36
+
37
+    /**
38
+     * 查询缓存列表
39
+     */
40
+    @AuthPermissions("monitor:cache:list")
41
+    @Get
42
+    @Mapping("list")
43
+    public PageData<Cache> list(Page<Cache> page, Cache cache) {
44
+        List<Cache> cacheList = getList(cache);
45
+        // 分页
46
+        List<Cache> list = cacheList.stream()
47
+                .skip((page.getPageNumber() - 1) * page.getPageSize())
48
+                .limit(page.getPageSize())
49
+                .collect(Collectors.toList());
50
+        return getPageData(list).total(cacheList.size());
51
+    }
52
+
53
+    /**
54
+     * 删除缓存
55
+     */
56
+    @RyLog(title = "缓存监控", businessType = BusinessType.DELETE)
57
+    @AuthPermissions("monitor:cache:remove")
58
+    @Delete
59
+    @Mapping
60
+    public Result<Void> delete(Cache cache) {
61
+        RType type = RType.valueOf(cache.getName());
62
+        boolean b = false;
63
+        switch (type) {
64
+            case OBJECT:
65
+                b = redisUtil.deleteCacheObject(cache.getKey());
66
+                break;
67
+            case LIST:
68
+                b = redisUtil.deleteCacheList(cache.getKey());
69
+                break;
70
+            case MAP:
71
+                b = redisUtil.deleteCacheMap(cache.getKey());
72
+                break;
73
+            case SET:
74
+                b = redisUtil.deleteCacheSet(cache.getKey());
75
+                break;
76
+            case ZSET:
77
+                b = redisUtil.deleteCacheZSet(cache.getKey());
78
+                break;
79
+            default:
80
+                break;
81
+        }
82
+        return toResult(b);
83
+    }
84
+
85
+    /**
86
+     * 查询缓存信息
87
+     * @return
88
+     */
89
+    @AuthPermissions("monitor:cache:query")
90
+    @Get
91
+    @Mapping("info")
92
+    public Result<Map<String, String>> info() {
93
+        RScript script = redissonClient.getScript();
94
+        String info = script.eval(RScript.Mode.READ_ONLY, "return redis.call('info');", RScript.ReturnType.STATUS);
95
+        Map<String, String> map = new HashMap<>();
96
+        if(StrUtil.isNotEmpty(info)) {
97
+            List<String> split = StrUtil.split(info, "\r\n");
98
+            for (String s : split) {
99
+                if(StrUtil.isNotEmpty(s) && StrUtil.contains(s, ":")) {
100
+                    String[] strings = StrUtil.splitToArray(s, ":");
101
+                    map.put(strings[0], strings[1]);
102
+                }
103
+            }
104
+        }
105
+        return Result.succeed(map);
106
+    }
107
+
108
+    private List<Cache> getList(Cache cache) {
109
+        RKeys keys = redissonClient.getKeys();
110
+        List<Cache> cacheList = new ArrayList<>();
111
+        for (String key : keys.getKeys()) {
112
+            Cache cc = new Cache();
113
+            RType type = keys.getType(key);
114
+            cc.setType(type.getValue());
115
+            cc.setName(type.name());
116
+            cc.setKey(key);
117
+            getValue(cc, key, type);
118
+            getDesc(cc, key);
119
+            cacheList.add(cc);
120
+        }
121
+        // 根据查询条件检索
122
+        return cacheList.stream()
123
+                .filter(cc -> StrUtil.isEmpty(cache.getKey()) || cc.getKey().contains(cache.getKey()))
124
+                .collect(Collectors.toList());
125
+    }
126
+
127
+    private void getValue(Cache cache, String key, RType type) {
128
+        switch (type) {
129
+            case OBJECT:
130
+                cache.setValue(Collections.singletonList(redisUtil.getCacheObject(key)));
131
+                break;
132
+            case LIST:
133
+                cache.setValue(redisUtil.getCacheList(key));
134
+                break;
135
+            case MAP:
136
+                cache.setValue(redisUtil.getCacheMap(key));
137
+                break;
138
+            case SET:
139
+                cache.setValue(redisUtil.getCacheSet(key));
140
+                break;
141
+            case ZSET:
142
+                cache.setValue(redisUtil.getCacheZSetRange(key, 1, -1));
143
+                break;
144
+            default:
145
+                break;
146
+        }
147
+    }
148
+
149
+    private void getDesc(Cache cache, String key) {
150
+        if(key.startsWith(CacheConstant.CAPTCHA_CODE_KEY)) {
151
+            cache.setDescription("验证码");
152
+        } else if(key.startsWith(CacheConstant.LOGIN_ERROR_KEY)) {
153
+            cache.setDescription("登录失败");
154
+        } else if(key.startsWith(CacheConstant.SYS_DICT_KEY)) {
155
+            cache.setDescription("数据字典");
156
+        } else if(key.startsWith(CacheConstant.SYS_CONFIG_KEY)) {
157
+            cache.setDescription("系统参数");
158
+        } else if(key.startsWith(CacheConstant.RATE_LIMIT_KEY)) {
159
+            cache.setDescription("限流");
160
+        }
161
+    }
162
+
163
+}

+ 109
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/UserOnlineController.java 파일 보기

@@ -0,0 +1,109 @@
1
+package com.ruoyi.web.controller.monitor;
2
+
3
+import cn.dev33.satoken.session.SaSession;
4
+import cn.dev33.satoken.session.SaTerminalInfo;
5
+import cn.dev33.satoken.stp.StpUtil;
6
+import cn.hutool.core.util.StrUtil;
7
+import com.mybatisflex.core.paginate.Page;
8
+import com.ruoyi.common.constants.CacheConstant;
9
+import com.ruoyi.common.enums.BusinessType;
10
+import com.ruoyi.common.web.controller.BaseController;
11
+import com.ruoyi.common.web.domain.PageData;
12
+import com.ruoyi.common.web.domain.entity.UserOnline;
13
+import com.ruoyi.common.web.domain.model.LoginUser;
14
+import com.ruoyi.framework.annotation.RyLog;
15
+import org.noear.solon.annotation.*;
16
+import org.noear.solon.auth.annotation.AuthPermissions;
17
+import org.noear.solon.core.handle.Result;
18
+
19
+import java.util.ArrayList;
20
+import java.util.List;
21
+import java.util.stream.Collectors;
22
+
23
+/**
24
+ * 在线用户监控
25
+ * @author ruoyi
26
+ */
27
+@Controller
28
+@Mapping("monitor/online")
29
+public class UserOnlineController extends BaseController {
30
+
31
+    /**
32
+     * 查询在线用户列表
33
+     */
34
+    @AuthPermissions("monitor:online:list")
35
+    @Get
36
+    @Mapping("list")
37
+    public PageData<UserOnline> list(Page<UserOnline> page, UserOnline userOnline) {
38
+        List<UserOnline> userOnlineList = getList(userOnline);
39
+        // 分页
40
+        List<UserOnline> list = userOnlineList.stream()
41
+                .skip((page.getPageNumber() - 1) * page.getPageSize())
42
+                .limit(page.getPageSize())
43
+                .collect(Collectors.toList());
44
+        return getPageData(list).total(userOnlineList.size());
45
+    }
46
+
47
+    /**
48
+     * 强退所有用户
49
+     */
50
+    @RyLog(title = "在线用户", businessType = BusinessType.FORCE)
51
+    @AuthPermissions("monitor:online:batchLogout")
52
+    @Delete
53
+    @Mapping("forceLogoutAll/{userIds}")
54
+    public Result<Void> forceLogoutAll(@Path Long[] userIds) {
55
+        for (Long userId : userIds) {
56
+            StpUtil.logout(userId);
57
+        }
58
+        return Result.succeed();
59
+    }
60
+
61
+    /**
62
+     * 强退用户
63
+     */
64
+    @AuthPermissions("monitor:online:forceLogout")
65
+    @RyLog(title = "在线用户", businessType = BusinessType.FORCE)
66
+    @Delete
67
+    @Mapping("{token}")
68
+    public Result<Void> forceLogout(@Path String token) {
69
+        StpUtil.logoutByTokenValue(token);
70
+        return Result.succeed();
71
+    }
72
+
73
+    private List<UserOnline> getList(UserOnline userOnline) {
74
+        // 获取所有已登录的会话id(同一账号在多个设备登录只算作一个会话id)
75
+        List<String> sessionIdList = StpUtil.searchSessionId("", 0, -1, false);
76
+        List<UserOnline> userOnlineList = new ArrayList<>();
77
+        for (String sessionId : sessionIdList) {
78
+            // 根据会话id,查询对应的 SaSession 对象,此处一个 SaSession 对象即代表一个登录的账号
79
+            SaSession session = StpUtil.getSessionBySessionId(sessionId);
80
+            UserOnline uo = new UserOnline();
81
+            List<UserOnline.Device> devices = new ArrayList<>();
82
+            // 查询这个账号都在哪些设备登录了(terminalList.size()即为登录的设备数)
83
+            List<SaTerminalInfo> terminalList = session.terminalListCopy();
84
+            for (SaTerminalInfo saTerminalInfo : terminalList) {
85
+                // 获取指定 Token 的 Token-Session 对象
86
+                SaSession tokenSession = StpUtil.getTokenSessionByToken(saTerminalInfo.getTokenValue());
87
+                LoginUser loginUser = tokenSession.getModel(CacheConstant.LOGIN_USER_KEY, LoginUser.class);
88
+                uo.setUserid(loginUser.getUserid());
89
+                uo.setUserName(loginUser.getUsername());
90
+                uo.setNickName(loginUser.getSysUser().getNickName());
91
+                uo.setDeptName(loginUser.getSysUser().getDept().getDeptName());
92
+                UserOnline.Device device = uo.new Device();
93
+                device.setToken(tokenSession.getToken());
94
+                device.setDeviceType(saTerminalInfo.getDeviceType());
95
+                device.setLoginIp(loginUser.getIpaddr());
96
+                device.setLoginTime(loginUser.getLoginTime());
97
+                devices.add(device);
98
+            }
99
+            uo.setDevices(devices);
100
+            userOnlineList.add(uo);
101
+        }
102
+        // 根据查询条件检索
103
+        return userOnlineList.stream()
104
+                .filter(online -> StrUtil.isEmpty(userOnline.getUserName()) || online.getUserName().equals(userOnline.getUserName()))
105
+                .filter(online -> StrUtil.isEmpty(userOnline.getDeptName()) || online.getDeptName().equals(userOnline.getDeptName()))
106
+                .collect(Collectors.toList());
107
+    }
108
+
109
+}

+ 128
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java 파일 보기

@@ -0,0 +1,128 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.framework.annotation.RyLog;
10
+import com.ruoyi.system.domain.SysConfig;
11
+import com.ruoyi.system.service.ISysConfigService;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+import org.noear.solon.validation.annotation.Validated;
16
+
17
+import java.util.Arrays;
18
+import java.util.List;
19
+
20
+/**
21
+ * 系统参数配置 操作处理
22
+ * @author ruoyi
23
+ */
24
+@Controller
25
+@Mapping("system/config")
26
+public class SysConfigController extends BaseController {
27
+
28
+    @Inject
29
+    ISysConfigService sysConfigService;
30
+
31
+    /**
32
+     * 查询系统参数配置列表
33
+     */
34
+    @AuthPermissions("system:config:list")
35
+    @Get
36
+    @Mapping("list")
37
+    public PageData<SysConfig> list(Page<SysConfig> page, SysConfig sysConfig) {
38
+        QueryWrapper qw = getQW(sysConfig);
39
+        Page<SysConfig> result = sysConfigService.page(page, qw);
40
+        return getPageData(result);
41
+    }
42
+
43
+    /**
44
+     * 导出系统参数配置列表
45
+     */
46
+    @RyLog(title = "系统参数配置", businessType = BusinessType.EXPORT)
47
+    @AuthPermissions("system:config:export")
48
+    @Post
49
+    @Mapping("export")
50
+    public void export(SysConfig sysConfig) {
51
+        QueryWrapper qw = getQW(sysConfig);
52
+        List<SysConfig> list = sysConfigService.list(qw);
53
+        ExcelUtil.export(list);
54
+    }
55
+
56
+    /**
57
+     * 查询系统参数配置详情
58
+     */
59
+    @Get
60
+    @Mapping("{id}")
61
+    public SysConfig info(@Path Long id) {
62
+        return sysConfigService.getById(id);
63
+    }
64
+
65
+    /**
66
+     * 根据参数键名查询参数值
67
+     */
68
+    @Get
69
+    @Mapping("configKey/{configKey}")
70
+    public String getConfigKey(@Path String configKey) {
71
+        return sysConfigService.selectConfigByKey(configKey);
72
+    }
73
+
74
+    /**
75
+     * 新增系统参数配置
76
+     */
77
+    @RyLog(title = "系统参数配置", businessType = BusinessType.INSERT)
78
+    @AuthPermissions("system:config:add")
79
+    @Post
80
+    @Mapping
81
+    public Result<Void> add(@Body @Validated SysConfig sysConfig) {
82
+        return toResult(sysConfigService.add(sysConfig));
83
+    }
84
+
85
+    /**
86
+     * 修改系统参数配置
87
+     */
88
+    @RyLog(title = "系统参数配置", businessType = BusinessType.UPDATE)
89
+    @AuthPermissions("system:config:edit")
90
+    @Put
91
+    @Mapping
92
+    public Result<Void> edit(@Body @Validated SysConfig sysConfig) {
93
+        return toResult(sysConfigService.edit(sysConfig));
94
+    }
95
+
96
+    /**
97
+     * 删除系统参数配置
98
+     */
99
+    @RyLog(title = "系统参数配置", businessType = BusinessType.DELETE)
100
+    @AuthPermissions("system:config:remove")
101
+    @Delete
102
+    @Mapping("{dictIds}")
103
+    public Result<Void> delete(@Path Long[] dictIds) {
104
+        sysConfigService.delete(Arrays.asList(dictIds));
105
+        return Result.succeed();
106
+    }
107
+
108
+    /**
109
+     * 刷新系统参数配置缓存
110
+     */
111
+    @RyLog(title = "系统参数配置", businessType = BusinessType.CLEAN)
112
+    @AuthPermissions("system:config:remove")
113
+    @Get
114
+    @Mapping("refresh/cache")
115
+    public Result<Void> refreshCache() {
116
+        sysConfigService.loadingConfigCache();
117
+        return Result.succeed();
118
+    }
119
+
120
+    private QueryWrapper getQW(SysConfig sysConfig) {
121
+        QueryWrapper qw = QueryWrapper.create();
122
+        qw.and(SysConfig::getConfigName).like(sysConfig.getConfigName());
123
+        qw.and(SysConfig::getConfigType).eq(sysConfig.getConfigType());
124
+        qw.and(SysConfig::getConfigKey).like(sysConfig.getConfigKey());
125
+        return qw;
126
+    }
127
+
128
+}

+ 119
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java 파일 보기

@@ -0,0 +1,119 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.ruoyi.common.constants.UserConstant;
4
+import com.ruoyi.common.enums.BusinessType;
5
+import com.ruoyi.common.web.controller.BaseController;
6
+import com.ruoyi.common.web.domain.entity.SysDept;
7
+import com.ruoyi.framework.annotation.RyDataScope;
8
+import com.ruoyi.framework.annotation.RyLog;
9
+import com.ruoyi.system.domain.vo.TreeSelect;
10
+import com.ruoyi.system.service.ISysDeptService;
11
+import org.noear.solon.annotation.*;
12
+import org.noear.solon.auth.annotation.AuthPermissions;
13
+import org.noear.solon.core.handle.Result;
14
+import org.noear.solon.validation.annotation.Validated;
15
+
16
+import java.util.List;
17
+import java.util.Map;
18
+
19
+/**
20
+ * 部门 操作处理
21
+ * @author ruoyi
22
+ */
23
+@Controller
24
+@Mapping("system/dept")
25
+public class SysDeptController extends BaseController {
26
+
27
+    @Inject
28
+    ISysDeptService sysDeptService;
29
+
30
+    /**
31
+     * 获取部门列表
32
+     */
33
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
34
+    @AuthPermissions("system:dept:list")
35
+    @Get
36
+    @Mapping("list")
37
+    public List<SysDept> list(SysDept dept) {
38
+        return sysDeptService.selectDeptList(dept);
39
+    }
40
+
41
+    /**
42
+     * 查询部门列表(排除节点)
43
+     */
44
+    @AuthPermissions("system:dept:list")
45
+    @Get
46
+    @Mapping("list/exclude/{deptId}")
47
+    public List<SysDept> excludeChild(@Path Long deptId) {
48
+        return sysDeptService.excludeChild(deptId);
49
+    }
50
+
51
+    /**
52
+     * 查询部门详情
53
+     */
54
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
55
+    @AuthPermissions("system:dept:query")
56
+    @Get
57
+    @Mapping("{deptId}")
58
+    public SysDept info(@Path Long deptId, SysDept sysDept) {
59
+        return sysDeptService.info(deptId, sysDept);
60
+    }
61
+
62
+    /**
63
+     * 新增部门
64
+     */
65
+    @RyLog(title = "部门", businessType = BusinessType.INSERT)
66
+    @AuthPermissions("system:dept:add")
67
+    @Post
68
+    @Mapping
69
+    public Result<Void> add(@Body @Validated SysDept sysDept) {
70
+        return toResult(sysDeptService.add(sysDept));
71
+    }
72
+
73
+    /**
74
+     * 修改部门
75
+     */
76
+    @RyLog(title = "部门", businessType = BusinessType.UPDATE)
77
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
78
+    @AuthPermissions("system:dept:edit")
79
+    @Put
80
+    @Mapping
81
+    public Result<Void> edit(@Body @Validated SysDept sysDept) {
82
+        return toResult(sysDeptService.edit(sysDept));
83
+    }
84
+
85
+    /**
86
+     * 删除部门
87
+     */
88
+    @RyLog(title = "部门", businessType = BusinessType.DELETE)
89
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
90
+    @AuthPermissions("system:dept:remove")
91
+    @Delete
92
+    @Mapping("{deptId}")
93
+    public Result<Void> delete(@Path Long deptId, SysDept sysDept) {
94
+        return toResult(sysDeptService.delete(deptId, sysDept));
95
+    }
96
+
97
+    /**
98
+     * 获取对应角色部门树列表
99
+     */
100
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
101
+    @AuthPermissions("system:role:query")
102
+    @Get
103
+    @Mapping(value = "deptTree/{roleId}")
104
+    public Result<Map<String, Object>> deptTree(@Path Long roleId, SysDept sysDept) {
105
+        return Result.succeed(sysDeptService.deptTree(roleId, sysDept));
106
+    }
107
+
108
+    /**
109
+     * 获取部门树列表
110
+     */
111
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
112
+    @AuthPermissions("system:user:list")
113
+    @Get
114
+    @Mapping("deptTree")
115
+    public List<TreeSelect> deptTree(SysDept dept) {
116
+        return sysDeptService.selectDeptTreeList(dept);
117
+    }
118
+
119
+}

+ 129
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java 파일 보기

@@ -0,0 +1,129 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.framework.annotation.RyLog;
10
+import com.ruoyi.system.domain.SysDictData;
11
+import com.ruoyi.system.service.ISysDictDataService;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+import org.noear.solon.validation.annotation.Validated;
16
+
17
+import java.util.Arrays;
18
+import java.util.List;
19
+
20
+/**
21
+ * 数据字典 操作处理
22
+ * @author ruoyi
23
+ */
24
+@Controller
25
+@Mapping("system/dict/data")
26
+public class SysDictDataController extends BaseController {
27
+
28
+    @Inject
29
+    ISysDictDataService sysDictDataService;
30
+
31
+    /**
32
+     * 查询数据字典列表
33
+     */
34
+    @AuthPermissions("system:dict:list")
35
+    @Get
36
+    @Mapping("list")
37
+    public PageData<SysDictData> list(Page<SysDictData> page, SysDictData sysDictData) {
38
+        QueryWrapper qw = getQW(sysDictData);
39
+        Page<SysDictData> result = sysDictDataService.page(page, qw);
40
+        return getPageData(result);
41
+    }
42
+
43
+    /**
44
+     * 导出数据字典列表
45
+     */
46
+    @RyLog(title = "数据字典", businessType = BusinessType.EXPORT)
47
+    @AuthPermissions("system:dict:export")
48
+    @Post
49
+    @Mapping("export")
50
+    public void export(SysDictData sysDictData) {
51
+        QueryWrapper qw = getQW(sysDictData);
52
+        List<SysDictData> list = sysDictDataService.list(qw);
53
+        ExcelUtil.export(list);
54
+    }
55
+
56
+    /**
57
+     * 查询数据字典详情
58
+     */
59
+    @AuthPermissions("system:dict:query")
60
+    @Get
61
+    @Mapping("{id}")
62
+    public SysDictData info(@Path Long id) {
63
+        return sysDictDataService.getById(id);
64
+    }
65
+
66
+    /**
67
+     * 根据字典类型查询数据字典
68
+     */
69
+    @Get
70
+    @Mapping("type/{dictType}")
71
+    public List<SysDictData> getDataByType(@Path String dictType) {
72
+        return sysDictDataService.getDataByType(dictType);
73
+    }
74
+
75
+    /**
76
+     * 新增数据字典
77
+     */
78
+    @RyLog(title = "数据字典", businessType = BusinessType.INSERT)
79
+    @AuthPermissions("system:dict:add")
80
+    @Post
81
+    @Mapping
82
+    public Result<Void> add(@Body @Validated SysDictData sysDictData) {
83
+        return toResult(sysDictDataService.add(sysDictData));
84
+    }
85
+
86
+    /**
87
+     * 修改数据字典
88
+     */
89
+    @RyLog(title = "数据字典", businessType = BusinessType.UPDATE)
90
+    @AuthPermissions("system:dict:edit")
91
+    @Put
92
+    @Mapping
93
+    public Result<Void> edit(@Body @Validated SysDictData sysDictData) {
94
+        return toResult(sysDictDataService.edit(sysDictData));
95
+    }
96
+
97
+    /**
98
+     * 删除数据字典
99
+     */
100
+    @RyLog(title = "数据字典", businessType = BusinessType.DELETE)
101
+    @AuthPermissions("system:dict:remove")
102
+    @Delete
103
+    @Mapping("{dictCodes}")
104
+    public Result<Void> delete(@Path Long[] dictCodes) {
105
+        sysDictDataService.delete(Arrays.asList(dictCodes));
106
+        return Result.succeed();
107
+    }
108
+
109
+    /**
110
+     * 刷新字典缓存
111
+     */
112
+    @RyLog(title = "数据字典", businessType = BusinessType.CLEAN)
113
+    @AuthPermissions("system:dict:remove")
114
+    @Get
115
+    @Mapping("refresh/cache")
116
+    public Result<Void> refreshCache() {
117
+        sysDictDataService.loadingDictCache();
118
+        return Result.succeed();
119
+    }
120
+
121
+    private QueryWrapper getQW(SysDictData sysDictData) {
122
+        QueryWrapper qw = QueryWrapper.create();
123
+        qw.and(SysDictData::getDictType).eq(sysDictData.getDictType());
124
+        qw.and(SysDictData::getDictLabel).like(sysDictData.getDictLabel());
125
+        qw.and(SysDictData::getStatus).eq(sysDictData.getStatus());
126
+        return qw;
127
+    }
128
+
129
+}

+ 119
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java 파일 보기

@@ -0,0 +1,119 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.framework.annotation.RyLog;
10
+import com.ruoyi.system.domain.SysDictType;
11
+import com.ruoyi.system.service.ISysDictTypeService;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+import org.noear.solon.data.annotation.Transaction;
16
+import org.noear.solon.validation.annotation.Validated;
17
+
18
+import java.util.Arrays;
19
+import java.util.List;
20
+
21
+/**
22
+ * 数据字典类型 操作处理
23
+ * @author ruoyi
24
+ */
25
+@Controller
26
+@Mapping("system/dict/type")
27
+public class SysDictTypeController extends BaseController {
28
+
29
+    @Inject
30
+    ISysDictTypeService sysDictTypeService;
31
+
32
+    /**
33
+     * 查询数据字典类型列表
34
+     */
35
+    @AuthPermissions("system:dict:list")
36
+    @Get
37
+    @Mapping("list")
38
+    public PageData<SysDictType> list(Page<SysDictType> page, SysDictType sysDictType) {
39
+        QueryWrapper qw = getQW(sysDictType);
40
+        Page<SysDictType> result = sysDictTypeService.page(page, qw);
41
+        return getPageData(result);
42
+    }
43
+
44
+    /**
45
+     * 导出数据字典类型列表
46
+     */
47
+    @RyLog(title = "数据字典类型", businessType = BusinessType.EXPORT)
48
+    @AuthPermissions("system:dict:export")
49
+    @Post
50
+    @Mapping("export")
51
+    public void export(SysDictType sysDictType) {
52
+        QueryWrapper qw = getQW(sysDictType);
53
+        List<SysDictType> list = sysDictTypeService.list(qw);
54
+        ExcelUtil.export(list);
55
+    }
56
+
57
+    /**
58
+     * 查询数据字典类型详情
59
+     */
60
+    @AuthPermissions("system:dict:query")
61
+    @Get
62
+    @Mapping("{id}")
63
+    public SysDictType info(@Path Long id) {
64
+        return sysDictTypeService.getById(id);
65
+    }
66
+
67
+    /**
68
+     * 新增数据字典类型
69
+     */
70
+    @RyLog(title = "数据字典类型", businessType = BusinessType.INSERT)
71
+    @AuthPermissions("system:dict:add")
72
+    @Post
73
+    @Mapping
74
+    public Result<Void> add(@Body @Validated SysDictType sysDictType) {
75
+        return toResult(sysDictTypeService.add(sysDictType));
76
+    }
77
+
78
+    /**
79
+     * 修改数据字典类型
80
+     */
81
+    @RyLog(title = "数据字典类型", businessType = BusinessType.UPDATE)
82
+    @AuthPermissions("system:dict:edit")
83
+    @Transaction
84
+    @Put
85
+    @Mapping
86
+    public Result<Void> edit(@Body @Validated SysDictType sysDictType) {
87
+        return toResult(sysDictTypeService.edit(sysDictType));
88
+    }
89
+
90
+    /**
91
+     * 删除数据字典类型
92
+     */
93
+    @RyLog(title = "数据字典类型", businessType = BusinessType.DELETE)
94
+    @AuthPermissions("system:dict:remove")
95
+    @Delete
96
+    @Mapping("{dictIds}")
97
+    public Result<Void> delete(@Path Long[] dictIds) {
98
+        sysDictTypeService.delete(Arrays.asList(dictIds));
99
+        return Result.succeed();
100
+    }
101
+
102
+    /**
103
+     * 获取字典选择框列表
104
+     */
105
+    @Get
106
+    @Mapping("optionselect")
107
+    public List<SysDictType> optionselect() {
108
+        return sysDictTypeService.list();
109
+    }
110
+
111
+    private QueryWrapper getQW(SysDictType sysDictType) {
112
+        QueryWrapper qw = QueryWrapper.create();
113
+        qw.and(SysDictType::getDictName).like(sysDictType.getDictName());
114
+        qw.and(SysDictType::getDictType).like(sysDictType.getDictType());
115
+        qw.and(SysDictType::getStatus).eq(sysDictType.getStatus());
116
+        return qw;
117
+    }
118
+
119
+}

+ 102
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginLogController.java 파일 보기

@@ -0,0 +1,102 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.framework.annotation.RyLog;
10
+import com.ruoyi.system.domain.SysLoginLog;
11
+import com.ruoyi.system.service.ISysLoginLogService;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+
16
+import java.util.Arrays;
17
+import java.util.List;
18
+
19
+/**
20
+ * 登录日志 操作处理
21
+ * @author ruoyi
22
+ */
23
+@Controller
24
+@Mapping("system/loginlog")
25
+public class SysLoginLogController extends BaseController {
26
+
27
+    @Inject
28
+    ISysLoginLogService sysLoginLogService;
29
+
30
+    /**
31
+     * 查询登录日志列表
32
+     */
33
+    @AuthPermissions("system:loginlog:list")
34
+    @Get
35
+    @Mapping("list")
36
+    public PageData<SysLoginLog> list(Page<SysLoginLog> page, SysLoginLog sysLoginLog) {
37
+        QueryWrapper qw = getQW(sysLoginLog);
38
+        Page<SysLoginLog> result = sysLoginLogService.page(page, qw);
39
+        return getPageData(result);
40
+    }
41
+
42
+    /**
43
+     * 导出登录日志列表
44
+     */
45
+    @RyLog(title = "登录日志", businessType = BusinessType.EXPORT)
46
+    @AuthPermissions("system:loginlog:export")
47
+    @Post
48
+    @Mapping("export")
49
+    public void export(SysLoginLog sysLoginLog) {
50
+        QueryWrapper qw = getQW(sysLoginLog);
51
+        List<SysLoginLog> list = sysLoginLogService.list(qw);
52
+        ExcelUtil.export(list);
53
+    }
54
+
55
+    /**
56
+     * 解锁用户登录状态
57
+     */
58
+    @RyLog(title = "登录日志", businessType = BusinessType.OTHER)
59
+    @AuthPermissions("system:loginlog:unlock")
60
+    @Get
61
+    @Mapping("unlock/{userName}")
62
+    public Result<Void> unlock(@Path String userName) {
63
+        sysLoginLogService.unlock(userName);
64
+        return Result.succeed();
65
+    }
66
+
67
+    /**
68
+     * 删除登录日志
69
+     */
70
+    @RyLog(title = "登录日志", businessType = BusinessType.DELETE)
71
+    @AuthPermissions("system:loginlog:remove")
72
+    @Delete
73
+    @Mapping("{infoIds}")
74
+    public Result<Void> remove(@Path String[] infoIds) {
75
+        return toResult(sysLoginLogService.removeByIds(Arrays.asList(infoIds)));
76
+    }
77
+
78
+    /**
79
+     * 清空登录日志
80
+     */
81
+    @RyLog(title = "登录日志", businessType = BusinessType.CLEAN)
82
+    @AuthPermissions("system:loginlog:remove")
83
+    @Delete
84
+    @Mapping("clean")
85
+    public Result<Void> clean() {
86
+        sysLoginLogService.clean();
87
+        return Result.succeed();
88
+    }
89
+
90
+    private QueryWrapper getQW(SysLoginLog sysLoginLog) {
91
+        QueryWrapper qw = QueryWrapper.create();
92
+        qw.and(SysLoginLog::getUserName).like(sysLoginLog.getUserName());
93
+        qw.and(SysLoginLog::getIpaddr).like(sysLoginLog.getIpaddr());
94
+        qw.and(SysLoginLog::getDeviceType).eq(sysLoginLog.getDeviceType());
95
+        qw.and(SysLoginLog::getStatus).eq(sysLoginLog.getStatus());
96
+        qw.and(SysLoginLog::getCreateTime).ge(sysLoginLog.getStartTime());
97
+        qw.and(SysLoginLog::getCreateTime).le(sysLoginLog.getEndTime());
98
+        qw.orderBy(SysLoginLog::getCreateTime).desc();
99
+        return qw;
100
+    }
101
+
102
+}

+ 124
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java 파일 보기

@@ -0,0 +1,124 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.ruoyi.common.enums.BusinessType;
4
+import com.ruoyi.common.utils.SecurityUtil;
5
+import com.ruoyi.common.web.controller.BaseController;
6
+import com.ruoyi.framework.annotation.RyLog;
7
+import com.ruoyi.system.domain.SysMenu;
8
+import com.ruoyi.system.domain.vo.RouterVo;
9
+import com.ruoyi.system.domain.vo.TreeSelect;
10
+import com.ruoyi.system.service.ISysMenuService;
11
+import org.noear.solon.annotation.*;
12
+import org.noear.solon.auth.annotation.AuthPermissions;
13
+import org.noear.solon.core.handle.Result;
14
+import org.noear.solon.validation.annotation.Validated;
15
+
16
+import java.util.HashMap;
17
+import java.util.List;
18
+import java.util.Map;
19
+
20
+/**
21
+ * 系统菜单 操作处理
22
+ * @author ruoyi
23
+ */
24
+@Controller
25
+@Mapping("system/menu")
26
+public class SysMenuController extends BaseController {
27
+
28
+    @Inject
29
+    ISysMenuService sysMenuService;
30
+
31
+    /**
32
+     * 查询系统菜单列表
33
+     */
34
+    @AuthPermissions("system:menu:list")
35
+    @Get
36
+    @Mapping("list")
37
+    public List<SysMenu> list(SysMenu menu) {
38
+        Long userId = SecurityUtil.getUserId();
39
+        return sysMenuService.selectMenuList(menu, userId);
40
+    }
41
+
42
+    /**
43
+     * 查询系统菜单详情
44
+     */
45
+    @AuthPermissions("system:menu:query")
46
+    @Get
47
+    @Mapping("{id}")
48
+    public SysMenu info(@Path Long id) {
49
+        return sysMenuService.getById(id);
50
+    }
51
+
52
+    /**
53
+     * 获取菜单下拉树列表
54
+     * @param menu
55
+     * @return
56
+     */
57
+    @Get
58
+    @Mapping("treeselect")
59
+    public List<TreeSelect> treeselect(SysMenu menu) {
60
+        Long userId = SecurityUtil.getUserId();
61
+        List<SysMenu> menus = sysMenuService.selectMenuList(menu, userId);
62
+        return sysMenuService.buildMenuTreeSelect(menus);
63
+    }
64
+
65
+    /**
66
+     * 加载对应角色菜单列表树
67
+     */
68
+    @Get
69
+    @Mapping("roleMenuTreeselect/{roleId}")
70
+    public Map<String, Object> roleMenuTreeselect(@Path("roleId") Long roleId) {
71
+        Long userId = SecurityUtil.getUserId();
72
+        List<SysMenu> menus = sysMenuService.selectMenuList(userId);
73
+        Map<String, Object> map = new HashMap<>();
74
+        map.put("checkedKeys", sysMenuService.selectMenuListByRoleId(roleId));
75
+        map.put("menus", sysMenuService.buildMenuTreeSelect(menus));
76
+        return map;
77
+    }
78
+
79
+    /**
80
+     * 新增系统菜单
81
+     */
82
+    @RyLog(title = "系统菜单", businessType = BusinessType.INSERT)
83
+    @AuthPermissions("system:menu:add")
84
+    @Post
85
+    @Mapping
86
+    public Result<Void> add(@Body @Validated SysMenu sysMenu) {
87
+        return toResult(sysMenuService.add(sysMenu));
88
+    }
89
+
90
+    /**
91
+     * 修改系统菜单
92
+     */
93
+    @RyLog(title = "系统菜单", businessType = BusinessType.UPDATE)
94
+    @AuthPermissions("system:menu:edit")
95
+    @Put
96
+    @Mapping
97
+    public Result<Void> edit(@Body @Validated SysMenu sysMenu) {
98
+        return toResult(sysMenuService.edit(sysMenu));
99
+    }
100
+
101
+    /**
102
+     * 删除系统菜单
103
+     */
104
+    @RyLog(title = "系统菜单", businessType = BusinessType.DELETE)
105
+    @AuthPermissions("system:menu:remove")
106
+    @Delete
107
+    @Mapping("{menuId}")
108
+    public Result<Void> delete(@Path Long menuId) {
109
+        return toResult(sysMenuService.delete(menuId));
110
+    }
111
+
112
+    /**
113
+     * 获取路由信息
114
+     * @return
115
+     */
116
+    @Get
117
+    @Mapping("getRouters")
118
+    public List<RouterVo> getRouters() {
119
+        Long userId = SecurityUtil.getUserId();
120
+        List<SysMenu> menus = sysMenuService.selectMenuTreeByUserId(userId);
121
+        return sysMenuService.buildMenus(menus);
122
+    }
123
+
124
+}

+ 87
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java 파일 보기

@@ -0,0 +1,87 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.web.controller.BaseController;
7
+import com.ruoyi.common.web.domain.PageData;
8
+import com.ruoyi.framework.annotation.RyLog;
9
+import com.ruoyi.system.domain.SysNotice;
10
+import com.ruoyi.system.service.ISysNoticeService;
11
+import org.noear.solon.annotation.*;
12
+import org.noear.solon.auth.annotation.AuthPermissions;
13
+import org.noear.solon.core.handle.Result;
14
+import org.noear.solon.validation.annotation.Validated;
15
+
16
+import java.util.Arrays;
17
+
18
+/**
19
+ * 通知公告 操作处理
20
+ * @author ruoyi
21
+ */
22
+@Controller
23
+@Mapping("system/notice")
24
+public class SysNoticeController extends BaseController {
25
+
26
+    @Inject
27
+    ISysNoticeService sysNoticeService;
28
+
29
+    /**
30
+     * 查询通知公告列表
31
+     */
32
+    @AuthPermissions("system:notice:list")
33
+    @Get
34
+    @Mapping("list")
35
+    public PageData<SysNotice> list(Page<SysNotice> page, SysNotice sysNotice) {
36
+        QueryWrapper qw = QueryWrapper.create();
37
+        qw.and(SysNotice::getNoticeTitle).like(sysNotice.getNoticeTitle());
38
+        qw.and(SysNotice::getNoticeType).eq(sysNotice.getNoticeType());
39
+        qw.orderBy(SysNotice::getCreateTime).desc();
40
+        Page<SysNotice> result = sysNoticeService.page(page, qw);
41
+        return getPageData(result);
42
+    }
43
+
44
+    /**
45
+     * 查询通知公告详情
46
+     */
47
+    @AuthPermissions("system:notice:query")
48
+    @Get
49
+    @Mapping("{id}")
50
+    public SysNotice info(@Path Long id) {
51
+        return sysNoticeService.getById(id);
52
+    }
53
+
54
+    /**
55
+     * 新增通知公告
56
+     */
57
+    @RyLog(title = "通知公告", businessType = BusinessType.INSERT)
58
+    @AuthPermissions("system:notice:add")
59
+    @Post
60
+    @Mapping
61
+    public Result<Void> add(@Body @Validated SysNotice sysNotice) {
62
+        return toResult(sysNoticeService.save(sysNotice));
63
+    }
64
+
65
+    /**
66
+     * 修改通知公告
67
+     */
68
+    @RyLog(title = "通知公告", businessType = BusinessType.UPDATE)
69
+    @AuthPermissions("system:notice:edit")
70
+    @Put
71
+    @Mapping
72
+    public Result<Void> edit(@Body @Validated SysNotice sysNotice) {
73
+        return toResult(sysNoticeService.updateById(sysNotice));
74
+    }
75
+
76
+    /**
77
+     * 删除通知公告
78
+     */
79
+    @RyLog(title = "通知公告", businessType = BusinessType.DELETE)
80
+    @AuthPermissions("system:notice:remove")
81
+    @Delete
82
+    @Mapping("{noticeIds}")
83
+    public Result<Void> delete(@Path Long[] noticeIds) {
84
+        return toResult(sysNoticeService.removeByIds(Arrays.asList(noticeIds)));
85
+    }
86
+
87
+}

+ 90
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOperLogController.java 파일 보기

@@ -0,0 +1,90 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.framework.annotation.RyLog;
10
+import com.ruoyi.system.domain.SysOperLog;
11
+import com.ruoyi.system.service.ISysOperLogService;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+
16
+import java.util.Arrays;
17
+import java.util.List;
18
+
19
+/**
20
+ * 操作日志 操作处理
21
+ * @author ruoyi
22
+ */
23
+@Controller
24
+@Mapping("system/operlog")
25
+public class SysOperLogController extends BaseController {
26
+
27
+    @Inject
28
+    ISysOperLogService sysOperLogService;
29
+
30
+    /**
31
+     * 查询操作日志列表
32
+     */
33
+    @AuthPermissions("system:operlog:list")
34
+    @Get
35
+    @Mapping("list")
36
+    public PageData<SysOperLog> list(Page<SysOperLog> page, SysOperLog sysOperLog) {
37
+        QueryWrapper qw = getQW(sysOperLog);
38
+        Page<SysOperLog> result = sysOperLogService.page(page, qw);
39
+        return getPageData(result);
40
+    }
41
+
42
+    /**
43
+     * 导出操作日志列表
44
+     */
45
+    @RyLog(title = "操作日志", businessType = BusinessType.EXPORT)
46
+    @AuthPermissions("system:operlog:export")
47
+    @Post
48
+    @Mapping("export")
49
+    public void export(SysOperLog sysOperLog) {
50
+        QueryWrapper qw = getQW(sysOperLog);
51
+        List<SysOperLog> list = sysOperLogService.list(qw);
52
+        ExcelUtil.export(list);
53
+    }
54
+
55
+    /**
56
+     * 删除操作日志
57
+     */
58
+    @RyLog(title = "操作日志", businessType = BusinessType.DELETE)
59
+    @AuthPermissions("system:operlog:remove")
60
+    @Delete
61
+    @Mapping("{operIds}")
62
+    public Result<Void> remove(@Path String[] operIds) {
63
+        return toResult(sysOperLogService.removeByIds(Arrays.asList(operIds)));
64
+    }
65
+
66
+    /**
67
+     * 清空操作日志
68
+     */
69
+    @RyLog(title = "操作日志", businessType = BusinessType.CLEAN)
70
+    @AuthPermissions("system:operlog:remove")
71
+    @Delete
72
+    @Mapping("clean")
73
+    public Result<Void> clean() {
74
+        sysOperLogService.clean();
75
+        return Result.succeed();
76
+    }
77
+
78
+    private QueryWrapper getQW(SysOperLog sysOperLog) {
79
+        QueryWrapper qw = QueryWrapper.create();
80
+        qw.and(SysOperLog::getTitle).like(sysOperLog.getTitle());
81
+        qw.and(SysOperLog::getBusinessType).eq(sysOperLog.getBusinessType());
82
+        qw.and(SysOperLog::getStatus).eq(sysOperLog.getStatus());
83
+        qw.and(SysOperLog::getOperName).like(sysOperLog.getOperName());
84
+        qw.and(SysOperLog::getCreateTime).ge(sysOperLog.getStartTime());
85
+        qw.and(SysOperLog::getCreateTime).le(sysOperLog.getEndTime());
86
+        qw.orderBy(SysOperLog::getCreateTime).desc();
87
+        return qw;
88
+    }
89
+
90
+}

+ 117
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java 파일 보기

@@ -0,0 +1,117 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.framework.annotation.RyLog;
10
+import com.ruoyi.system.domain.SysPost;
11
+import com.ruoyi.system.service.ISysPostService;
12
+import org.noear.solon.annotation.*;
13
+import org.noear.solon.auth.annotation.AuthPermissions;
14
+import org.noear.solon.core.handle.Result;
15
+import org.noear.solon.validation.annotation.Validated;
16
+
17
+import java.util.Arrays;
18
+import java.util.List;
19
+
20
+/**
21
+ * 岗位 操作处理
22
+ * @author ruoyi
23
+ */
24
+@Controller
25
+@Mapping("system/post")
26
+public class SysPostController extends BaseController {
27
+
28
+    @Inject
29
+    ISysPostService sysPostService;
30
+
31
+    /**
32
+     * 查询岗位列表
33
+     */
34
+    @AuthPermissions("system:post:list")
35
+    @Get
36
+    @Mapping("list")
37
+    public PageData<SysPost> list(Page<SysPost> page, SysPost sysPost) {
38
+        QueryWrapper qw = getQW(sysPost);
39
+        Page<SysPost> result = sysPostService.page(page, qw);
40
+        return getPageData(result);
41
+    }
42
+
43
+    /**
44
+     * 导出岗位列表
45
+     */
46
+    @RyLog(title = "岗位", businessType = BusinessType.EXPORT)
47
+    @AuthPermissions("system:post:export")
48
+    @Post
49
+    @Mapping("export")
50
+    public void export(SysPost sysPost) {
51
+        QueryWrapper qw = getQW(sysPost);
52
+        List<SysPost> list = sysPostService.list(qw);
53
+        ExcelUtil.export(list);
54
+    }
55
+
56
+    /**
57
+     * 查询岗位详情
58
+     */
59
+    @AuthPermissions("system:post:query")
60
+    @Get
61
+    @Mapping("{id}")
62
+    public SysPost info(@Path Long id) {
63
+        return sysPostService.getById(id);
64
+    }
65
+
66
+    /**
67
+     * 新增岗位
68
+     */
69
+    @RyLog(title = "岗位", businessType = BusinessType.INSERT)
70
+    @AuthPermissions("system:post:add")
71
+    @Post
72
+    @Mapping
73
+    public Result<Void> add(@Body @Validated SysPost sysPost) {
74
+        return toResult(sysPostService.add(sysPost));
75
+    }
76
+
77
+    /**
78
+     * 修改岗位
79
+     */
80
+    @RyLog(title = "岗位", businessType = BusinessType.UPDATE)
81
+    @AuthPermissions("system:post:edit")
82
+    @Put
83
+    @Mapping
84
+    public Result<Void> edit(@Body @Validated SysPost sysPost) {
85
+        return toResult(sysPostService.edit(sysPost));
86
+    }
87
+
88
+    /**
89
+     * 删除岗位
90
+     */
91
+    @RyLog(title = "岗位", businessType = BusinessType.DELETE)
92
+    @AuthPermissions("system:post:remove")
93
+    @Delete
94
+    @Mapping("{postIds}")
95
+    public Result<Void> delete(@Path Long[] postIds) {
96
+        sysPostService.delete(Arrays.asList(postIds));
97
+        return Result.succeed();
98
+    }
99
+
100
+    /**
101
+     * 获取岗位选择框列表
102
+     */
103
+    @Get
104
+    @Mapping("optionselect")
105
+    public List<SysPost> optionselect() {
106
+        return sysPostService.list();
107
+    }
108
+
109
+    private QueryWrapper getQW(SysPost sysPost) {
110
+        QueryWrapper qw = QueryWrapper.create();
111
+        qw.and(SysPost::getPostCode).like(sysPost.getPostCode());
112
+        qw.and(SysPost::getPostName).like(sysPost.getPostName());
113
+        qw.and(SysPost::getStatus).eq(sysPost.getStatus());
114
+        return qw;
115
+    }
116
+
117
+}

+ 177
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java 파일 보기

@@ -0,0 +1,177 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.ruoyi.common.constants.UserConstant;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.common.web.domain.entity.SysRole;
10
+import com.ruoyi.framework.annotation.RyDataScope;
11
+import com.ruoyi.framework.annotation.RyLog;
12
+import com.ruoyi.system.domain.SysUserRole;
13
+import com.ruoyi.system.service.ISysRoleService;
14
+import org.noear.solon.annotation.*;
15
+import org.noear.solon.auth.annotation.AuthPermissions;
16
+import org.noear.solon.core.handle.Result;
17
+import org.noear.solon.data.annotation.Transaction;
18
+import org.noear.solon.validation.annotation.Validated;
19
+
20
+import java.util.List;
21
+
22
+/**
23
+ * 角色 操作处理
24
+ * @author ruoyi
25
+ */
26
+@Controller
27
+@Mapping("system/role")
28
+public class SysRoleController extends BaseController {
29
+
30
+    @Inject
31
+    ISysRoleService sysRoleService;
32
+
33
+    /**
34
+     * 查询角色列表
35
+     */
36
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
37
+    @AuthPermissions("system:role:list")
38
+    @Get
39
+    @Mapping("list")
40
+    public PageData<SysRole> list(Page<SysRole> page, SysRole sysRole) {
41
+        startPage(page);
42
+        List<SysRole> list = sysRoleService.selectRoleList(sysRole);
43
+        return getPageData(list);
44
+    }
45
+
46
+    /**
47
+     * 导出角色列表
48
+     */
49
+    @RyLog(title = "角色", businessType = BusinessType.EXPORT)
50
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
51
+    @AuthPermissions("system:role:export")
52
+    @Post
53
+    @Mapping("export")
54
+    public void export(SysRole sysRole) {
55
+        List<SysRole> list = sysRoleService.selectRoleList(sysRole);
56
+        ExcelUtil.export(list);
57
+    }
58
+
59
+    /**
60
+     * 查询角色详情
61
+     */
62
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
63
+    @AuthPermissions("system:role:query")
64
+    @Get
65
+    @Mapping("{id}")
66
+    public SysRole info(@Path Long id, SysRole sysRole) {
67
+        return sysRoleService.info(id, sysRole);
68
+    }
69
+
70
+    /**
71
+     * 新增角色
72
+     */
73
+    @RyLog(title = "角色", businessType = BusinessType.INSERT)
74
+    @AuthPermissions("system:role:add")
75
+    @Transaction
76
+    @Post
77
+    @Mapping
78
+    public Result<Void> add(@Body @Validated SysRole sysRole) {
79
+        return toResult(sysRoleService.add(sysRole));
80
+    }
81
+
82
+    /**
83
+     * 修改角色
84
+     */
85
+    @RyLog(title = "角色", businessType = BusinessType.UPDATE)
86
+    @AuthPermissions("system:role:edit")
87
+    @Transaction
88
+    @Put
89
+    @Mapping
90
+    public Result<Void> edit(@Body @Validated SysRole sysRole) {
91
+        return toResult(sysRoleService.edit(sysRole));
92
+    }
93
+
94
+    /**
95
+     * 修改保存数据权限
96
+     */
97
+    @RyLog(title = "角色", businessType = BusinessType.UPDATE)
98
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
99
+    @AuthPermissions("system:role:edit")
100
+    @Transaction
101
+    @Put
102
+    @Mapping("dataScope")
103
+    public Result<Void> dataScope(@Body SysRole sysRole) {
104
+        return toResult(sysRoleService.dataScope(sysRole));
105
+    }
106
+
107
+    /**
108
+     * 状态修改
109
+     */
110
+    @RyLog(title = "角色", businessType = BusinessType.UPDATE)
111
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
112
+    @AuthPermissions("system:role:edit")
113
+    @Put
114
+    @Mapping("changeStatus")
115
+    public Result<Void> changeStatus(@Body SysRole sysRole) {
116
+        return toResult(sysRoleService.changeStatus(sysRole));
117
+    }
118
+
119
+    /**
120
+     * 删除角色
121
+     */
122
+    @RyLog(title = "角色", businessType = BusinessType.DELETE)
123
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
124
+    @AuthPermissions("system:role:remove")
125
+    @Transaction
126
+    @Delete
127
+    @Mapping("{roleIds}")
128
+    public Result<Void> delete(@Path Long[] roleIds, SysRole sysRole) {
129
+        return toResult(sysRoleService.delete(roleIds, sysRole));
130
+    }
131
+
132
+    /**
133
+     * 获取角色选择框列表
134
+     */
135
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
136
+    @AuthPermissions("system:role:query")
137
+    @Get
138
+    @Mapping("optionselect")
139
+    public List<SysRole> optionselect(SysRole sysRole) {
140
+        return sysRoleService.selectRoleList(sysRole);
141
+    }
142
+
143
+    /**
144
+     * 取消授权用户
145
+     */
146
+    @RyLog(title = "角色", businessType = BusinessType.GRANT)
147
+    @AuthPermissions("system:role:edit")
148
+    @Put
149
+    @Mapping("authUser/cancel")
150
+    public Result<Void> cancelAuthUser(@Body SysUserRole sysUserRole) {
151
+        return toResult(sysRoleService.cancelAuthUser(sysUserRole));
152
+    }
153
+
154
+    /**
155
+     * 批量取消授权用户
156
+     */
157
+    @RyLog(title = "角色", businessType = BusinessType.GRANT)
158
+    @AuthPermissions("system:role:edit")
159
+    @Put
160
+    @Mapping("authUser/cancelAll")
161
+    public Result<Void> cancelAuthUserAll(Long roleId, Long[] userIds) {
162
+        return toResult(sysRoleService.cancelAuthUsers(roleId, userIds));
163
+    }
164
+
165
+    /**
166
+     * 批量选择用户授权
167
+     */
168
+    @RyLog(title = "角色", businessType = BusinessType.GRANT)
169
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT)
170
+    @AuthPermissions("system:role:edit")
171
+    @Put
172
+    @Mapping("authUser/selectAll")
173
+    public Result<Void> selectAuthUserAll(Long roleId, Long[] userIds, SysRole sysRole) {
174
+        return toResult(sysRoleService.insertAuthUsers(roleId, userIds, sysRole));
175
+    }
176
+
177
+}

+ 234
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java 파일 보기

@@ -0,0 +1,234 @@
1
+package com.ruoyi.web.controller.system;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.ruoyi.common.constants.UserConstant;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.utils.ExcelUtil;
7
+import com.ruoyi.common.web.controller.BaseController;
8
+import com.ruoyi.common.web.domain.PageData;
9
+import com.ruoyi.common.web.domain.entity.SysRole;
10
+import com.ruoyi.common.web.domain.entity.SysUser;
11
+import com.ruoyi.framework.annotation.RyDataScope;
12
+import com.ruoyi.framework.annotation.RyLog;
13
+import com.ruoyi.system.service.ISysUserService;
14
+import org.noear.solon.annotation.*;
15
+import org.noear.solon.auth.annotation.AuthPermissions;
16
+import org.noear.solon.core.handle.Result;
17
+import org.noear.solon.data.annotation.Transaction;
18
+import org.noear.solon.validation.annotation.Validated;
19
+
20
+import java.util.List;
21
+import java.util.Map;
22
+
23
+/**
24
+ * 系统用户 操作处理
25
+ * @author ruoyi
26
+ */
27
+@Controller
28
+@Mapping("system/user")
29
+public class SysUserController extends BaseController {
30
+
31
+    @Inject
32
+    ISysUserService sysUserService;
33
+
34
+    /**
35
+     * 查询用户列表
36
+     */
37
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
38
+    @AuthPermissions("system:user:list")
39
+    @Get
40
+    @Mapping("list")
41
+    public PageData<SysUser> list(Page<SysUser> page, SysUser sysUser) {
42
+        startPage(page);
43
+        List<SysUser> list = sysUserService.selectUserList(sysUser);
44
+        return getPageData(list);
45
+    }
46
+
47
+    /**
48
+     * 导出用户列表
49
+     */
50
+    @RyLog(title = "系统用户", businessType = BusinessType.EXPORT)
51
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
52
+    @AuthPermissions("system:user:export")
53
+    @Post
54
+    @Mapping("export")
55
+    public void export(SysUser sysUser) {
56
+        List<SysUser> list = sysUserService.selectUserList(sysUser);
57
+        ExcelUtil.export(list);
58
+    }
59
+
60
+    /**
61
+     * 获取用户详情
62
+     */
63
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
64
+    @AuthPermissions("system:user:query")
65
+    @Get
66
+    @Mapping("{userId}")
67
+    public Map<String, Object> info(@Path Long userId, SysUser sysUser, SysRole sysRole) {
68
+        return sysUserService.info(userId, sysUser, sysRole);
69
+    }
70
+
71
+    /**
72
+     * 获取用户详情
73
+     */
74
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
75
+    @AuthPermissions("system:user:query")
76
+    @Get
77
+    @Mapping
78
+    public Map<String, Object> info(SysUser sysUser, SysRole sysRole) {
79
+        return sysUserService.info(null, sysUser, sysRole);
80
+    }
81
+
82
+    /**
83
+     * 新增用户
84
+     */
85
+    @RyLog(title = "系统用户", businessType = BusinessType.INSERT)
86
+    @AuthPermissions("system:user:add")
87
+    @Transaction
88
+    @Post
89
+    @Mapping
90
+    public Result<Void> add(@Body @Validated SysUser sysUser) {
91
+        return toResult(sysUserService.add(sysUser));
92
+    }
93
+
94
+    /**
95
+     * 修改用户
96
+     */
97
+    @RyLog(title = "系统用户", businessType = BusinessType.UPDATE)
98
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
99
+    @AuthPermissions("system:user:edit")
100
+    @Transaction
101
+    @Put
102
+    @Mapping
103
+    public Result<Void> edit(@Body @Validated SysUser sysUser) {
104
+        return toResult(sysUserService.edit(sysUser));
105
+    }
106
+
107
+    /**
108
+     * 删除用户
109
+     */
110
+    @RyLog(title = "系统用户", businessType = BusinessType.DELETE)
111
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
112
+    @AuthPermissions("system:user:remove")
113
+    @Transaction
114
+    @Delete
115
+    @Mapping("{userIds}")
116
+    public Result<Void> delete(@Path Long[] userIds, SysUser sysUser) {
117
+        return toResult(sysUserService.delete(userIds, sysUser));
118
+    }
119
+
120
+    /**
121
+     * 重置密码
122
+     */
123
+    @RyLog(title = "系统用户", businessType = BusinessType.UPDATE, isSaveRequestData = false)
124
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
125
+    @AuthPermissions("system:user:edit")
126
+    @Put
127
+    @Mapping("resetPwd")
128
+    public Result<Void> resetPwd(@Body SysUser sysUser) {
129
+        return toResult(sysUserService.resetPwd(sysUser));
130
+    }
131
+
132
+    /**
133
+     * 状态修改
134
+     */
135
+    @RyLog(title = "系统用户", businessType = BusinessType.UPDATE)
136
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
137
+    @AuthPermissions("system:user:edit")
138
+    @Put
139
+    @Mapping("changeStatus")
140
+    public Result<Void> changeStatus(@Body SysUser sysUser) {
141
+        return toResult(sysUserService.changeStatus(sysUser));
142
+    }
143
+
144
+    /**
145
+     * 根据用户编号获取授权角色
146
+     */
147
+    @RyLog(title = "系统用户", businessType = BusinessType.GRANT)
148
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
149
+    @AuthPermissions("system:user:query")
150
+    @Get
151
+    @Mapping("authRole/{userId}")
152
+    public Map<String, Object> authRole(@Path Long userId, SysRole sysRole) {
153
+        return sysUserService.authRole(userId, sysRole);
154
+    }
155
+
156
+    /**
157
+     * 用户授权角色
158
+     */
159
+    @RyLog(title = "系统用户", businessType = BusinessType.GRANT)
160
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
161
+    @AuthPermissions("system:user:edit")
162
+    @Put
163
+    @Mapping("authRole")
164
+    public Result<Void> insertAuthRole(Long userId, Long[] roleIds, SysUser sysUser) {
165
+        sysUserService.insertAuthRole(userId, roleIds, sysUser);
166
+        return Result.succeed();
167
+    }
168
+
169
+    /**
170
+     * 查询角色已授权用户列表
171
+     */
172
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
173
+    @AuthPermissions("system:role:list")
174
+    @Get
175
+    @Mapping("authUser/allocatedList")
176
+    public PageData<SysUser> allocatedList(Page<SysUser> page, SysUser sysUser) {
177
+        startPage(page);
178
+        List<SysUser> list = sysUserService.selectAllocatedList(sysUser);
179
+        return getPageData(list);
180
+    }
181
+
182
+    /**
183
+     * 查询角色未授权用户列表
184
+     */
185
+    @RyDataScope(deptAlias = UserConstant.DATA_SCOPE_ALIAS_DEPT, userAlias = UserConstant.DATA_SCOPE_ALIAS_USER)
186
+    @AuthPermissions("system:role:list")
187
+    @Get
188
+    @Mapping("authUser/unallocatedList")
189
+    public PageData<SysUser> unallocatedList(Page<SysUser> page, SysUser sysUser) {
190
+        startPage(page);
191
+        List<SysUser> list = sysUserService.selectUnallocatedList(sysUser);
192
+        return getPageData(list);
193
+    }
194
+
195
+    /**
196
+     * 个人中心 - 查询个人信息
197
+     */
198
+    @Get
199
+    @Mapping("profile")
200
+    public Map<String, Object> profile() {
201
+        return sysUserService.profile();
202
+    }
203
+
204
+    /**
205
+     * 个人中心 - 修改用户
206
+     */
207
+    @RyLog(title = "个人中心", businessType = BusinessType.UPDATE)
208
+    @Put
209
+    @Mapping("profile")
210
+    public Result<Void> updateProfile(@Body SysUser sysUser) {
211
+        return toResult(sysUserService.updateProfile(sysUser));
212
+    }
213
+
214
+    /**
215
+     * 个人中心 - 修改密码
216
+     */
217
+    @RyLog(title = "个人中心", businessType = BusinessType.UPDATE, isSaveRequestData = false)
218
+    @Put
219
+    @Mapping("profile/updatePwd")
220
+    public Result<Void> updateProfilePwd(String oldPassword, String newPassword) {
221
+        return toResult(sysUserService.updateProfilePwd(oldPassword, newPassword));
222
+    }
223
+
224
+    /**
225
+     * 个人中心 - 修改头像
226
+     */
227
+    @RyLog(title = "个人中心", businessType = BusinessType.UPDATE)
228
+    @Put
229
+    @Mapping("profile/avatar")
230
+    public Result<Void> updateProfileAvatar(String avatar) {
231
+        return toResult(sysUserService.updateProfileAvatar(avatar));
232
+    }
233
+
234
+}

+ 32
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/FileController.java 파일 보기

@@ -0,0 +1,32 @@
1
+package com.ruoyi.web.controller.tool;
2
+
3
+import com.ruoyi.common.utils.FileUtil;
4
+import com.ruoyi.framework.config.FileConfig;
5
+import org.noear.solon.annotation.Controller;
6
+import org.noear.solon.annotation.Inject;
7
+import org.noear.solon.annotation.Mapping;
8
+import org.noear.solon.annotation.Post;
9
+import org.noear.solon.core.handle.Result;
10
+import org.noear.solon.core.handle.UploadedFile;
11
+
12
+/**
13
+ * 文件 操作处理
14
+ * @author ruoyi
15
+ */
16
+@Controller
17
+@Mapping("tool/file")
18
+public class FileController {
19
+
20
+    @Inject
21
+    FileConfig fileConfig;
22
+
23
+    /**
24
+     * 单文件上传
25
+     */
26
+    @Post
27
+    @Mapping("upload")
28
+    public Result<String> upload(UploadedFile file) {
29
+        return Result.succeed(FileUtil.upload(file, fileConfig.getMaxSize(), fileConfig.getFileType(), fileConfig.getSavePath(), fileConfig.getRequestPrefix()));
30
+    }
31
+
32
+}

+ 150
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/GenTableController.java 파일 보기

@@ -0,0 +1,150 @@
1
+package com.ruoyi.web.controller.tool;
2
+
3
+import com.mybatisflex.core.paginate.Page;
4
+import com.mybatisflex.core.query.QueryWrapper;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.web.controller.BaseController;
7
+import com.ruoyi.common.web.domain.PageData;
8
+import com.ruoyi.framework.annotation.RyLog;
9
+import com.ruoyi.gen.domain.GenTable;
10
+import com.ruoyi.gen.service.IGenTableService;
11
+import org.noear.solon.annotation.*;
12
+import org.noear.solon.auth.annotation.AuthPermissions;
13
+import org.noear.solon.core.handle.Result;
14
+import org.noear.solon.data.annotation.Transaction;
15
+import org.noear.solon.validation.annotation.Validated;
16
+
17
+import java.util.List;
18
+import java.util.Map;
19
+
20
+/**
21
+ * 代码生成 操作处理
22
+ * @author ruoyi
23
+ */
24
+@Controller
25
+@Mapping("tool/gen")
26
+public class GenTableController extends BaseController {
27
+
28
+    @Inject
29
+    IGenTableService genTableService;
30
+
31
+    /**
32
+     * 查询数据库列表
33
+     */
34
+    @AuthPermissions("tool:gen:list")
35
+    @Get
36
+    @Mapping("tables")
37
+    public PageData<GenTable> tables(Page<GenTable> page, GenTable genTable) {
38
+        startPage(page);
39
+        List<GenTable> list = genTableService.tables(genTable);
40
+        return getPageData(list);
41
+    }
42
+
43
+    /**
44
+     * 查询代码生成列表
45
+     */
46
+    @AuthPermissions("tool:gen:list")
47
+    @Get
48
+    @Mapping("list")
49
+    public PageData<GenTable> list(Page<GenTable> page, GenTable genTable) {
50
+        QueryWrapper qw = QueryWrapper.create();
51
+        qw.and(GenTable::getTableName).like(genTable.getTableName());
52
+        qw.and(GenTable::getTableComment).like(genTable.getTableComment());
53
+        Page<GenTable> result = genTableService.page(page, qw);
54
+        return getPageData(result);
55
+    }
56
+
57
+    /**
58
+     * 查询代码生成详情
59
+     */
60
+    @AuthPermissions("tool:gen:query")
61
+    @Get
62
+    @Mapping("{tableId}")
63
+    public Map<String, Object> info(@Path Long tableId) {
64
+        return genTableService.info(tableId);
65
+    }
66
+
67
+    /**
68
+     * 预览代码生成
69
+     */
70
+    @AuthPermissions("tool:gen:preview")
71
+    @Get
72
+    @Mapping("preview/{tableId}")
73
+    public Map<String, String> preview(@Path Long tableId) {
74
+        return genTableService.preview(tableId);
75
+    }
76
+
77
+    /**
78
+     * 新增代码生成(导入表)
79
+     */
80
+    @RyLog(title = "代码生成", businessType = BusinessType.INSERT)
81
+    @AuthPermissions("tool:gen:add")
82
+    @Transaction
83
+    @Post
84
+    @Mapping
85
+    public Result<Void> add(String tables) {
86
+        genTableService.add(tables);
87
+        return Result.succeed();
88
+    }
89
+
90
+    /**
91
+     * 修改代码生成
92
+     */
93
+    @RyLog(title = "代码生成", businessType = BusinessType.UPDATE)
94
+    @AuthPermissions("tool:gen:edit")
95
+    @Transaction
96
+    @Put
97
+    @Mapping
98
+    public Result<Void> edit(@Body @Validated GenTable genTable) {
99
+        return toResult(genTableService.edit(genTable));
100
+    }
101
+
102
+    /**
103
+     * 删除代码生成
104
+     */
105
+    @RyLog(title = "代码生成", businessType = BusinessType.DELETE)
106
+    @AuthPermissions("tool:gen:remove")
107
+    @Transaction
108
+    @Delete
109
+    @Mapping("{tableIds}")
110
+    public Result<Void> delete(@Path Long[] tableIds) {
111
+        genTableService.delete(tableIds);
112
+        return Result.succeed();
113
+    }
114
+
115
+    /**
116
+     * 同步数据库
117
+     */
118
+    @RyLog(title = "代码生成", businessType = BusinessType.UPDATE)
119
+    @AuthPermissions("tool:gen:edit")
120
+    @Get
121
+    @Mapping("synchDb/{tableName}")
122
+    public Result<Void> synchDb(@Path String tableName) {
123
+        genTableService.synchDb(tableName);
124
+        return Result.succeed();
125
+    }
126
+
127
+    /**
128
+     * 生成代码(自定义路径)
129
+     */
130
+    @RyLog(title = "代码生成", businessType = BusinessType.GENCODE)
131
+    @AuthPermissions("tool:gen:code")
132
+    @Get
133
+    @Mapping("genCode/{tableName}")
134
+    public Result<Void> genCode(@Path String tableName) {
135
+        genTableService.genCode(tableName);
136
+        return Result.succeed();
137
+    }
138
+
139
+    /**
140
+     * 批量生成代码
141
+     */
142
+    @RyLog(title = "代码生成", businessType = BusinessType.GENCODE)
143
+    @AuthPermissions("tool:gen:code")
144
+    @Get
145
+    @Mapping("batchGenCode")
146
+    public void batchGenCode(String tables) {
147
+        genTableService.batchGenCode(tables);
148
+    }
149
+
150
+}

+ 186
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/JobController.java 파일 보기

@@ -0,0 +1,186 @@
1
+package com.ruoyi.web.controller.tool;
2
+
3
+import cn.hutool.core.util.StrUtil;
4
+import com.mybatisflex.core.paginate.Page;
5
+import com.ruoyi.common.enums.BusinessType;
6
+import com.ruoyi.common.enums.DictEnum;
7
+import com.ruoyi.common.utils.ExcelUtil;
8
+import com.ruoyi.common.web.controller.BaseController;
9
+import com.ruoyi.common.web.domain.PageData;
10
+import com.ruoyi.framework.annotation.RyLog;
11
+import com.ruoyi.schedule.domain.JobTriggers;
12
+import com.ruoyi.schedule.domain.SysJob;
13
+import org.noear.solon.annotation.*;
14
+import org.noear.solon.auth.annotation.AuthPermissions;
15
+import org.noear.solon.core.handle.Result;
16
+import org.noear.solon.scheduling.annotation.Scheduled;
17
+import org.noear.solon.scheduling.scheduled.JobHolder;
18
+import org.noear.solon.scheduling.scheduled.manager.IJobManager;
19
+import org.quartz.*;
20
+import org.quartz.impl.matchers.GroupMatcher;
21
+
22
+import java.util.*;
23
+import java.util.stream.Collectors;
24
+
25
+/**
26
+ * 定时任务 操作处理
27
+ * @author ruoyi
28
+ */
29
+@Controller
30
+@Mapping("tool/job")
31
+public class JobController extends BaseController {
32
+
33
+    @Inject
34
+    IJobManager jobManager;
35
+
36
+    @Inject
37
+    Scheduler scheduler;
38
+
39
+    /**
40
+     * 查询定时任务列表
41
+     */
42
+    @AuthPermissions("tool:job:list")
43
+    @Get
44
+    @Mapping("list")
45
+    public PageData<SysJob> list(Page<SysJob> page, SysJob sysJob) {
46
+        List<SysJob> sysJobList = getList(sysJob);
47
+        // 分页
48
+        List<SysJob> list = sysJobList.stream()
49
+                .skip((page.getPageNumber() - 1) * page.getPageSize())
50
+                .limit(page.getPageSize())
51
+                .collect(Collectors.toList());
52
+        return getPageData(list).total(sysJobList.size());
53
+    }
54
+
55
+    /**
56
+     * 导出定时任务列表
57
+     */
58
+    @RyLog(title = "定时任务", businessType = BusinessType.EXPORT)
59
+    @AuthPermissions("tool:job:export")
60
+    @Post
61
+    @Mapping("export")
62
+    public void export(SysJob sysJob) {
63
+        List<SysJob> sysJobList = getList(sysJob);
64
+        ExcelUtil.export(sysJobList);
65
+    }
66
+
67
+    /**
68
+     * 查询定时任务详情
69
+     */
70
+    @AuthPermissions("tool:job:query")
71
+    @Get
72
+    @Mapping("{jobName}")
73
+    public SysJob info(@Path String jobName) {
74
+        JobHolder jobHolder = jobManager.jobGet(jobName);
75
+        List<JobTriggers> jobTriggersList = getJobTriggers();
76
+        return toSysJob(jobHolder, jobTriggersList);
77
+    }
78
+
79
+    /**
80
+     * 状态修改
81
+     */
82
+    @RyLog(title = "定时任务", businessType = BusinessType.UPDATE)
83
+    @AuthPermissions("tool:job:changeStatus")
84
+    @Put
85
+    @Mapping("changeStatus")
86
+    public Result<Void> changeStatus(@Body SysJob sysJob) {
87
+        if(!jobManager.jobExists(sysJob.getJobName())) {
88
+            return Result.failure("任务不存在!");
89
+        }
90
+        JobHolder jobHolder = jobManager.jobGet(sysJob.getJobName());
91
+        if(DictEnum.SYS_JOB_STATUS.OK.getValue().equals(sysJob.getStatus())) {
92
+            jobManager.jobStart(sysJob.getJobName(), null);
93
+        } else {
94
+            jobManager.jobStop(sysJob.getJobName());
95
+        }
96
+        return Result.succeed();
97
+    }
98
+
99
+    /**
100
+     * 删除定时任务
101
+     */
102
+    @RyLog(title = "定时任务", businessType = BusinessType.DELETE)
103
+    @AuthPermissions("tool:job:remove")
104
+    @Delete
105
+    @Mapping("{jobNames}")
106
+    public Result<Void> delete(@Path String[] jobNames) {
107
+        for (String jobName : jobNames) {
108
+            jobManager.jobRemove(jobName);
109
+        }
110
+        return Result.succeed();
111
+    }
112
+
113
+    private List<SysJob> getList(SysJob sysJob) {
114
+        Map<String, JobHolder> jobHolderMap = jobManager.jobGetAll();
115
+        List<SysJob> sysJobs = new ArrayList<>();
116
+        List<JobTriggers> jobTriggersList = getJobTriggers();
117
+        for (Map.Entry<String, JobHolder> entry : jobHolderMap.entrySet()) {
118
+            sysJobs.add(toSysJob(entry.getValue(), jobTriggersList));
119
+        }
120
+        // 根据查询条件检索
121
+        return sysJobs.stream()
122
+                .filter(job -> StrUtil.isEmpty(sysJob.getJobName()) || job.getJobName().equals(sysJob.getJobName()))
123
+                .filter(job -> StrUtil.isEmpty(sysJob.getJobSimpleName()) || job.getJobSimpleName().equals(sysJob.getJobSimpleName()))
124
+                .filter(job -> StrUtil.isEmpty(sysJob.getStatus()) || job.getStatus().equals(sysJob.getStatus()))
125
+                .collect(Collectors.toList());
126
+    }
127
+
128
+    private SysJob toSysJob(JobHolder jobHolder, List<JobTriggers> jobTriggersList) {
129
+        Scheduled scheduled = jobHolder.getScheduled();
130
+        SysJob sysJob = new SysJob();
131
+        sysJob.setJobName(jobHolder.getName());
132
+        sysJob.setJobSimpleName(jobHolder.getSimpleName());
133
+        sysJob.setCronExpression(StrUtil.isNotEmpty(scheduled.cron()) ? scheduled.cron() : String.valueOf(scheduled.fixedRate()));
134
+        sysJob.setStatus(DictEnum.SYS_JOB_STATUS.PAUSE.getValue());
135
+        // 匹配当前 Job  TODO 按照名称 + 分组匹配
136
+        Optional<JobTriggers> optionalJobTriggers = jobTriggersList.stream().filter(jobTriggers -> jobHolder.getName().equals(jobTriggers.getJobKey().getName())).findFirst();
137
+        if(optionalJobTriggers.isPresent()) {
138
+            JobTriggers jobTriggers = optionalJobTriggers.get();
139
+            sysJob.setJobGroup(jobTriggers.getJobKey().getGroup());
140
+            List<JobTriggers.TriggerOfJob> triggersOfJob = jobTriggers.getTriggersOfJob();
141
+            if(!triggersOfJob.isEmpty()) {
142
+                // Job和触发器 Trigger目前是一对一
143
+                JobTriggers.TriggerOfJob triggerOfJob = triggersOfJob.get(0);
144
+                if(triggerOfJob.getTriggerState() == Trigger.TriggerState.NORMAL) {
145
+                    sysJob.setStatus(DictEnum.SYS_JOB_STATUS.OK.getValue());
146
+                }
147
+                Trigger trigger = triggerOfJob.getTrigger();
148
+                sysJob.setStartTime(trigger.getStartTime());
149
+                sysJob.setEndTime(trigger.getEndTime());
150
+                sysJob.setNextFireTime(trigger.getNextFireTime());
151
+                sysJob.setPreviousFireTime(trigger.getPreviousFireTime());
152
+            }
153
+        }
154
+        return sysJob;
155
+    }
156
+
157
+    private List<JobTriggers> getJobTriggers() {
158
+        List<JobTriggers> list = new ArrayList<>();
159
+        try {
160
+            // 查询所有的 JobKey
161
+            Set<JobKey> jobKeys = scheduler.getJobKeys(GroupMatcher.anyJobGroup());
162
+            if(!jobKeys.isEmpty()) {
163
+                for (JobKey jobKey : jobKeys) {
164
+                    JobTriggers jobTriggers = new JobTriggers();
165
+                    jobTriggers.setJobKey(jobKey);
166
+                    // 查询当前 Job的触发器(也就是 Trigger。同一个 Job可以有多个 Trigger)
167
+                    List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
168
+                    List<JobTriggers.TriggerOfJob> triggersOfJob = new ArrayList<>();
169
+                    for (Trigger trigger : triggers) {
170
+                        JobTriggers.TriggerOfJob triggerOfJob = jobTriggers.new TriggerOfJob();
171
+                        // 查询触发器状态
172
+                        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
173
+                        triggerOfJob.setTrigger(trigger);
174
+                        triggerOfJob.setTriggerState(triggerState);
175
+                        triggersOfJob.add(triggerOfJob);
176
+                    }
177
+                    jobTriggers.setTriggersOfJob(triggersOfJob);
178
+                    list.add(jobTriggers);
179
+                }
180
+            }
181
+        } catch (SchedulerException ignored) {
182
+        }
183
+        return list;
184
+    }
185
+
186
+}

+ 90
- 0
cmc-temperature-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SysJobLogController.java 파일 보기

@@ -0,0 +1,90 @@
1
+package com.ruoyi.web.controller.tool;
2
+
3
+import com.ruoyi.framework.annotation.RyLog;
4
+import com.ruoyi.schedule.domain.SysJobLog;
5
+import com.ruoyi.schedule.service.ISysJobLogService;
6
+import org.noear.solon.annotation.*;
7
+import org.noear.solon.auth.annotation.AuthPermissions;
8
+import org.noear.solon.core.handle.Result;
9
+import com.mybatisflex.core.query.QueryWrapper;
10
+import com.ruoyi.common.enums.BusinessType;
11
+import com.ruoyi.common.utils.ExcelUtil;
12
+import com.ruoyi.common.web.controller.BaseController;
13
+import com.mybatisflex.core.paginate.Page;
14
+import com.ruoyi.common.web.domain.PageData;
15
+
16
+import java.util.Arrays;
17
+import java.util.List;
18
+
19
+/**
20
+ * 定时任务调度日志 操作处理
21
+ * @author ruoyi
22
+ */
23
+@Controller
24
+@Mapping("tool/jobLog")
25
+public class SysJobLogController extends BaseController {
26
+
27
+    @Inject
28
+    ISysJobLogService sysJobLogService;
29
+
30
+    /**
31
+     * 查询定时任务调度日志列表
32
+     */
33
+    @AuthPermissions("tool:job:list")
34
+    @Get
35
+    @Mapping("list")
36
+    public PageData<SysJobLog> list(Page<SysJobLog> page, SysJobLog sysJobLog) {
37
+        QueryWrapper qw = getQW(sysJobLog);
38
+        Page<SysJobLog> result = sysJobLogService.page(page, qw);
39
+        return getPageData(result);
40
+    }
41
+
42
+    /**
43
+     * 导出定时任务调度日志列表
44
+     */
45
+    @RyLog(title = "定时任务调度日志", businessType = BusinessType.EXPORT)
46
+    @AuthPermissions("tool:job:export")
47
+    @Post
48
+    @Mapping("export")
49
+    public void export(SysJobLog sysJobLog) {
50
+        QueryWrapper qw = getQW(sysJobLog);
51
+        List<SysJobLog> list = sysJobLogService.list(qw);
52
+        ExcelUtil.export(list);
53
+    }
54
+
55
+    /**
56
+     * 删除定时任务调度日志
57
+     */
58
+    @RyLog(title = "定时任务调度日志", businessType = BusinessType.DELETE)
59
+    @AuthPermissions("tool:job:remove")
60
+    @Delete
61
+    @Mapping("{jobLogIds}")
62
+    public Result<Void> delete(@Path Long[] jobLogIds) {
63
+        return toResult(sysJobLogService.removeByIds(Arrays.asList(jobLogIds)));
64
+    }
65
+
66
+    /**
67
+     * 清空定时任务调度日志
68
+     */
69
+    @RyLog(title = "定时任务调度日志", businessType = BusinessType.CLEAN)
70
+    @AuthPermissions("tool:job:remove")
71
+    @Delete
72
+    @Mapping("clean")
73
+    public Result<Void> clean() {
74
+        sysJobLogService.clean();
75
+        return Result.succeed();
76
+    }
77
+
78
+    private QueryWrapper getQW(SysJobLog sysJobLog) {
79
+        QueryWrapper qw = QueryWrapper.create();
80
+        qw.and(SysJobLog::getJobName).like(sysJobLog.getJobName());
81
+        qw.and(SysJobLog::getJobSimpleName).like(sysJobLog.getJobSimpleName());
82
+        qw.and(SysJobLog::getJobGroup).eq(sysJobLog.getJobGroup());
83
+        qw.and(SysJobLog::getStatus).eq(sysJobLog.getStatus());
84
+        qw.and(SysJobLog::getCreateTime).ge(sysJobLog.getStartTime());
85
+        qw.and(SysJobLog::getCreateTime).le(sysJobLog.getEndTime());
86
+        qw.orderBy(SysJobLog::getCreateTime).desc();
87
+        return qw;
88
+    }
89
+
90
+}

+ 240
- 0
cmc-temperature-back/ruoyi-admin/src/main/resources/app-dev.yml 파일 보기

@@ -0,0 +1,240 @@
1
+ruoyi:
2
+  # 安全配置
3
+  security:
4
+    # IP黑名单
5
+    ips:
6
+      - 1.1.1.1
7
+    # 放行白名单
8
+    whites:
9
+      - /captcha
10
+      - /login
11
+      - /logout
12
+      - /register
13
+      - /solon-admin/**
14
+      - /healthz
15
+      - /doc.html
16
+      - /swagger-resources
17
+      - /swagger/*
18
+      - /webjars/js/**
19
+      - /webjars/css/**
20
+  # XSS配置
21
+  xss:
22
+    # 过滤开关
23
+    enabled: true
24
+    # 排除路径
25
+    excludes:
26
+#      - /system/notice
27
+  # 验证码配置
28
+  captcha:
29
+    # 验证码开关
30
+    enabled: true
31
+    # 干扰类型: line 线段干扰、circle 圆圈干扰、shear 扭曲干扰
32
+    invadeType: line
33
+    # 验证码类型: math 四则运算、char 字符
34
+    type: math
35
+  # 登录配置
36
+  login:
37
+    # 登录失败最大次数
38
+    errorCount: 5
39
+    # 登录失败达最大次数后的锁定时长(单位:分钟)
40
+    lockTime: 10
41
+  # 代码生成配置
42
+  gen:
43
+    # 作者
44
+    author: ruoyi
45
+    # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
46
+    packageName: com.ruoyi.system
47
+    # 自动去除表前缀,默认是false
48
+    autoRemovePre: false
49
+    # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
50
+    tablePrefix: demo_
51
+    # 忽略的表前缀(不会查询这些前缀的表)
52
+    ignoreTablePrefix: [qrtz_, gen_, sys_]
53
+  # 文件配置
54
+  file:
55
+    # 允许上传的文件大小(单位:MB,设为-1不限制)
56
+    maxSize: 2
57
+    # 允许上传的文件类型
58
+    fileType: [jpg, jpeg, png, doc, docx, xls, xlsx, ppt, txt, pdf, zip]
59
+    # 本地保存路径
60
+    savePath: D:/ruoyi/uploadPath
61
+    # 本地文件请求路径前缀
62
+    requestPrefix: http://localhost:90/ruoyi-file
63
+
64
+server:
65
+  request:
66
+    # 设定最大的请求包大小(或表单项的值大小,默认:2M)
67
+    maxBodySize: 2mb
68
+    # 最大的上传文件大小(默认使用 maxBodySize 配置值)
69
+    maxFileSize: 5mb
70
+    # 最大的请求头大小(默认:8k)
71
+    maxHeaderSize: 8kb
72
+    # 请求体编码
73
+    encoding: utf-8
74
+  response:
75
+    # 响应体编码
76
+    encoding: utf-8
77
+
78
+solon:
79
+  # 序列化
80
+  serialization:
81
+    json:
82
+      dateAsFormat: yyyy-MM-dd HH:mm:ss # 配置日期格式(默认输出为时间戳)
83
+      dateAsTimeZone: GMT+8 # 配置时区
84
+#      dateAsTicks: false # 将date转为毫秒数(和 dateAsFormat 二选一)
85
+      longAsString: true # 将long型转为字符串输出(默认为false)
86
+      boolAsInt: false   # 将bool型转为字符串输出(默认为false)
87
+      nullStringAsEmpty: false
88
+      nullBoolAsFalse: false
89
+      nullNumberAsZero: false
90
+      nullArrayAsEmpty: false
91
+      nullAsWriteable: false # 输出所有null值
92
+      enumAsName: false # 枚举使用名字
93
+  # 监控服务端配置
94
+  admin:
95
+    server:
96
+      # 心跳速率,单位:毫秒
97
+      heartbeatInterval: 10000
98
+      # 客户端监控周期,单位:毫秒
99
+      clientMonitorPeriod: 5000
100
+      # 连接超时,单位:毫秒
101
+      connectTimeout: 5000
102
+      # 读取超时,单位:毫秒
103
+      readTimeout: 5000
104
+      # 界面路径(自定义时要以'/'结尾)
105
+      uiPath: /solon-admin/
106
+      # 基础签权(可以多个)
107
+      basicAuth:
108
+        admin: 123456
109
+  # 监控客户端配置
110
+  client:
111
+    # 令牌:监视接口的安全控制
112
+    token: 3C41D632-A070-060C-40D2-6D84B3C07094
113
+    # 连接超时,单位:毫秒
114
+    connectTimeout: 5000
115
+    # 读取超时,单位:毫秒
116
+    readTimeout: 5000
117
+    # 是否向服务端发送敏感信息,如环境变量等
118
+    showSecretInformation: false
119
+  # 监控项配置
120
+  health:
121
+    # 可选: *、disk、cpu、jvm、memory、os、qps(多个用,分隔)
122
+    detector: "*"
123
+  # 接口文档
124
+  docs:
125
+    routes:
126
+      - id: openapi
127
+        groupName: 系统接口
128
+        info:
129
+          title: 接口文档
130
+          description: 在线API文档
131
+#          termsOfService: https://gitee.com/noear/solon
132
+          contact:
133
+            name: ruoyi
134
+          version: 1.0
135
+        schemes:
136
+          - HTTP
137
+          - HTTPS
138
+        globalResponseInData: true
139
+        globalResult: org.noear.solon.core.handle.Result
140
+        apis:
141
+          - basePackage: com.ruoyi.web.controller
142
+
143
+sa-token:
144
+  # token名称(同时也是 cookie名称)
145
+  token-name: Authorization
146
+  # token前缀
147
+  token-prefix: Bearer
148
+  # token有效期(单位:秒) 默认30天,-1 代表永久有效
149
+  timeout: 2592000
150
+  # token临时有效期 (指定时间内无操作就视为token过期,单位:秒),默认-1 代表不限制,永不冻结
151
+  active-timeout: -1
152
+  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
153
+  is-concurrent: false
154
+  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
155
+  is-share: true
156
+  # token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
157
+  token-style: uuid
158
+  # 是否输出操作日志
159
+  is-log: true
160
+
161
+# mybatis-flex 数据源及 mybatis配置
162
+mybatis-flex:
163
+  # 动态数据源
164
+  datasource:
165
+    master:
166
+      type: com.zaxxer.hikari.HikariDataSource
167
+      driverClassName: org.sqlite.JDBC
168
+      jdbcUrl: jdbc:sqlite::resource:static/cmc-temperature.db?date_string_format=yyyy-MM-dd HH:mm:ss
169
+      username:
170
+      password:
171
+#      type: com.zaxxer.hikari.HikariDataSource
172
+#      driverClassName: com.mysql.cj.jdbc.Driver
173
+#      jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
174
+#      username: root
175
+#      password:
176
+#    slave_1:
177
+#      type: com.zaxxer.hikari.HikariDataSource
178
+#      driverClassName: com.mysql.cj.jdbc.Driver
179
+#      jdbcUrl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
180
+#      username: root
181
+#      password:
182
+  # 实体扫描
183
+  type-aliases-package:
184
+    - com.ruoyi.system.domain.*
185
+  # mapper扫描
186
+  mapper-locations:
187
+    # 如果没有对应 xml文件的 mapper,必须配置一下 mapper的扫描路径
188
+#    - com.ruoyi.system.mapper.*
189
+    # 如果有 xml文件,只需要配置 xml文件的扫描路径,xml对应的 mapper会自动关联进去
190
+    - classpath:mapper/**/*.xml
191
+  # Mybatis 的扩展配置
192
+  configuration:
193
+    cacheEnabled: false
194
+    mapUnderscoreToCamelCase: true
195
+  # Mybatis-Flex 的全局配置
196
+  global-config:
197
+    print-banner: true
198
+    # 不配置逻辑删除字段将会真删除
199
+    logic-delete-column: del_flag
200
+    # 主键配置
201
+    key-config:
202
+      # Auto自增
203
+      key-type: Auto
204
+      # value:
205
+
206
+# Redis配置
207
+redis:
208
+  cache_source:
209
+    config: |
210
+      singleServerConfig:
211
+        address: redis://127.0.0.1:6379
212
+        password:
213
+        database: 7
214
+      codec: !<org.redisson.codec.JsonJacksonCodec> {}
215
+
216
+# 分页插件配置
217
+pagehelper:
218
+  offsetAsPageNum: true
219
+  rowBoundsWithCount: true
220
+  pageSizeZero: false
221
+  reasonable: true
222
+  params: pageNum=pageHelperStart;pageSize=pageHelperRows;
223
+  supportMethodsArguments: false
224
+
225
+# 接口文档配置
226
+knife4j:
227
+  # 开启增强配置
228
+  enable: true
229
+  # 开启生产环境屏蔽
230
+  production: false
231
+  # 签权
232
+  basic:
233
+    enable: true
234
+    username: admin
235
+    password: 123456
236
+  # 前端UI的个性化配置
237
+  setting:
238
+    enableVersion: true
239
+    enableOpenApi: false
240
+    enableFooter: false

+ 235
- 0
cmc-temperature-back/ruoyi-admin/src/main/resources/app-prod.yml 파일 보기

@@ -0,0 +1,235 @@
1
+ruoyi:
2
+  # 安全配置
3
+  security:
4
+    # IP黑名单
5
+    ips:
6
+      - 1.1.1.1
7
+    # 放行白名单
8
+    whites:
9
+      - /captcha
10
+      - /login
11
+      - /logout
12
+      - /register
13
+      - /solon-admin/**
14
+      - /healthz
15
+      - /doc.html
16
+      - /swagger-resources
17
+      - /swagger/*
18
+      - /webjars/js/**
19
+      - /webjars/css/**
20
+  # XSS配置
21
+  xss:
22
+    # 过滤开关
23
+    enabled: true
24
+    # 排除路径
25
+    excludes:
26
+#      - /system/notice
27
+  # 验证码配置
28
+  captcha:
29
+    # 验证码开关
30
+    enabled: true
31
+    # 干扰类型: line 线段干扰、circle 圆圈干扰、shear 扭曲干扰
32
+    invadeType: line
33
+    # 验证码类型: math 四则运算、char 字符
34
+    type: math
35
+  # 登录配置
36
+  login:
37
+    # 登录失败最大次数
38
+    errorCount: 5
39
+    # 登录失败达最大次数后的锁定时长(单位:分钟)
40
+    lockTime: 10
41
+  # 代码生成配置
42
+  gen:
43
+    # 作者
44
+    author: ruoyi
45
+    # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool
46
+    packageName: com.ruoyi.system
47
+    # 自动去除表前缀,默认是false
48
+    autoRemovePre: false
49
+    # 表前缀(生成类名不会包含表前缀,多个用逗号分隔)
50
+    tablePrefix: demo_
51
+    # 忽略的表前缀(不会查询这些前缀的表)
52
+    ignoreTablePrefix: [qrtz_, gen_, sys_]
53
+  # 文件配置
54
+  file:
55
+    # 允许上传的文件大小(单位:MB,设为-1不限制)
56
+    maxSize: 2
57
+    # 允许上传的文件类型
58
+    fileType: [jpg, jpeg, png, doc, docx, xls, xlsx, ppt, txt, pdf, zip]
59
+    # 本地保存路径
60
+    savePath: C:\Users\ruoyi\Desktop
61
+    # 本地文件请求路径前缀
62
+    requestPrefix: http://localhost:90/ruoyi-file
63
+
64
+server:
65
+  request:
66
+    # 设定最大的请求包大小(或表单项的值大小,默认:2M)
67
+    maxBodySize: 2mb
68
+    # 最大的上传文件大小(默认使用 maxBodySize 配置值)
69
+    maxFileSize: 5mb
70
+    # 最大的请求头大小(默认:8k)
71
+    maxHeaderSize: 8kb
72
+    # 请求体编码
73
+    encoding: utf-8
74
+  response:
75
+    # 响应体编码
76
+    encoding: utf-8
77
+
78
+solon:
79
+  # 序列化
80
+  serialization:
81
+    json:
82
+      dateAsFormat: yyyy-MM-dd HH:mm:ss # 配置日期格式(默认输出为时间戳)
83
+      dateAsTimeZone: GMT+8 # 配置时区
84
+#      dateAsTicks: false # 将date转为毫秒数(和 dateAsFormat 二选一)
85
+      longAsString: true # 将long型转为字符串输出(默认为false)
86
+      boolAsInt: false   # 将bool型转为字符串输出(默认为false)
87
+      nullStringAsEmpty: false
88
+      nullBoolAsFalse: false
89
+      nullNumberAsZero: false
90
+      nullArrayAsEmpty: false
91
+      nullAsWriteable: false # 输出所有null值
92
+      enumAsName: false # 枚举使用名字
93
+  # 监控服务端配置
94
+  admin:
95
+    server:
96
+      # 心跳速率,单位:毫秒
97
+      heartbeatInterval: 10000
98
+      # 客户端监控周期,单位:毫秒
99
+      clientMonitorPeriod: 5000
100
+      # 连接超时,单位:毫秒
101
+      connectTimeout: 5000
102
+      # 读取超时,单位:毫秒
103
+      readTimeout: 5000
104
+      # 界面路径(自定义时要以'/'结尾)
105
+      uiPath: /solon-admin/
106
+      # 基础签权(可以多个)
107
+      basicAuth:
108
+        admin: 123456
109
+  # 监控客户端配置
110
+  client:
111
+    # 令牌:监视接口的安全控制
112
+    token: 3C41D632-A070-060C-40D2-6D84B3C07094
113
+    # 连接超时,单位:毫秒
114
+    connectTimeout: 5000
115
+    # 读取超时,单位:毫秒
116
+    readTimeout: 5000
117
+    # 是否向服务端发送敏感信息,如环境变量等
118
+    showSecretInformation: false
119
+  # 监控项配置
120
+  health:
121
+    # 可选: *、disk、cpu、jvm、memory、os、qps(多个用,分隔)
122
+    detector: "*"
123
+  # 接口文档
124
+  docs:
125
+    routes:
126
+      - id: openapi
127
+        groupName: 系统接口
128
+        info:
129
+          title: 接口文档
130
+          description: 在线API文档
131
+#          termsOfService: https://gitee.com/noear/solon
132
+          contact:
133
+            name: ruoyi
134
+          version: 1.0
135
+        schemes:
136
+          - HTTP
137
+          - HTTPS
138
+        globalResponseInData: true
139
+        globalResult: org.noear.solon.core.handle.Result
140
+        apis:
141
+          - basePackage: com.ruoyi.web.controller
142
+
143
+sa-token:
144
+  # token名称(同时也是 cookie名称)
145
+  token-name: Authorization
146
+  # token前缀
147
+  token-prefix: Bearer
148
+  # token有效期(单位:秒) 默认30天,-1 代表永久有效
149
+  timeout: 2592000
150
+  # token临时有效期 (指定时间内无操作就视为token过期,单位:秒),默认-1 代表不限制,永不冻结
151
+  active-timeout: -1
152
+  # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
153
+  is-concurrent: false
154
+  # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
155
+  is-share: true
156
+  # token风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
157
+  token-style: uuid
158
+  # 是否输出操作日志
159
+  is-log: true
160
+
161
+# mybatis-flex 数据源及 mybatis配置
162
+mybatis-flex:
163
+  # 动态数据源
164
+  datasource:
165
+    master:
166
+      type: com.zaxxer.hikari.HikariDataSource
167
+      driverClassName: com.mysql.cj.jdbc.Driver
168
+      jdbcUrl: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
169
+      username: root
170
+      password:
171
+#    slave_1:
172
+#      type: com.zaxxer.hikari.HikariDataSource
173
+#      driverClassName: com.mysql.cj.jdbc.Driver
174
+#      jdbcUrl: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&autoReconnect=true&rewriteBatchedStatements=true
175
+#      username: root
176
+#      password:
177
+  # 实体扫描
178
+  type-aliases-package:
179
+    - com.ruoyi.system.domain.*
180
+  # mapper扫描
181
+  mapper-locations:
182
+    # 如果没有对应 xml文件的 mapper,必须配置一下 mapper的扫描路径
183
+#    - com.ruoyi.system.mapper.*
184
+    # 如果有 xml文件,只需要配置 xml文件的扫描路径,xml对应的 mapper会自动关联进去
185
+    - classpath:mapper/**/*.xml
186
+  # Mybatis 的扩展配置
187
+  configuration:
188
+    cacheEnabled: false
189
+    mapUnderscoreToCamelCase: true
190
+  # Mybatis-Flex 的全局配置
191
+  global-config:
192
+    print-banner: true
193
+    # 不配置逻辑删除字段将会真删除
194
+    logic-delete-column: del_flag
195
+    # 主键配置
196
+    key-config:
197
+      # Auto自增
198
+      key-type: Auto
199
+      # value:
200
+
201
+# Redis配置
202
+redis:
203
+  cache_source:
204
+    config: |
205
+      singleServerConfig:
206
+        address: redis://127.0.0.1:6379
207
+        password:
208
+        database: 7
209
+      codec: !<org.redisson.codec.JsonJacksonCodec> {}
210
+
211
+# 分页插件配置
212
+pagehelper:
213
+  offsetAsPageNum: true
214
+  rowBoundsWithCount: true
215
+  pageSizeZero: false
216
+  reasonable: true
217
+  params: pageNum=pageHelperStart;pageSize=pageHelperRows;
218
+  supportMethodsArguments: false
219
+
220
+# 接口文档配置
221
+knife4j:
222
+  # 开启增强配置
223
+  enable: true
224
+  # 开启生产环境屏蔽
225
+  production: true
226
+  # 签权
227
+  basic:
228
+    enable: true
229
+    username: admin
230
+    password: 123456
231
+  # 前端UI的个性化配置
232
+  setting:
233
+    enableVersion: true
234
+    enableOpenApi: false
235
+    enableFooter: false

+ 7
- 0
cmc-temperature-back/ruoyi-admin/src/main/resources/app.yml 파일 보기

@@ -0,0 +1,7 @@
1
+server:
2
+  port: 8080
3
+
4
+solon:
5
+  app:
6
+    name: ruoyi-solon
7
+  env: dev

+ 1
- 0
cmc-temperature-back/ruoyi-admin/src/main/resources/banner.txt 파일 보기

@@ -0,0 +1 @@
1
+ ~~ Solon ~~                                          ${solon.version}

+ 90
- 0
cmc-temperature-back/ruoyi-admin/src/main/resources/logback-solon.xml 파일 보기

@@ -0,0 +1,90 @@
1
+<?xml version="1.0" encoding="UTF-8" ?>
2
+
3
+<!DOCTYPE configuration>
4
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
5
+    <conversionRule conversionWord="tags" converterClass="ch.qos.logback.solon.SolonTagsConverter" />
6
+
7
+    <solonProperty name="APP_NAME" source="solon.app.name"
8
+                   defaultValue="solon" />
9
+
10
+    <!-- 控制台输出配置 -->
11
+    <solonProperty name="CONSOLE_LOG_LEVEL" source="solon.logging.appender.console.level"
12
+                   defaultValue="INFO" />
13
+
14
+    <solonProperty name="CONSOLE_LOG_PATTERN" source="solon.logging.appender.console.pattern"
15
+                   defaultValue="%highlight(%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [-%t][*%X{traceId}]%tags[%logger{20}]:) %n%msg%n" />
16
+
17
+    <!-- 日志文件输出配置 -->
18
+    <solonProperty name="FILE_LOG_NAME" source="solon.logging.appender.file.name"
19
+                   defaultValue="logs/${APP_NAME}" />
20
+
21
+    <solonProperty name="FILE_LOG_LEVEL" source="solon.logging.appender.file.level"
22
+                   defaultValue="INFO" />
23
+
24
+    <solonProperty name="FILE_LOG_EXTENSION" source="solon.logging.appender.file.extension"
25
+                   defaultValue=".log" />
26
+
27
+    <solonProperty name="FILE_LOG_ROLLING" source="solon.logging.appender.file.rolling"
28
+                   defaultValue="${FILE_LOG_NAME}_%d{yyyy-MM-dd}_%i${FILE_LOG_EXTENSION}" />
29
+
30
+    <solonProperty name="FILE_LOG_PATTERN" source="solon.logging.appender.file.pattern"
31
+                   defaultValue="%-5level %d{yyyy-MM-dd HH:mm:ss.SSS} [-%t][*%X{traceId}]%tags[%logger{20}]: %n%msg%n" />
32
+
33
+    <solonProperty name="FILE_LOG_MAX_HISTORY" source="solon.logging.appender.file.maxHistory"
34
+                   defaultValue="30" />
35
+
36
+    <solonProperty name="FILE_LOG_MAX_FILE_SIZE" source="solon.logging.appender.file.maxFileSize"
37
+                   defaultValue="100 MB" />
38
+
39
+    <!-- 记录器配置 -->
40
+    <solonProperty name="LOGGER_ROOT_LEVEL" source="solon.logging.logger.root.level"
41
+                   defaultValue="INFO" />
42
+
43
+    <!-- 控制台输出 -->
44
+    <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
45
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
46
+            <level>${CONSOLE_LOG_LEVEL}</level>
47
+        </filter>
48
+        <encoder>
49
+            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
50
+        </encoder>
51
+    </appender>
52
+
53
+    <!-- 日志文件输出 -->
54
+    <appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">
55
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
56
+            <level>${FILE_LOG_LEVEL}</level>
57
+        </filter>
58
+
59
+        <File>${FILE_LOG_NAME}.log</File>
60
+        <append>true</append>
61
+        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
62
+            <!-- 日志文件名格式 -->
63
+            <fileNamePattern>${FILE_LOG_ROLLING}</fileNamePattern>
64
+            <!-- 日志最大的历史保留天数 -->
65
+            <maxHistory>${FILE_LOG_MAX_HISTORY}</maxHistory>
66
+            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
67
+                <!-- 日志文件最大的大小 -->
68
+                <maxFileSize>${FILE_LOG_MAX_FILE_SIZE}</maxFileSize>
69
+            </timeBasedFileNamingAndTriggeringPolicy>
70
+        </rollingPolicy>
71
+        <encoder>
72
+            <pattern>${FILE_LOG_PATTERN}</pattern>
73
+            <charset>UTF-8</charset>
74
+        </encoder>
75
+    </appender>
76
+
77
+    <appender name="Solon" class="ch.qos.logback.solon.SolonAppender">
78
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
79
+            <level>INFO</level>
80
+        </filter>
81
+    </appender>
82
+
83
+    <root>
84
+        <level value="${LOGGER_ROOT_LEVEL}" />
85
+        <appender-ref ref="Console"/>
86
+        <appender-ref ref="File"/>
87
+        <appender-ref ref="Solon"/>
88
+    </root>
89
+
90
+</configuration>

+ 30
- 0
cmc-temperature-back/ruoyi-admin/src/main/resources/quartz.properties 파일 보기

@@ -0,0 +1,30 @@
1
+# 指定持久化方案
2
+org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
3
+org.quartz.jobStore.acquireTriggersWithinLock=true
4
+org.quartz.jobStore.misfireThreshold=5000
5
+
6
+# 指定表前缀
7
+org.quartz.jobStore.tablePrefix=QRTZ_
8
+
9
+# 指定数据源
10
+org.quartz.jobStore.dataSource=ryDS
11
+
12
+org.quartz.dataSource.ryDS.provider=hikaricp
13
+org.quartz.dataSource.ryDS.driver=org.sqlite.JDBC
14
+org.quartz.dataSource.ryDS.URL=jdbc:sqlite::resource:static/cmc-temperature.db?date_string_format=yyyy-MM-dd HH:mm:ss
15
+org.quartz.dataSource.ryDS.user=
16
+org.quartz.dataSource.ryDS.password=
17
+#org.quartz.dataSource.ryDS.provider=hikaricp
18
+#org.quartz.dataSource.ryDS.driver=com.mysql.cj.jdbc.Driver
19
+#org.quartz.dataSource.ryDS.URL=jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&zeroDateTimeBehavior=convertToNull&autoReconnect=true
20
+#org.quartz.dataSource.ryDS.user=root
21
+#org.quartz.dataSource.ryDS.password=
22
+org.quartz.dataSource.ryDS.maxConnections=10
23
+org.quartz.datasource.ryDS.validateOnCheckout=true
24
+org.quartz.datasource.ryDS.validationQuery=select 1
25
+
26
+# 指定线程池
27
+org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
28
+org.quartz.threadPool.threadCount=5
29
+org.quartz.threadPool.threadPriority=5
30
+org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true

BIN
cmc-temperature-back/ruoyi-admin/src/main/resources/static/cmc-temperature.db 파일 보기


+ 86
- 0
cmc-temperature-back/ruoyi-common/pom.xml 파일 보기

@@ -0,0 +1,86 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xmlns="http://maven.apache.org/POM/4.0.0"
3
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
5
+    <modelVersion>4.0.0</modelVersion>
6
+
7
+    <parent>
8
+        <groupId>com.ruoyi</groupId>
9
+        <artifactId>ruoyi-solon</artifactId>
10
+        <version>${ruoyi-solon.version}</version>
11
+    </parent>
12
+
13
+    <artifactId>ruoyi-common</artifactId>
14
+    <description>通用模块</description>
15
+
16
+    <dependencies>
17
+        <!-- 数据校验 -->
18
+        <dependency>
19
+            <groupId>org.noear</groupId>
20
+            <artifactId>solon-security-validation</artifactId>
21
+        </dependency>
22
+        <!-- MyBatis-Flex -->
23
+        <dependency>
24
+            <groupId>org.noear</groupId>
25
+            <artifactId>mybatis-flex-solon-plugin</artifactId>
26
+        </dependency>
27
+        <!-- mybatis分页插件 -->
28
+        <dependency>
29
+            <groupId>org.noear</groupId>
30
+            <artifactId>mybatis-pagehelper-solon-plugin</artifactId>
31
+        </dependency>
32
+        <!-- redisson -->
33
+        <dependency>
34
+            <groupId>org.noear</groupId>
35
+            <artifactId>redisson-solon-plugin</artifactId>
36
+        </dependency>
37
+        <!-- Office文档操作 -->
38
+        <dependency>
39
+            <groupId>org.noear</groupId>
40
+            <artifactId>easypoi-solon-plugin</artifactId>
41
+            <exclusions>
42
+                <exclusion>
43
+                    <groupId>org.noear</groupId>
44
+                    <artifactId>easypoi-wps-solon</artifactId>
45
+                </exclusion>
46
+            </exclusions>
47
+        </dependency>
48
+
49
+        <!-- sa-token -->
50
+        <dependency>
51
+            <groupId>cn.dev33</groupId>
52
+            <artifactId>sa-token-solon-plugin</artifactId>
53
+            <version>${sa-token.version}</version>
54
+        </dependency>
55
+        <!-- sa-token-dao数据持久化 -->
56
+        <dependency>
57
+            <groupId>cn.dev33</groupId>
58
+            <artifactId>sa-token-redisson</artifactId>
59
+            <version>${sa-token.version}</version>
60
+        </dependency>
61
+        <dependency>
62
+            <groupId>cn.dev33</groupId>
63
+            <artifactId>sa-token-snack3</artifactId>
64
+            <version>${sa-token.version}</version>
65
+        </dependency>
66
+
67
+        <!-- hutool工具 - JSON实现 -->
68
+        <dependency>
69
+            <groupId>cn.hutool</groupId>
70
+            <artifactId>hutool-json</artifactId>
71
+        </dependency>
72
+        <!-- hutool工具 - 加密解密模块 -->
73
+        <dependency>
74
+            <groupId>cn.hutool</groupId>
75
+            <artifactId>hutool-crypto</artifactId>
76
+        </dependency>
77
+
78
+        <!-- lombok -->
79
+        <dependency>
80
+            <groupId>org.projectlombok</groupId>
81
+            <artifactId>lombok</artifactId>
82
+            <scope>provided</scope>
83
+        </dependency>
84
+    </dependencies>
85
+
86
+</project>

+ 43
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/CacheConstant.java 파일 보기

@@ -0,0 +1,43 @@
1
+package com.ruoyi.common.constants;
2
+
3
+/**
4
+ * 缓存常量信息
5
+ * @author ruoyi
6
+ */
7
+public class CacheConstant {
8
+
9
+    /**
10
+     * 登录验证码
11
+     */
12
+    // redis key
13
+    public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
14
+    //登录验证码有效期(分钟)
15
+    public static final long CAPTCHA_CODE_EXPIRATION = 2L;
16
+
17
+    /**
18
+     * 登录失败
19
+     */
20
+    // redis key
21
+    public static final String LOGIN_ERROR_KEY = "login_error:";
22
+
23
+    /**
24
+     * 登录用户
25
+     */
26
+    public static final String LOGIN_USER_KEY = "loginUser";
27
+
28
+    /**
29
+     * 字典管理 cache key
30
+     */
31
+    public static final String SYS_DICT_KEY = "sys_dict:";
32
+
33
+    /**
34
+     * 参数管理 cache key
35
+     */
36
+    public static final String SYS_CONFIG_KEY = "sys_config:";
37
+
38
+    /**
39
+     * 限流 cache key
40
+     */
41
+    public static final String RATE_LIMIT_KEY = "rate_limit:";
42
+
43
+}

+ 20
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/DataSourceConstant.java 파일 보기

@@ -0,0 +1,20 @@
1
+package com.ruoyi.common.constants;
2
+
3
+/**
4
+ * 数据源常量信息
5
+ * @author ruoyi
6
+ */
7
+public class DataSourceConstant {
8
+
9
+    /**
10
+     * 数据源
11
+     */
12
+    public static final String DATA_SOURCE = "data_source";
13
+
14
+    /**
15
+     * 子数据源(default 或 master,会做为动态源的默认源)
16
+     */
17
+    public static final String DATA_SOURCE_MASTER = "master";
18
+    public static final String DATA_SOURCE_SLAVE_1 = "slave_1";
19
+
20
+}

+ 117
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/GenConstant.java 파일 보기

@@ -0,0 +1,117 @@
1
+package com.ruoyi.common.constants;
2
+
3
+/**
4
+ * 代码生成通用常量
5
+ * @author ruoyi
6
+ */
7
+public class GenConstant {
8
+
9
+    /** 单表(增删改查) */
10
+    public static final String TPL_CRUD = "crud";
11
+
12
+    /** 树表(增删改查) */
13
+    public static final String TPL_TREE = "tree";
14
+
15
+    /** 主子表(增删改查) */
16
+    public static final String TPL_SUB = "sub";
17
+
18
+    /** 树编码字段 */
19
+    public static final String TREE_CODE = "treeCode";
20
+
21
+    /** 树父编码字段 */
22
+    public static final String TREE_PARENT_CODE = "treeParentCode";
23
+
24
+    /** 树名称字段 */
25
+    public static final String TREE_NAME = "treeName";
26
+
27
+    /** 上级菜单ID字段 */
28
+    public static final String PARENT_MENU_ID = "parentMenuId";
29
+
30
+    /** 上级菜单名称字段 */
31
+    public static final String PARENT_MENU_NAME = "parentMenuName";
32
+
33
+    /** 数据库字符串类型 */
34
+    public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
35
+
36
+    /** 数据库文本类型 */
37
+    public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
38
+
39
+    /** 数据库时间类型 */
40
+    public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
41
+
42
+    /** 数据库数字类型 */
43
+    public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
44
+            "bigint", "float", "double", "decimal" };
45
+
46
+    /** 页面不需要编辑字段 */
47
+    public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
48
+
49
+    /** 页面不需要显示的列表字段 */
50
+    public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "update_by",
51
+            "update_time", "del_flag" };
52
+
53
+    /** 页面不需要查询字段 */
54
+    public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "update_by",
55
+            "update_time", "del_flag", "remark" };
56
+
57
+    /** Entity基类字段 */
58
+    public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "delFlag", "remark" };
59
+
60
+    /** Tree基类字段 */
61
+    public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors" };
62
+
63
+    /** 文本框 */
64
+    public static final String HTML_INPUT = "input";
65
+
66
+    /** 文本域 */
67
+    public static final String HTML_TEXTAREA = "textarea";
68
+
69
+    /** 下拉框 */
70
+    public static final String HTML_SELECT = "select";
71
+
72
+    /** 单选框 */
73
+    public static final String HTML_RADIO = "radio";
74
+
75
+    /** 复选框 */
76
+    public static final String HTML_CHECKBOX = "checkbox";
77
+
78
+    /** 日期控件 */
79
+    public static final String HTML_DATETIME = "datetime";
80
+
81
+    /** 图片上传控件 */
82
+    public static final String HTML_IMAGE_UPLOAD = "imageUpload";
83
+
84
+    /** 文件上传控件 */
85
+    public static final String HTML_FILE_UPLOAD = "fileUpload";
86
+
87
+    /** 富文本控件 */
88
+    public static final String HTML_EDITOR = "editor";
89
+
90
+    /** 字符串类型 */
91
+    public static final String TYPE_STRING = "String";
92
+
93
+    /** 整型 */
94
+    public static final String TYPE_INTEGER = "Integer";
95
+
96
+    /** 长整型 */
97
+    public static final String TYPE_LONG = "Long";
98
+
99
+    /** 浮点型 */
100
+    public static final String TYPE_DOUBLE = "Double";
101
+
102
+    /** 高精度计算类型 */
103
+    public static final String TYPE_BIGDECIMAL = "BigDecimal";
104
+
105
+    /** 时间类型 */
106
+    public static final String TYPE_DATE = "Date";
107
+
108
+    /** 模糊查询 */
109
+    public static final String QUERY_LIKE = "LIKE";
110
+
111
+    /** 相等查询 */
112
+    public static final String QUERY_EQ = "EQ";
113
+
114
+    /** 需要 */
115
+    public static final String REQUIRE = "1";
116
+
117
+}

+ 50
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/HttpConstant.java 파일 보기

@@ -0,0 +1,50 @@
1
+package com.ruoyi.common.constants;
2
+
3
+/**
4
+ * Http通用常量信息
5
+ * @author ruoyi
6
+ */
7
+public class HttpConstant {
8
+
9
+    /**
10
+     * 鉴权请求头(与 sa-token的 token-name保持一致)
11
+     */
12
+    public static final String TOKEN_NAME = "Authorization";
13
+
14
+    /**
15
+     * Http
16
+     */
17
+    public static final String HTTP = "http://";
18
+    public static final String HTTPS = "https://";
19
+
20
+    /**
21
+     * 请求方式
22
+     */
23
+    public static final String HTTP_GET = "GET";
24
+    public static final String HTTP_POST = "POST";
25
+    public static final String HTTP_PUT = "PUT";
26
+    public static final String HTTP_DELETE = "DELETE";
27
+
28
+    /**
29
+     * 状态码
30
+     */
31
+    public static final int HTTP_BAD_REQUEST = 400;
32
+    public static final int HTTP_NOT_FOUND = 404;
33
+    public static final int HTTP_INTERNAL_ERROR = 500;
34
+
35
+    /**
36
+     * www主域
37
+     */
38
+    public static final String WWW = "www.";
39
+
40
+    /**
41
+     * 未知 IP
42
+     */
43
+    public static final String IP_UNKNOWN = "unknown";
44
+
45
+    /**
46
+     * Content-Type
47
+     */
48
+    public static final String CONTENT_TYPE_FORM = "application/x-www-form-urlencoded";
49
+
50
+}

+ 68
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/constants/UserConstant.java 파일 보기

@@ -0,0 +1,68 @@
1
+package com.ruoyi.common.constants;
2
+
3
+/**
4
+ * 用户常量信息
5
+ * @author ruoyi
6
+ */
7
+public class UserConstant {
8
+
9
+    /**
10
+     * 用户名长度限制
11
+     */
12
+    // 最小
13
+    public static final int USERNAME_MIN_LENGTH = 2;
14
+    // 最大
15
+    public static final int USERNAME_MAX_LENGTH = 20;
16
+
17
+    /**
18
+     * 密码长度限制
19
+     */
20
+    // 最小
21
+    public static final int PASSWORD_MIN_LENGTH = 5;
22
+    // 最大
23
+    public static final int PASSWORD_MAX_LENGTH = 20;
24
+
25
+    /**
26
+     * 超级管理员
27
+     */
28
+    // 用户 ID
29
+    public static final long ADMIN_USER_ID = 1L;
30
+    // 角色 ID
31
+    public static final long ADMIN_ROLE_ID = 1L;
32
+
33
+    /**
34
+     * 菜单类型
35
+     */
36
+    // 目录
37
+    public static final String MENU_TYPE_DIR = "M";
38
+    // 菜单
39
+    public static final String MENU_TYPE_MENU = "C";
40
+
41
+    /** InnerLink组件标识 */
42
+    public final static String INNER_LINK = "InnerLink";
43
+
44
+    /** Layout组件标识 */
45
+    public final static String LAYOUT = "Layout";
46
+
47
+    /** ParentView组件标识 */
48
+    public final static String PARENT_VIEW = "ParentView";
49
+
50
+    /**
51
+     * 数据权限
52
+     */
53
+    // 全部数据权限
54
+    public static final String DATA_SCOPE_ALL = "1";
55
+    // 自定数据权限
56
+    public static final String DATA_SCOPE_CUSTOM = "2";
57
+    // 部门数据权限
58
+    public static final String DATA_SCOPE_DEPT = "3";
59
+    // 部门及以下数据权限
60
+    public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
61
+    // 仅本人数据权限
62
+    public static final String DATA_SCOPE_SELF = "5";
63
+    // 部门表的别名
64
+    public static final String DATA_SCOPE_ALIAS_DEPT = "d";
65
+    // 用户表的别名
66
+    public static final String DATA_SCOPE_ALIAS_USER = "u";
67
+
68
+}

+ 57
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java 파일 보기

@@ -0,0 +1,57 @@
1
+package com.ruoyi.common.enums;
2
+
3
+/**
4
+ * 业务操作类型
5
+ * @author ruoyi
6
+ */
7
+public enum BusinessType {
8
+    /**
9
+     * 其它
10
+     */
11
+    OTHER,
12
+
13
+    /**
14
+     * 新增
15
+     */
16
+    INSERT,
17
+
18
+    /**
19
+     * 修改
20
+     */
21
+    UPDATE,
22
+
23
+    /**
24
+     * 删除
25
+     */
26
+    DELETE,
27
+
28
+    /**
29
+     * 授权
30
+     */
31
+    GRANT,
32
+
33
+    /**
34
+     * 导出
35
+     */
36
+    EXPORT,
37
+
38
+    /**
39
+     * 导入
40
+     */
41
+    IMPORT,
42
+
43
+    /**
44
+     * 强退
45
+     */
46
+    FORCE,
47
+
48
+    /**
49
+     * 生成代码
50
+     */
51
+    GENCODE,
52
+    
53
+    /**
54
+     * 清空数据
55
+     */
56
+    CLEAN
57
+}

+ 27
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java 파일 보기

@@ -0,0 +1,27 @@
1
+package com.ruoyi.common.enums;
2
+
3
+/**
4
+ * 登录设备类型
5
+ * @author ruoyi
6
+ */
7
+public enum DeviceType {
8
+    PC("00", "PC端"),
9
+    APP("01", "APP端");
10
+
11
+    private final String code;
12
+    private final String info;
13
+
14
+    DeviceType(String code, String info) {
15
+        this.code = code;
16
+        this.info = info;
17
+    }
18
+
19
+    public String getCode() {
20
+        return code;
21
+    }
22
+
23
+    public String getInfo() {
24
+        return info;
25
+    }
26
+
27
+}

+ 77
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/DictEnum.java 파일 보기

@@ -0,0 +1,77 @@
1
+package com.ruoyi.common.enums;
2
+
3
+import lombok.AllArgsConstructor;
4
+import lombok.Getter;
5
+
6
+/**
7
+ * 字典 枚举类
8
+ * @author ruoyi
9
+ */
10
+public class DictEnum {
11
+
12
+    /**
13
+     * 删除标识
14
+     */
15
+    @Getter
16
+    @AllArgsConstructor
17
+    public enum DEL_FLAG {
18
+        OK(0, "正常"),
19
+        DELETED(1, "删除");
20
+
21
+        final int value;
22
+        final String name;
23
+    }
24
+
25
+    /**
26
+     * 通用状态
27
+     */
28
+    @Getter
29
+    @AllArgsConstructor
30
+    public enum COMMON_STATUS {
31
+        OK("0", "正常"),
32
+        DISABLE("1", "停用");
33
+
34
+        final String value;
35
+        final String name;
36
+    }
37
+
38
+    /**
39
+     * 通用成功失败状态
40
+     */
41
+    @Getter
42
+    @AllArgsConstructor
43
+    public enum COMMON_SUCCESS_FAIL {
44
+        SUCCESS("0", "成功"),
45
+        FAIL("1", "失败");
46
+
47
+        final String value;
48
+        final String name;
49
+    }
50
+
51
+    /**
52
+     * 通用是否
53
+     */
54
+    @Getter
55
+    @AllArgsConstructor
56
+    public enum COMMON_YES_NO {
57
+        YES("Y", "是"),
58
+        NO("N", "否");
59
+
60
+        final String value;
61
+        final String name;
62
+    }
63
+
64
+    /**
65
+     * 定时任务状态
66
+     */
67
+    @Getter
68
+    @AllArgsConstructor
69
+    public enum SYS_JOB_STATUS {
70
+        OK("0", "正常"),
71
+        PAUSE("1", "暂停");
72
+
73
+        final String value;
74
+        final String name;
75
+    }
76
+
77
+}

+ 24
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/enums/RateLimitType.java 파일 보기

@@ -0,0 +1,24 @@
1
+package com.ruoyi.common.enums;
2
+
3
+/**
4
+ * 限流类型 枚举
5
+ * @author ruoyi
6
+ */
7
+public enum RateLimitType {
8
+
9
+    /**
10
+     * 默认策略全局限流
11
+     */
12
+    DEFAULT,
13
+
14
+    /**
15
+     * 根据登录用户凭据进行限流
16
+     */
17
+    TOKEN,
18
+
19
+    /**
20
+     * 根据请求客户端IP进行限流
21
+     */
22
+    IP
23
+
24
+}

+ 56
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/ContextUtil.java 파일 보기

@@ -0,0 +1,56 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import cn.hutool.core.util.StrUtil;
4
+import com.ruoyi.common.constants.HttpConstant;
5
+import org.noear.solon.core.handle.Context;
6
+
7
+import java.util.HashMap;
8
+import java.util.Map;
9
+
10
+/**
11
+ * 请求上下文 工具类
12
+ * @author ruoyi
13
+ */
14
+public class ContextUtil {
15
+
16
+    /**
17
+     * 获取请求上下文
18
+     * @return
19
+     */
20
+    public static Context getContext() {
21
+        return Context.current();
22
+    }
23
+
24
+    /**
25
+     * 获取客户端 IP
26
+     * @return
27
+     */
28
+    public static String getIpAddr() {
29
+        try {
30
+            // 请求上下文
31
+            Context ctx = getContext();
32
+            return ctx.realIp();
33
+        } catch (Exception e) {
34
+            return HttpConstant.IP_UNKNOWN;
35
+        }
36
+    }
37
+
38
+    /**
39
+     * 获取请求头
40
+     * @param headers
41
+     * @return
42
+     */
43
+    public static Map<String, String> getHeaders(String... headers) {
44
+        // 请求上下文
45
+        Context ctx = getContext();
46
+        Map<String, String> map = new HashMap<>();
47
+        for (Map.Entry<String, String> stringStringEntry : ctx.headerMap().toValueMap().entrySet()) {
48
+            // 鉴权请求头(Http协议规定了请求头大小写不敏感)
49
+            if(StrUtil.equalsAnyIgnoreCase(stringStringEntry.getKey(), headers)) {
50
+                map.put(stringStringEntry.getKey(), stringStringEntry.getValue());
51
+            }
52
+        }
53
+        return map;
54
+    }
55
+
56
+}

+ 53
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/CryptoUtil.java 파일 보기

@@ -0,0 +1,53 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import cn.hutool.crypto.SecureUtil;
4
+import cn.hutool.crypto.asymmetric.KeyType;
5
+import cn.hutool.crypto.asymmetric.RSA;
6
+
7
+/**
8
+ * 加解密 工具类
9
+ * @author ruoyi
10
+ **/
11
+public class CryptoUtil {
12
+
13
+    // RSA公钥(需与前端公钥相同)
14
+    public static String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n" +
15
+            "nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==";
16
+
17
+    // RSA私钥(需与前端私钥相同)
18
+    public static String privateKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n" +
19
+            "7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n" +
20
+            "PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n" +
21
+            "kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n" +
22
+            "cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n" +
23
+            "DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n" +
24
+            "YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n" +
25
+            "UP8iWi1Qw0Y=";
26
+
27
+    /**
28
+     * RSA私钥解密
29
+     * @param text 待解密的文本
30
+     * @return 解密后的文本
31
+     */
32
+    public static String rsaDecrypt(String text) {
33
+        return getRSA().decryptStr(text, KeyType.PrivateKey);
34
+    }
35
+
36
+    /**
37
+     * RSA公钥加密
38
+     * @param text 待加密的文本
39
+     * @return 加密后的文本
40
+     */
41
+    public static String rsaEncrypt(String text) {
42
+        return getRSA().encryptBase64(text, KeyType.PublicKey);
43
+    }
44
+
45
+    /**
46
+     * 获取加解密对象RSA
47
+     * @return
48
+     */
49
+    private static RSA getRSA() {
50
+        return SecureUtil.rsa(privateKey, publicKey);
51
+    }
52
+
53
+}

+ 47
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExcelUtil.java 파일 보기

@@ -0,0 +1,47 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import cn.afterturn.easypoi.excel.ExcelExportUtil;
4
+import cn.afterturn.easypoi.excel.entity.ExportParams;
5
+import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
6
+import com.ruoyi.common.constants.HttpConstant;
7
+import com.ruoyi.common.web.exception.ServiceException;
8
+import org.apache.poi.ss.usermodel.Workbook;
9
+import org.noear.solon.core.handle.Context;
10
+
11
+import java.io.IOException;
12
+import java.util.List;
13
+
14
+/**
15
+ * Excel相关处理
16
+ * @author ruoyi
17
+ */
18
+public class ExcelUtil {
19
+
20
+    /**
21
+     * 导出 Excel
22
+     * @param list 数据
23
+     * @return
24
+     */
25
+    public static <T> void export(List<T> list) {
26
+        if(list.isEmpty()) {
27
+            throw new ServiceException("导出数据为空");
28
+        }
29
+        Context ctx = ContextUtil.getContext();
30
+        ctx.contentType(HttpConstant.CONTENT_TYPE_FORM);
31
+        ExportParams exportParams = new ExportParams();
32
+        exportParams.setType(ExcelType.HSSF);
33
+        Workbook workbook = ExcelExportUtil.exportExcel(exportParams, list.get(0).getClass(), list);
34
+        try {
35
+            workbook.write(ctx.outputStream());
36
+        } catch (IOException e) {
37
+            e.printStackTrace();
38
+        } finally {
39
+            try {
40
+                workbook.close();
41
+            } catch (IOException e) {
42
+                e.printStackTrace();
43
+            }
44
+        }
45
+    }
46
+
47
+}

+ 87
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/FileUtil.java 파일 보기

@@ -0,0 +1,87 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import cn.hutool.core.date.DateUtil;
4
+import cn.hutool.core.util.StrUtil;
5
+import com.ruoyi.common.constants.HttpConstant;
6
+import com.ruoyi.common.web.exception.ServiceException;
7
+import org.noear.solon.Utils;
8
+import org.noear.solon.core.handle.Context;
9
+import org.noear.solon.core.handle.UploadedFile;
10
+
11
+import java.io.ByteArrayOutputStream;
12
+import java.io.File;
13
+import java.io.IOException;
14
+import java.util.List;
15
+
16
+/**
17
+ * 文件 工具类
18
+ * @author ruoyi
19
+ */
20
+public class FileUtil extends cn.hutool.core.io.FileUtil {
21
+
22
+    /**
23
+     * 上传
24
+     * @param file
25
+     * @param maxSize
26
+     * @param fileType
27
+     * @return
28
+     */
29
+    public static String upload(UploadedFile file, long maxSize, List<String> fileType, String savePath, String requestPrefix) {
30
+        try {
31
+            checkFile(file, maxSize, fileType);
32
+            String fileName = StrUtil.isEmpty(file.getExtension()) ? Utils.guid() : Utils.guid() + "." + file.getExtension();
33
+            String key = File.separator + DateUtil.today() + File.separator + fileName;
34
+            File saveFile = new File(savePath + key);
35
+            if (!saveFile.exists()) {
36
+                if (!saveFile.getParentFile().exists()) {
37
+                    saveFile.getParentFile().mkdirs();
38
+                }
39
+            }
40
+            file.transferTo(saveFile);
41
+            return requestPrefix + key;
42
+        } catch (Exception e) {
43
+            throw new ServiceException(e);
44
+        }
45
+    }
46
+
47
+    /**
48
+     * 下载
49
+     * @param byteArrayOutputStream
50
+     * @return
51
+     */
52
+    public static void download(ByteArrayOutputStream byteArrayOutputStream) {
53
+        Context ctx = ContextUtil.getContext();
54
+        ctx.contentType(HttpConstant.CONTENT_TYPE_FORM);
55
+        try {
56
+            byteArrayOutputStream.writeTo(ctx.outputStream());
57
+        } catch (Exception e) {
58
+            e.printStackTrace();
59
+        } finally {
60
+            try {
61
+                byteArrayOutputStream.close();
62
+            } catch (IOException e) {
63
+                e.printStackTrace();
64
+            }
65
+        }
66
+    }
67
+
68
+    /**
69
+     * 校验文件
70
+     * @param file
71
+     * @param maxSize
72
+     * @param fileType
73
+     * @throws IOException
74
+     */
75
+    private static void checkFile(UploadedFile file, long maxSize, List<String> fileType) throws IOException {
76
+        if(file == null || file.isEmpty()) {
77
+            throw new ServiceException("文件为空");
78
+        }
79
+        if(maxSize != -1 && file.getContentSize() > maxSize * 1024 * 1024) {
80
+            throw new ServiceException("请上传 " + maxSize + "M 以内的文件");
81
+        }
82
+        if(!fileType.contains(file.getExtension())) {
83
+            throw new ServiceException("不支持此类文件上传");
84
+        }
85
+    }
86
+
87
+}

+ 332
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtil.java 파일 보기

@@ -0,0 +1,332 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import org.redisson.api.*;
4
+import org.redisson.api.options.KeysScanParams;
5
+import org.redisson.client.codec.StringCodec;
6
+import org.redisson.client.protocol.ScoredEntry;
7
+
8
+import java.time.Duration;
9
+import java.util.*;
10
+
11
+/**
12
+ * Redis操作
13
+ * @author ruoyi
14
+ */
15
+public class RedisUtil {
16
+
17
+    RedissonClient redissonClient;
18
+
19
+    public RedisUtil(RedissonClient redissonClient) {
20
+        this.redissonClient = redissonClient;
21
+    }
22
+
23
+    // ============================================= string ============================================================
24
+    /**
25
+     * 缓存基本的对象,String、Integer、实体类等
26
+     * @param key 缓存的键值
27
+     * @param value 缓存的值
28
+     */
29
+    public <T> void setCacheObject(final String key, final T value) {
30
+        RBucket<T> bucket = redissonClient.getBucket(key);
31
+        bucket.set(value);
32
+    }
33
+
34
+    /**
35
+     * 缓存基本的对象,String、Integer、实体类等
36
+     * @param key 缓存的键值
37
+     * @param value 缓存的值
38
+     * @param duration 有效时间
39
+     */
40
+    public <T> void setCacheObject(final String key, final T value, final Duration duration) {
41
+        RBucket<T> bucket = redissonClient.getBucket(key);
42
+        bucket.set(value);
43
+        bucket.expire(duration);
44
+    }
45
+
46
+    /**
47
+     * 获取缓存的基本对象
48
+     * @param key 缓存键值
49
+     * @return
50
+     */
51
+    public <T> T getCacheObject(final String key) {
52
+        RBucket<T> bucket = redissonClient.getBucket(key);
53
+        return bucket.get();
54
+    }
55
+
56
+    /**
57
+     * 获取缓存的基本对象剩余时间
58
+     * @param key
59
+     * @param <T>
60
+     * @return 剩余时间(单位:毫秒)
61
+     */
62
+    public <T> long getCacheObjectExpire(final String key) {
63
+        RBucket<T> bucket = redissonClient.getBucket(key);
64
+        return bucket.remainTimeToLive() == -2 ? 0L : bucket.remainTimeToLive();
65
+    }
66
+
67
+    /**
68
+     * 删除缓存的基本对象
69
+     * @param key 缓存的键值
70
+     * @return
71
+     */
72
+    public <T> boolean deleteCacheObject(final String key) {
73
+        RBucket<T> bucket = redissonClient.getBucket(key);
74
+        return bucket.delete();
75
+    }
76
+
77
+    /**
78
+     * 删除所有缓存的基本对象
79
+     * @param pattern 缓存的键值正则表达式
80
+     */
81
+    public <T> void deleteCacheObjectAll(final String pattern) {
82
+        Iterable<String> keysByPattern = getKeys(pattern);
83
+        for (String key : keysByPattern) {
84
+            RBucket<T> bucket = redissonClient.getBucket(key);
85
+            bucket.delete();
86
+        }
87
+    }
88
+
89
+    // ============================================== list =============================================================
90
+    /**
91
+     * 缓存List数据(注意是addAll,一直往list中存放数据)
92
+     * @param key 缓存的键值
93
+     * @param dataList 待缓存的List数据
94
+     * @return
95
+     */
96
+    public <T> boolean setCacheList(final String key, final List<T> dataList) {
97
+        RList<T> list = redissonClient.getList(key);
98
+        return list.addAll(dataList);
99
+    }
100
+
101
+    /**
102
+     * 缓存List数据(注意是addAll,一直往list中存放数据)
103
+     * @param key 缓存的键值
104
+     * @param dataList 待缓存的List数据
105
+     * @param duration 有效时间
106
+     * @return
107
+     */
108
+    public <T> boolean setCacheList(final String key, final List<T> dataList, final Duration duration) {
109
+        RList<T> list = redissonClient.getList(key);
110
+        boolean b = list.addAll(dataList);
111
+        boolean expire = list.expire(duration);
112
+        return b && expire;
113
+    }
114
+
115
+    /**
116
+     * 获取缓存的List数据
117
+     * @param key 缓存的键值
118
+     * @return
119
+     */
120
+    public <T> List<T> getCacheList(final String key) {
121
+        RList<T> list = redissonClient.getList(key);
122
+        return list.readAll();
123
+    }
124
+
125
+    /**
126
+     * 删除缓存的List数据
127
+     * @param key 缓存的键值
128
+     * @return
129
+     */
130
+    public <T> boolean deleteCacheList(final String key) {
131
+        RList<T> list = redissonClient.getList(key);
132
+        return list.delete();
133
+    }
134
+
135
+    /**
136
+     * 删除所有缓存的List数据
137
+     * @param pattern 缓存的键值正则表达式
138
+     * @return
139
+     */
140
+    public <T> void deleteCacheListAll(final String pattern) {
141
+        Iterable<String> keysByPattern = getKeys(pattern);
142
+        for (String key : keysByPattern) {
143
+            RList<T> list = redissonClient.getList(key);
144
+            list.delete();
145
+        }
146
+    }
147
+
148
+    // ============================================== hash =============================================================
149
+    /**
150
+     * 缓存Map数据(注意是putAll,一直往map中存放数据)
151
+     * @param key 缓存的键值
152
+     * @param dataMap 待缓存的Map数据
153
+     */
154
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
155
+        RMap<String, T> map = redissonClient.getMap(key);
156
+        map.putAll(dataMap);
157
+    }
158
+
159
+    /**
160
+     * 缓存Map数据(注意是putAll,一直往map中存放数据)
161
+     * @param key 缓存的键值
162
+     * @param dataMap 待缓存的Map数据
163
+     * @param duration 有效时间
164
+     */
165
+    public <T> void setCacheMap(final String key, final Map<String, T> dataMap, final Duration duration) {
166
+        RMap<String, T> map = redissonClient.getMap(key);
167
+        map.putAll(dataMap);
168
+        map.expire(duration);
169
+    }
170
+
171
+    /**
172
+     * 获取缓存的Map数据
173
+     * @param key 缓存的键值
174
+     * @return
175
+     */
176
+    public <T> Map<String, T> getCacheMap(final String key) {
177
+        RMap<String, T> map = redissonClient.getMap(key);
178
+        return map.readAllMap();
179
+    }
180
+
181
+    /**
182
+     * 删除缓存的Map数据
183
+     * @param key 缓存的键值
184
+     * @return
185
+     */
186
+    public <T> boolean deleteCacheMap(final String key) {
187
+        RMap<String, T> map = redissonClient.getMap(key);
188
+        return map.delete();
189
+    }
190
+
191
+    // ============================================== set ==============================================================
192
+    /**
193
+     * 缓存Set数据(注意是addAll,一直往set中存放数据)
194
+     * @param key 缓存的键值
195
+     * @param dataSet 待缓存的Set数据
196
+     * @return
197
+     */
198
+    public <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
199
+        RSet<T> set = redissonClient.getSet(key);
200
+        return set.addAll(dataSet);
201
+    }
202
+
203
+    /**
204
+     * 缓存Set数据(注意是addAll,一直往set中存放数据)
205
+     * @param key 缓存的键值
206
+     * @param dataSet 待缓存的Set数据
207
+     * @param duration 有效时间
208
+     * @return
209
+     */
210
+    public <T> boolean setCacheSet(final String key, final Set<T> dataSet, final Duration duration) {
211
+        RSet<T> set = redissonClient.getSet(key);
212
+        boolean b = set.addAll(dataSet);
213
+        boolean expire = set.expire(duration);
214
+        return b && expire;
215
+    }
216
+
217
+    /**
218
+     * 获取缓存的Set数据
219
+     * @param key 缓存的键值
220
+     * @return
221
+     */
222
+    public <T> Set<T> getCacheSet(final String key) {
223
+        RSet<T> set = redissonClient.getSet(key);
224
+        return set.readAll();
225
+    }
226
+
227
+    /**
228
+     * 删除缓存的Set数据
229
+     * @param key 缓存的键值
230
+     * @return
231
+     */
232
+    public <T> boolean deleteCacheSet(final String key) {
233
+        RSet<T> set = redissonClient.getSet(key);
234
+        return set.delete();
235
+    }
236
+
237
+    // ============================================== zset =============================================================
238
+    /**
239
+     * 缓存ZSet数据(注意是addAll,一直往ZSet中存放数据)
240
+     * @param key 缓存的键值
241
+     * @param dataZSet 待缓存的ZSet数据
242
+     * @return
243
+     */
244
+    public <T> boolean setCacheZSet(final String key, final Map<T, Double> dataZSet) {
245
+        RScoredSortedSet<T> scoredSortedSet = redissonClient.getScoredSortedSet(key);
246
+        return scoredSortedSet.addAll(dataZSet) > 0;
247
+    }
248
+
249
+    /**
250
+     * 缓存ZSet数据(注意是addAll,一直往ZSet中存放数据)
251
+     * @param key 缓存的键值
252
+     * @param dataZSet 待缓存的ZSet数据
253
+     * @param duration 有效时间
254
+     * @return
255
+     */
256
+    public <T> boolean setCacheZSet(final String key, final Map<T, Double> dataZSet, final Duration duration) {
257
+        RScoredSortedSet<T> scoredSortedSet = redissonClient.getScoredSortedSet(key);
258
+        int i = scoredSortedSet.addAll(dataZSet);
259
+        boolean expire = scoredSortedSet.expire(duration);
260
+        return i > 0 && expire;
261
+    }
262
+
263
+    /**
264
+     * 获取缓存的ZSet分数
265
+     * @param key 缓存的键值
266
+     * @param t 元素
267
+     * @return
268
+     */
269
+    public <T> Double getCacheZSetScore(final String key, final T t) {
270
+        RScoredSortedSet<T> scoredSortedSet = redissonClient.getScoredSortedSet(key);
271
+        return scoredSortedSet.getScore(t);
272
+    }
273
+
274
+    /**
275
+     * 获取缓存的ZSet排名
276
+     * @param key 缓存的键值
277
+     * @param t 元素
278
+     * @return
279
+     */
280
+    public <T> Integer getCacheZSetRank(final String key, final T t) {
281
+        RScoredSortedSet<T> scoredSortedSet = redissonClient.getScoredSortedSet(key);
282
+        return scoredSortedSet.revRank(t) + 1;
283
+    }
284
+
285
+    /**
286
+     * 获取缓存的ZSet指定排名范围
287
+     * @param key 缓存的键值
288
+     * @param start 起始排名(从1开始)
289
+     * @param end 结束排名(从1开始)
290
+     * @return
291
+     */
292
+    public <T> Collection<ScoredEntry<T>> getCacheZSetRange(final String key, final int start, final int end) {
293
+        RScoredSortedSet<T> scoredSortedSet = redissonClient.getScoredSortedSet(key);
294
+        return scoredSortedSet.entryRangeReversed(start - 1, end == -1 ? end : end - 1);
295
+    }
296
+
297
+    /**
298
+     * 删除缓存的ZSet数据
299
+     * @param key 缓存的键值
300
+     * @return
301
+     */
302
+    public <T> boolean deleteCacheZSet(final String key) {
303
+        RScoredSortedSet<T> scoredSortedSet = redissonClient.getScoredSortedSet(key);
304
+        return scoredSortedSet.delete();
305
+    }
306
+
307
+    // ============================================== Lua ==============================================================
308
+
309
+    /**
310
+     * 运行lua脚本
311
+     * @param luaScript
312
+     * @param keys
313
+     * @param values
314
+     * @return
315
+     */
316
+    public Long executeScript(String luaScript, List<Object> keys, Object... values) {
317
+        RScript script = redissonClient.getScript(StringCodec.INSTANCE);
318
+        String lua = script.scriptLoad(luaScript);
319
+        return script.evalSha(RScript.Mode.READ_WRITE, lua, RScript.ReturnType.INTEGER, keys, values);
320
+    }
321
+
322
+    /**
323
+     * 正则匹配所有key
324
+     * @param pattern 缓存的键值正则表达式
325
+     * @return
326
+     */
327
+    private Iterable<String> getKeys(final String pattern) {
328
+        RKeys keys = redissonClient.getKeys();
329
+        return keys.getKeys(new KeysScanParams().pattern(pattern));
330
+    }
331
+
332
+}

+ 171
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtil.java 파일 보기

@@ -0,0 +1,171 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import cn.dev33.satoken.stp.StpUtil;
4
+import cn.hutool.core.date.DateUtil;
5
+import cn.hutool.core.util.ObjectUtil;
6
+import cn.hutool.core.util.StrUtil;
7
+import cn.hutool.crypto.SecureUtil;
8
+import com.ruoyi.common.constants.CacheConstant;
9
+import com.ruoyi.common.constants.UserConstant;
10
+import com.ruoyi.common.web.domain.model.LoginUser;
11
+
12
+/**
13
+ * 鉴权 工具类
14
+ * @author ruoyi
15
+ */
16
+public class SecurityUtil {
17
+
18
+    /**
19
+     * 登录
20
+     * @param loginUser
21
+     * @param deviceType 登录设备类型
22
+     * @return
23
+     */
24
+    public static LoginUser login(LoginUser loginUser, String deviceType) {
25
+        StpUtil.login(loginUser.getUserid(), deviceType);
26
+
27
+        long loginTime = DateUtil.date().getTime() / 1000;
28
+        loginUser.setLoginTime(loginTime);
29
+        long tokenTimeout = StpUtil.getTokenTimeout();
30
+        long expireTime = -1;
31
+        if(tokenTimeout != -1) {
32
+            expireTime = loginTime + tokenTimeout;
33
+        }
34
+        loginUser.setExpireTime(expireTime);
35
+        loginUser.setToken(getTokenValue());
36
+
37
+        setLoginUser(loginUser);
38
+        return loginUser;
39
+    }
40
+
41
+    /**
42
+     * 设置用户数据
43
+     * @param loginUser
44
+     */
45
+    public static void setLoginUser(LoginUser loginUser) {
46
+        StpUtil.getTokenSession().set(CacheConstant.LOGIN_USER_KEY, loginUser);
47
+    }
48
+
49
+    /**
50
+     * 获取用户数据
51
+     */
52
+    public static LoginUser getLoginUser() {
53
+        try {
54
+            return StpUtil.getTokenSession().getModel(CacheConstant.LOGIN_USER_KEY, LoginUser.class);
55
+        } catch (Exception e) {
56
+            return null;
57
+        }
58
+    }
59
+
60
+    /**
61
+     * 获取 token-name(HttpConstant.TOKEN_NAME)
62
+     */
63
+    public static String getTokenName() {
64
+        return StpUtil.getTokenName();
65
+    }
66
+
67
+    /**
68
+     * 获取 token的值
69
+     */
70
+    public static String getTokenValue() {
71
+        return StpUtil.getTokenValue();
72
+    }
73
+
74
+    /**
75
+     * 获取 token剩余有效期(单位:秒,返回 -1代表永久有效)
76
+     */
77
+    public static long getTokenTimeOut() {
78
+        return StpUtil.getTokenTimeout();
79
+    }
80
+
81
+    /**
82
+     * 获取用户 ID
83
+     * @return
84
+     */
85
+    public static long getUserId() {
86
+        return StpUtil.getLoginIdAsLong();
87
+    }
88
+
89
+    /**
90
+     * 获取账号
91
+     * @return
92
+     */
93
+    public static String getUserName() {
94
+        LoginUser loginUser = getLoginUser();
95
+        return ObjectUtil.isNotNull(loginUser) ? loginUser.getUsername() : null;
96
+    }
97
+
98
+    /**
99
+     * 获取登录设备类型
100
+     * @return
101
+     */
102
+    public static String getDeviceType() {
103
+        LoginUser loginUser = getLoginUser();
104
+        return ObjectUtil.isNotNull(loginUser) ? loginUser.getDeviceType() : null;
105
+    }
106
+
107
+    /**
108
+     * 登出
109
+     */
110
+    public static void logout() {
111
+        StpUtil.logout();
112
+    }
113
+
114
+    /**
115
+     * 是否登录
116
+     * @return
117
+     */
118
+    public static boolean isLogin() {
119
+        return StpUtil.isLogin();
120
+    }
121
+
122
+    /**
123
+     * 是否为超级管理员
124
+     * @param userId 用户ID
125
+     * @return 结果
126
+     */
127
+    public static boolean isAdmin(Long userId) {
128
+        return userId != null && userId == UserConstant.ADMIN_USER_ID;
129
+    }
130
+
131
+    /**
132
+     * 是否拥有某项权限
133
+     * @param permissions 权限数组
134
+     * @param and   and/or
135
+     * @return 结果
136
+     */
137
+    public static boolean hasPermission(String[] permissions, boolean and) {
138
+        return and ? StpUtil.hasPermissionAnd(permissions) : StpUtil.hasPermissionOr(permissions);
139
+    }
140
+
141
+    /**
142
+     * 是否拥有某项角色
143
+     * @param roles 角色数组
144
+     * @param and   and/or
145
+     * @return 结果
146
+     */
147
+    public static boolean hasRole(String[] roles, boolean and) {
148
+        return and ? StpUtil.hasRoleAnd(roles) : StpUtil.hasRoleOr(roles);
149
+    }
150
+
151
+    /**
152
+     * 加密登录密码
153
+     * @param password 密码
154
+     * @return 加密字符串
155
+     */
156
+    public static String encryptPassword(String password) {
157
+        // 使用 MD5摘要算法加密
158
+        return SecureUtil.md5(password);
159
+    }
160
+
161
+    /**
162
+     * 判断密码是否相同
163
+     * @param rawPassword 明文真实密码
164
+     * @param encodedPassword 加密后密码
165
+     * @return 结果
166
+     */
167
+    public static boolean matchesPassword(String rawPassword, String encodedPassword) {
168
+        return StrUtil.equals(encryptPassword(rawPassword), encodedPassword);
169
+    }
170
+
171
+}

+ 143
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/utils/XssUtil.java 파일 보기

@@ -0,0 +1,143 @@
1
+package com.ruoyi.common.utils;
2
+
3
+import java.util.regex.Matcher;
4
+import java.util.regex.Pattern;
5
+
6
+/**
7
+ * 跨站脚本攻击(Xss)工具类
8
+ * @author ruoyi
9
+ */
10
+public class XssUtil {
11
+
12
+    /**
13
+     * 去除标签中所有 on开头的事件
14
+     * @param html
15
+     * @return
16
+     */
17
+    public static String removeEvent(String html) {
18
+        // 第一种情况 onEvent='...'
19
+        // 第二种情况 onEvent="..."
20
+        // 第三种情况 onEvent=...
21
+        String regex = "<[a-zA-Z]+\\s+[\\w\\s\\-%=:;\"\'\\u4e00-\\u9fa5]*(on\\w+=((\'[^>']*\')|(\"[^>\"]*\")|([\\w(),'\"\\[\\];\\u4e00-\\u9fa5]*)))";
22
+        Pattern pattern = Pattern.compile(regex);
23
+        Matcher matcher = pattern.matcher(html);
24
+        while (matcher.find()) {
25
+            html = html.substring(0, matcher.start(1)) + html.substring(matcher.end(1));
26
+            matcher = pattern.matcher(html);
27
+        }
28
+        return html;
29
+    }
30
+
31
+    /**
32
+     * 去除 script 标签
33
+     * @param html
34
+     * @return
35
+     */
36
+    public static String removeScript(String html) {
37
+        String regex = "</?[sS][cC][rR][iI][pP][tT][^>]*>";
38
+        Pattern pattern = Pattern.compile(regex);
39
+        Matcher matcher = pattern.matcher(html);
40
+        if (matcher.find()) {
41
+            html = matcher.replaceAll("");
42
+        }
43
+        return html;
44
+    }
45
+
46
+    /**
47
+     * 去除eval相关代码
48
+     * @param html
49
+     * @return
50
+     */
51
+    public static String removeEval(String html) {
52
+        String regex = "eval\\([^)]*?\\)";
53
+        Pattern pattern = Pattern.compile(regex);
54
+        Matcher matcher = pattern.matcher(html);
55
+        if (matcher.find()) {
56
+            html = matcher.replaceAll("");
57
+        }
58
+        return html;
59
+    }
60
+
61
+    /**
62
+     * 把标签中的 javascript 替换掉
63
+     * @param html
64
+     * @return
65
+     */
66
+    public static String swapJavascript(String html) {
67
+        String regex = "<[a-zA-Z]+\\s+[\\w\\s\\-%=:;\"\'\\u4e00-\\u9fa5]*([jJ][aA][vV][aA][sS][cC][rR][iI][pP][tT][^>]*?)";
68
+        Pattern pattern = Pattern.compile(regex);
69
+        Matcher matcher = pattern.matcher(html);
70
+        while (matcher.find()) {
71
+            html = html.substring(0, matcher.start(1)) + "java_script" + html.substring(matcher.end(1));
72
+            matcher = pattern.matcher(html);
73
+        }
74
+        return html;
75
+    }
76
+
77
+    /**
78
+     * 把标签中的 vbscript 替换掉
79
+     * @param html
80
+     * @return
81
+     */
82
+    public static String swapVbscript(String html) {
83
+        String regex = "<[a-zA-Z]+\\s+[\\w\\s\\-%=:;\"\'\\u4e00-\\u9fa5]*([vV][bB][sS][cC][rR][iI][pP][tT][^>]*?)";
84
+        Pattern pattern = Pattern.compile(regex);
85
+        Matcher matcher = pattern.matcher(html);
86
+        while (matcher.find()) {
87
+            html = html.substring(0, matcher.start(1)) + "vb_script" + html.substring(matcher.end(1));
88
+            matcher = pattern.matcher(html);
89
+        }
90
+        return html;
91
+    }
92
+
93
+    /**
94
+     * 把标签中的 livescript 替换掉
95
+     * @param html
96
+     * @return
97
+     */
98
+    public static String swapLivescript(String html) {
99
+        String regex = "<[a-zA-Z]+\\s+[\\w\\s\\-%=:;\"\'\\u4e00-\\u9fa5]*([lL][iI][vV][eE][sS][cC][rR][iI][pP][tT][^>]*?)";
100
+        Pattern pattern = Pattern.compile(regex);
101
+        Matcher matcher = pattern.matcher(html);
102
+        while (matcher.find()) {
103
+            html = html.substring(0, matcher.start(1)) + "live_script" + html.substring(matcher.end(1));
104
+            matcher = pattern.matcher(html);
105
+        }
106
+        return html;
107
+    }
108
+
109
+    /**
110
+     * 对html转义
111
+     * @param html
112
+     * @return
113
+     */
114
+    public static String encode(String html) {
115
+        // 对 form、iframe、frameset、frame 标签的尖括号转义
116
+        String regex = "</?(([fF][oO][rR][mM])|([iI][fF][rR][aA][mM][eE])|([fF][rR][aA][mM][eE]([sS][eE][tT])?))[^>]*?>";
117
+        Pattern pattern = Pattern.compile(regex);
118
+        Matcher matcher = pattern.matcher(html);
119
+        while (matcher.find()) {
120
+            int start = matcher.start();
121
+            int end = matcher.end();
122
+            StringBuilder sb = new StringBuilder();
123
+            if (start > 0) {
124
+                sb.append(html.substring(0, start));
125
+            }
126
+            sb.append("&#60;").append(html.substring(start + 1, end - 1)).append("&#62;");
127
+            sb.append(html.substring(end));
128
+            html = sb.toString();
129
+            matcher = pattern.matcher(html);
130
+        }
131
+        // 对 document. 和 window. 中的 . 转义
132
+        regex = "((document)|(window))\\.";
133
+        pattern = Pattern.compile(regex);
134
+        matcher = pattern.matcher(html);
135
+        while (matcher.find()) {
136
+            int end = matcher.end();
137
+            html = html.substring(0, end - 1) + "&middot;" + html.substring(end);
138
+            matcher = pattern.matcher(html);
139
+        }
140
+        return html;
141
+    }
142
+
143
+}

+ 86
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/controller/BaseController.java 파일 보기

@@ -0,0 +1,86 @@
1
+package com.ruoyi.common.web.controller;
2
+
3
+import cn.hutool.core.convert.Convert;
4
+import com.github.pagehelper.PageHelper;
5
+import com.github.pagehelper.PageInfo;
6
+import com.mybatisflex.core.paginate.Page;
7
+import com.ruoyi.common.web.domain.PageData;
8
+import org.noear.solon.core.handle.Result;
9
+import org.noear.solon.validation.annotation.Valid;
10
+
11
+import java.util.List;
12
+
13
+/**
14
+ * web层通用数据处理
15
+ * @author ruoyi
16
+ */
17
+@Valid
18
+public class BaseController {
19
+
20
+    /**
21
+     * 设置请求分页数据
22
+     * @param page
23
+     */
24
+    protected <T> void startPage(Page<T> page) {
25
+        Integer pageNumber = Convert.toInt(page.getPageNumber(), 1);
26
+        Integer pageSize = Convert.toInt(page.getPageSize());
27
+        PageHelper.startPage(pageNumber, pageSize);
28
+    }
29
+
30
+    /**
31
+     * 清理分页的线程变量
32
+     */
33
+    protected void clearPage() {
34
+        PageHelper.clearPage();
35
+    }
36
+
37
+    /**
38
+     * 响应请求分页数据
39
+     * @param list
40
+     * @return
41
+     */
42
+    protected <T> PageData<T> getPageData(List<T> list) {
43
+        return getPD(list, new PageInfo<>(list).getTotal());
44
+    }
45
+
46
+    /**
47
+     * 响应请求分页数据
48
+     * @param page
49
+     * @return
50
+     */
51
+    protected <T> PageData<T> getPageData(Page<T> page) {
52
+        return getPD(page.getRecords(), page.getTotalRow());
53
+    }
54
+
55
+    /**
56
+     * 响应返回结果
57
+     * @param result 结果
58
+     * @return
59
+     */
60
+    protected Result<Void> toResult(boolean result) {
61
+        return result ? Result.succeed() : Result.failure();
62
+    }
63
+
64
+    /**
65
+     * 响应返回结果
66
+     * @param rows 影响行数
67
+     * @return
68
+     */
69
+    protected Result<Void> toResult(int rows) {
70
+        return rows > 0 ? Result.succeed() : Result.failure();
71
+    }
72
+
73
+    /**
74
+     * 分页数据
75
+     * @param list
76
+     * @param total
77
+     * @return
78
+     */
79
+    private <T> PageData<T> getPD(List<T> list, long total) {
80
+        PageData<T> pageData = new PageData<>();
81
+        pageData.setList(list);
82
+        pageData.setTotal(total);
83
+        return pageData;
84
+    }
85
+
86
+}

+ 39
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/BaseEntity.java 파일 보기

@@ -0,0 +1,39 @@
1
+package com.ruoyi.common.web.domain;
2
+
3
+import com.mybatisflex.annotation.Column;
4
+import lombok.Data;
5
+
6
+import java.io.Serializable;
7
+import java.util.Date;
8
+
9
+/**
10
+ * Entity基类(建表时必须包含以下除 dataScope外的字段)
11
+ * @author ruoyi
12
+ */
13
+@Data
14
+public class BaseEntity implements Serializable {
15
+    private static final long serialVersionUID = 1L;
16
+
17
+    /** 创建者 */
18
+    private String createBy;
19
+
20
+    /** 创建时间 */
21
+    private Date createTime;
22
+
23
+    /** 更新者 */
24
+    private String updateBy;
25
+
26
+    /** 更新时间 */
27
+    private Date updateTime;
28
+
29
+    /** 删除标志(0代表存在 1代表删除) */
30
+    private int delFlag;
31
+
32
+    /** 备注 */
33
+    private String remark;
34
+
35
+    /** 数据权限sql拼接字段 */
36
+    @Column(ignore = true)
37
+    private String dataScopeSql;
38
+
39
+}

+ 27
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/PageData.java 파일 보기

@@ -0,0 +1,27 @@
1
+package com.ruoyi.common.web.domain;
2
+
3
+import lombok.Data;
4
+
5
+import java.io.Serializable;
6
+import java.util.List;
7
+
8
+/**
9
+ * 分页数据
10
+ * @author ruoyi
11
+ */
12
+@Data
13
+public class PageData<T> implements Serializable {
14
+    private static final long serialVersionUID = 1L;
15
+
16
+    /** 数据 */
17
+    private List<T> list;
18
+
19
+    /** 数据总量 */
20
+    private long total;
21
+
22
+    public PageData<T> total(long total) {
23
+        this.total = total;
24
+        return this;
25
+    }
26
+
27
+}

+ 33
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/TreeEntity.java 파일 보기

@@ -0,0 +1,33 @@
1
+package com.ruoyi.common.web.domain;
2
+
3
+import lombok.Data;
4
+import lombok.EqualsAndHashCode;
5
+
6
+import java.util.ArrayList;
7
+import java.util.List;
8
+
9
+/**
10
+ * Tree基类
11
+ * @author ruoyi
12
+ */
13
+@EqualsAndHashCode(callSuper = true)
14
+@Data
15
+public class TreeEntity extends BaseEntity {
16
+    private static final long serialVersionUID = 1L;
17
+
18
+    /** 父菜单名称 */
19
+    private String parentName;
20
+
21
+    /** 父菜单ID */
22
+    private Long parentId;
23
+
24
+    /** 显示顺序 */
25
+    private Integer orderNum;
26
+
27
+    /** 祖级列表 */
28
+    private String ancestors;
29
+
30
+    /** 子部门 */
31
+    private List<?> children = new ArrayList<>();
32
+
33
+}

+ 40
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/Cache.java 파일 보기

@@ -0,0 +1,40 @@
1
+package com.ruoyi.common.web.domain.entity;
2
+
3
+import lombok.Data;
4
+
5
+import java.io.Serializable;
6
+
7
+/**
8
+ * 缓存信息
9
+ * @author ruoyi
10
+ */
11
+@Data
12
+public class Cache implements Serializable {
13
+    private static final long serialVersionUID = 1L;
14
+
15
+    /**
16
+     * 类型
17
+     */
18
+    private String type;
19
+
20
+    /**
21
+     * 类型名
22
+     */
23
+    private String name;
24
+
25
+    /**
26
+     * 键
27
+     */
28
+    private String key;
29
+
30
+    /**
31
+     * 值
32
+     */
33
+    private Object value;
34
+
35
+    /**
36
+     * 描述
37
+     */
38
+    private String description;
39
+
40
+}

+ 69
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/SysDept.java 파일 보기

@@ -0,0 +1,69 @@
1
+package com.ruoyi.common.web.domain.entity;
2
+
3
+import com.mybatisflex.annotation.Column;
4
+import com.mybatisflex.annotation.Id;
5
+import com.mybatisflex.annotation.Table;
6
+import com.ruoyi.common.web.domain.BaseEntity;
7
+import lombok.Data;
8
+import lombok.EqualsAndHashCode;
9
+import org.noear.solon.validation.annotation.Email;
10
+import org.noear.solon.validation.annotation.Length;
11
+import org.noear.solon.validation.annotation.NotBlank;
12
+import org.noear.solon.validation.annotation.NotNull;
13
+
14
+import java.util.ArrayList;
15
+import java.util.List;
16
+
17
+/**
18
+ * 部门 对象
19
+ * @author ruoyi
20
+ */
21
+@EqualsAndHashCode(callSuper = true)
22
+@Data
23
+@Table(value = "sys_dept")
24
+public class SysDept extends BaseEntity {
25
+    private static final long serialVersionUID = 1L;
26
+
27
+    /** 部门ID */
28
+    @Id
29
+    private Long deptId;
30
+
31
+    /** 父部门ID */
32
+    private Long parentId;
33
+
34
+    /** 祖级列表 */
35
+    private String ancestors;
36
+
37
+    /** 部门名称 */
38
+    @NotBlank(message = "部门名称不能为空")
39
+    @Length(max = 30, message = "部门名称长度不能超过30个字符")
40
+    private String deptName;
41
+
42
+    /** 显示顺序 */
43
+    @NotNull(message = "显示顺序不能为空")
44
+    private Integer orderNum;
45
+
46
+    /** 负责人 */
47
+    private String leader;
48
+
49
+    /** 联系电话 */
50
+    @Length(max = 11, message = "联系电话长度不能超过11个字符")
51
+    private String phone;
52
+
53
+    /** 邮箱 */
54
+    @Email(message = "邮箱格式不正确")
55
+    @Length(max = 50, message = "邮箱长度不能超过50个字符")
56
+    private String email;
57
+
58
+    /** 部门状态:0正常,1停用 */
59
+    private String status;
60
+
61
+    /** 父部门名称 */
62
+    @Column(ignore = true)
63
+    private String parentName;
64
+
65
+    /** 子部门 */
66
+    @Column(ignore = true)
67
+    private List<SysDept> children = new ArrayList<>();
68
+
69
+}

+ 87
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/SysRole.java 파일 보기

@@ -0,0 +1,87 @@
1
+package com.ruoyi.common.web.domain.entity;
2
+
3
+import cn.afterturn.easypoi.excel.annotation.Excel;
4
+import com.mybatisflex.annotation.Column;
5
+import com.mybatisflex.annotation.Id;
6
+import com.mybatisflex.annotation.Table;
7
+import com.ruoyi.common.constants.UserConstant;
8
+import com.ruoyi.common.web.domain.BaseEntity;
9
+import lombok.Data;
10
+import lombok.EqualsAndHashCode;
11
+import org.noear.solon.validation.annotation.Length;
12
+import org.noear.solon.validation.annotation.NotBlank;
13
+import org.noear.solon.validation.annotation.NotNull;
14
+
15
+import java.util.Set;
16
+
17
+/**
18
+ * 角色 对象
19
+ * @author ruoyi
20
+ */
21
+@EqualsAndHashCode(callSuper = true)
22
+@Data
23
+@Table(value = "sys_role")
24
+public class SysRole extends BaseEntity {
25
+    private static final long serialVersionUID = 1L;
26
+
27
+    /** 角色ID */
28
+    @Excel(name = "角色序号")
29
+    @Id
30
+    private Long roleId;
31
+
32
+    /** 角色名称 */
33
+    @Excel(name = "角色名称")
34
+    @NotBlank(message = "角色名称不能为空")
35
+    @Length(max = 30, message = "角色名称长度不能超过30个字符")
36
+    private String roleName;
37
+
38
+    /** 角色权限 */
39
+    @Excel(name = "角色权限")
40
+    @NotBlank(message = "权限字符不能为空")
41
+    @Length(max = 100, message = "权限字符长度不能超过100个字符")
42
+    private String roleKey;
43
+
44
+    /** 角色排序 */
45
+    @Excel(name = "角色排序")
46
+    @NotNull(message = "显示顺序不能为空")
47
+    private Integer roleSort;
48
+
49
+    /** 数据范围(1:全部数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */
50
+    @Excel(name = "数据范围", replace = { "全部数据权限_1", "自定义数据权限_2", "本部门数据权限_3", "本部门及以下数据权限_4", "仅本人数据权限_5" })
51
+    private String dataScope;
52
+
53
+    /** 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */
54
+    private boolean menuCheckStrictly;
55
+
56
+    /** 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */
57
+    private boolean deptCheckStrictly;
58
+
59
+    /** 角色状态(0正常 1停用) */
60
+    @Excel(name = "角色状态", replace = { "正常_0", "停用_1" })
61
+    private String status;
62
+
63
+    /** 用户是否存在此角色标识 默认不存在 */
64
+    @Column(ignore = true)
65
+    private boolean flag = false;
66
+
67
+    /** 菜单组 */
68
+    @Column(ignore = true)
69
+    private Long[] menuIds;
70
+
71
+    /** 部门组(数据权限) */
72
+    @Column(ignore = true)
73
+    private Long[] deptIds;
74
+
75
+    /** 角色菜单权限 */
76
+    @Column(ignore = true)
77
+    private Set<String> permissions;
78
+
79
+    public boolean isAdmin() {
80
+        return isAdmin(this.roleId);
81
+    }
82
+
83
+    public static boolean isAdmin(Long roleId) {
84
+        return roleId != null && UserConstant.ADMIN_ROLE_ID == roleId;
85
+    }
86
+
87
+}

+ 105
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/SysUser.java 파일 보기

@@ -0,0 +1,105 @@
1
+package com.ruoyi.common.web.domain.entity;
2
+
3
+import cn.afterturn.easypoi.excel.annotation.Excel;
4
+import com.mybatisflex.annotation.Column;
5
+import com.mybatisflex.annotation.ColumnMask;
6
+import com.mybatisflex.annotation.Id;
7
+import com.mybatisflex.annotation.Table;
8
+import com.mybatisflex.core.mask.Masks;
9
+import com.ruoyi.common.constants.UserConstant;
10
+import com.ruoyi.common.web.domain.BaseEntity;
11
+import lombok.Data;
12
+import lombok.EqualsAndHashCode;
13
+import org.noear.solon.validation.annotation.Email;
14
+import org.noear.solon.validation.annotation.Length;
15
+import org.noear.solon.validation.annotation.NotBlank;
16
+
17
+import java.util.Date;
18
+import java.util.List;
19
+
20
+/**
21
+ * 系统用户 对象
22
+ * @author ruoyi
23
+ */
24
+@EqualsAndHashCode(callSuper = true)
25
+@Data
26
+@Table(value = "sys_user")
27
+public class SysUser extends BaseEntity {
28
+    private static final long serialVersionUID = 1L;
29
+
30
+    /** 用户ID */
31
+    @Excel(name = "用户序号")
32
+    @Id
33
+    private Long userId;
34
+
35
+    /** 部门ID */
36
+    private Long deptId;
37
+
38
+    /** 账号 */
39
+    @Excel(name = "账号")
40
+    @NotBlank(message = "账号不能为空")
41
+    @Length(min = UserConstant.USERNAME_MIN_LENGTH,
42
+            max = UserConstant.USERNAME_MAX_LENGTH,
43
+            message = "账号长度应在" + UserConstant.USERNAME_MIN_LENGTH + "和" + UserConstant.USERNAME_MAX_LENGTH + "之间")
44
+    private String userName;
45
+
46
+    /** 用户昵称 */
47
+    @Excel(name = "用户昵称")
48
+    @Length(max = 30, message = "用户昵称长度不能超过30个字符")
49
+    private String nickName;
50
+
51
+    /** 用户邮箱 */
52
+    @Excel(name = "用户邮箱")
53
+    @Email(message = "邮箱格式不正确")
54
+    @Length(max = 50, message = "邮箱长度不能超过50个字符")
55
+    private String email;
56
+
57
+    /** 手机号码 */
58
+    @Excel(name = "手机号码")
59
+    @Length(max = 11, message = "手机号码长度不能超过11个字符")
60
+    private String phonenumber;
61
+
62
+    /** 用户性别(0男 1女) */
63
+    @Excel(name = "用户性别", replace = { "男_0", "女_1", "未知_2" })
64
+    private String sex;
65
+
66
+    /** 用户头像 */
67
+    private String avatar;
68
+
69
+    /** 密码 */
70
+    @ColumnMask(Masks.PASSWORD)
71
+    private String password;
72
+
73
+    /** 帐号状态(0正常 1停用) */
74
+    @Excel(name = "帐号状态", replace = { "正常_0", "停用_1" })
75
+    private String status;
76
+
77
+    /** 最后登录IP */
78
+    @Excel(name = "最后登录IP")
79
+    private String loginIp;
80
+
81
+    /** 最后登录时间 */
82
+    @Excel(name = "最后登录时间", exportFormat = "yyyy-MM-dd HH:mm:ss")
83
+    private Date loginDate;
84
+
85
+    /** 部门对象 */
86
+    @Column(ignore = true)
87
+    private SysDept dept;
88
+
89
+    /** 角色对象 */
90
+    @Column(ignore = true)
91
+    private List<SysRole> roles;
92
+
93
+    /** 角色组 */
94
+    @Column(ignore = true)
95
+    private Long[] roleIds;
96
+
97
+    /** 岗位组 */
98
+    @Column(ignore = true)
99
+    private Long[] postIds;
100
+
101
+    /** 角色ID */
102
+    @Column(ignore = true)
103
+    private Long roleId;
104
+
105
+}

+ 69
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/entity/UserOnline.java 파일 보기

@@ -0,0 +1,69 @@
1
+package com.ruoyi.common.web.domain.entity;
2
+
3
+import lombok.Data;
4
+
5
+import java.io.Serializable;
6
+import java.util.List;
7
+
8
+/**
9
+ * 登录用户
10
+ * @author ruoyi
11
+ */
12
+@Data
13
+public class UserOnline implements Serializable {
14
+    private static final long serialVersionUID = 1L;
15
+
16
+    /**
17
+     * 用户ID
18
+     */
19
+    private Long userid;
20
+
21
+    /**
22
+     * 账号
23
+     */
24
+    private String userName;
25
+
26
+    /**
27
+     * 昵称
28
+     */
29
+    private String nickName;
30
+
31
+    /**
32
+     * 部门名称
33
+     */
34
+    private String deptName;
35
+
36
+    /**
37
+     * 登录设备
38
+     */
39
+    private List<Device> devices;
40
+
41
+
42
+    /**
43
+     * 登录设备
44
+     * @author ruoyi
45
+     */
46
+    @Data
47
+    public class Device {
48
+        /**
49
+         * 会话编号
50
+         */
51
+        private String token;
52
+
53
+        /**
54
+         * 设备
55
+         */
56
+        private String deviceType;
57
+
58
+        /**
59
+         * 登录IP地址
60
+         */
61
+        private String loginIp;
62
+
63
+        /**
64
+         * 登录时间(单位:秒)
65
+         */
66
+        private Long loginTime;
67
+    }
68
+
69
+}

+ 0
- 0
cmc-temperature-back/ruoyi-common/src/main/java/com/ruoyi/common/web/domain/model/LoginBody.java 파일 보기


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.

Loading…
취소
저장