ai-engineering-init 1.6.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/.claude/agents/code-reviewer.md +3 -130
  2. package/.claude/hooks/skill-forced-eval.js +46 -60
  3. package/.claude/hooks/stop.js +24 -1
  4. package/.claude/settings.json +10 -1
  5. package/.claude/skills/api-development/SKILL.md +179 -130
  6. package/.claude/skills/architecture-design/SKILL.md +102 -212
  7. package/.claude/skills/backend-annotations/SKILL.md +166 -220
  8. package/.claude/skills/bug-detective/SKILL.md +225 -186
  9. package/.claude/skills/code-patterns/SKILL.md +127 -244
  10. package/.claude/skills/codex-code-review/SKILL.md +327 -0
  11. package/.claude/skills/collaborating-with-codex/SKILL.md +96 -113
  12. package/.claude/skills/crud-development/SKILL.md +226 -307
  13. package/.claude/skills/data-permission/SKILL.md +131 -202
  14. package/.claude/skills/database-ops/SKILL.md +158 -355
  15. package/.claude/skills/error-handler/SKILL.md +224 -285
  16. package/.claude/skills/file-oss-management/SKILL.md +174 -169
  17. package/.claude/skills/git-workflow/SKILL.md +123 -341
  18. package/.claude/skills/json-serialization/SKILL.md +121 -137
  19. package/.claude/skills/leniu-report-customization/SKILL.md +82 -2
  20. package/.claude/skills/leniu-report-standard-customization/SKILL.md +65 -2
  21. package/.claude/skills/loki-log-query/SKILL.md +400 -0
  22. package/.claude/skills/mysql-debug/SKILL.md +58 -22
  23. package/.claude/skills/performance-doctor/SKILL.md +83 -89
  24. package/.claude/skills/redis-cache/SKILL.md +134 -185
  25. package/.claude/skills/scheduled-jobs/SKILL.md +187 -224
  26. package/.claude/skills/security-guard/SKILL.md +168 -276
  27. package/.claude/skills/sms-mail/SKILL.md +266 -228
  28. package/.claude/skills/social-login/SKILL.md +257 -195
  29. package/.claude/skills/sync-back-merge/SKILL.md +66 -0
  30. package/.claude/skills/tenant-management/SKILL.md +172 -188
  31. package/.claude/skills/utils-toolkit/SKILL.md +214 -222
  32. package/.claude/skills/websocket-sse/SKILL.md +251 -172
  33. package/.claude/skills/workflow-engine/SKILL.md +178 -250
  34. package/.claude/skills/yunxiao-task-management/SKILL.md +489 -0
  35. package/.codex/skills/api-development/SKILL.md +179 -130
  36. package/.codex/skills/architecture-design/SKILL.md +102 -212
  37. package/.codex/skills/backend-annotations/SKILL.md +166 -220
  38. package/.codex/skills/bug-detective/SKILL.md +225 -186
  39. package/.codex/skills/code-patterns/SKILL.md +127 -244
  40. package/.codex/skills/collaborating-with-codex/SKILL.md +96 -113
  41. package/.codex/skills/crud-development/SKILL.md +226 -307
  42. package/.codex/skills/data-permission/SKILL.md +131 -202
  43. package/.codex/skills/database-ops/SKILL.md +158 -355
  44. package/.codex/skills/error-handler/SKILL.md +224 -285
  45. package/.codex/skills/file-oss-management/SKILL.md +174 -169
  46. package/.codex/skills/git-workflow/SKILL.md +123 -341
  47. package/.codex/skills/json-serialization/SKILL.md +121 -137
  48. package/.codex/skills/leniu-report-customization/SKILL.md +82 -2
  49. package/.codex/skills/leniu-report-standard-customization/SKILL.md +65 -2
  50. package/.codex/skills/loki-log-query/SKILL.md +400 -0
  51. package/.codex/skills/loki-log-query/environments.json +45 -0
  52. package/.codex/skills/mysql-debug/SKILL.md +58 -22
  53. package/.codex/skills/performance-doctor/SKILL.md +83 -89
  54. package/.codex/skills/redis-cache/SKILL.md +134 -185
  55. package/.codex/skills/scheduled-jobs/SKILL.md +187 -224
  56. package/.codex/skills/security-guard/SKILL.md +168 -276
  57. package/.codex/skills/skill-creator/LICENSE.txt +202 -0
  58. package/.codex/skills/skill-creator/SKILL.md +479 -0
  59. package/.codex/skills/skill-creator/agents/analyzer.md +274 -0
  60. package/.codex/skills/skill-creator/agents/comparator.md +202 -0
  61. package/.codex/skills/skill-creator/agents/grader.md +223 -0
  62. package/.codex/skills/skill-creator/assets/eval_review.html +146 -0
  63. package/.codex/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  64. package/.codex/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  65. package/.codex/skills/skill-creator/references/schemas.md +430 -0
  66. package/.codex/skills/skill-creator/scripts/__init__.py +0 -0
  67. package/.codex/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  68. package/.codex/skills/skill-creator/scripts/generate_report.py +326 -0
  69. package/.codex/skills/skill-creator/scripts/improve_description.py +248 -0
  70. package/.codex/skills/skill-creator/scripts/package_skill.py +136 -0
  71. package/.codex/skills/skill-creator/scripts/quick_validate.py +103 -0
  72. package/.codex/skills/skill-creator/scripts/run_eval.py +310 -0
  73. package/.codex/skills/skill-creator/scripts/run_loop.py +332 -0
  74. package/.codex/skills/skill-creator/scripts/utils.py +47 -0
  75. package/.codex/skills/sms-mail/SKILL.md +266 -228
  76. package/.codex/skills/social-login/SKILL.md +257 -195
  77. package/.codex/skills/sync-back-merge/SKILL.md +66 -0
  78. package/.codex/skills/tenant-management/SKILL.md +172 -188
  79. package/.codex/skills/utils-toolkit/SKILL.md +214 -222
  80. package/.codex/skills/websocket-sse/SKILL.md +251 -172
  81. package/.codex/skills/workflow-engine/SKILL.md +178 -250
  82. package/.codex/skills/yunxiao-task-management/SKILL.md +489 -0
  83. package/.cursor/hooks/cursor-skill-eval.js +66 -6
  84. package/.cursor/hooks/stop.js +23 -1
  85. package/.cursor/skills/api-development/SKILL.md +179 -130
  86. package/.cursor/skills/architecture-design/SKILL.md +102 -212
  87. package/.cursor/skills/backend-annotations/SKILL.md +166 -220
  88. package/.cursor/skills/bug-detective/SKILL.md +225 -186
  89. package/.cursor/skills/code-patterns/SKILL.md +127 -244
  90. package/.cursor/skills/collaborating-with-codex/SKILL.md +96 -113
  91. package/.cursor/skills/crud-development/SKILL.md +226 -307
  92. package/.cursor/skills/data-permission/SKILL.md +131 -202
  93. package/.cursor/skills/database-ops/SKILL.md +158 -355
  94. package/.cursor/skills/error-handler/SKILL.md +224 -285
  95. package/.cursor/skills/file-oss-management/SKILL.md +174 -169
  96. package/.cursor/skills/git-workflow/SKILL.md +123 -341
  97. package/.cursor/skills/json-serialization/SKILL.md +121 -137
  98. package/.cursor/skills/leniu-report-customization/SKILL.md +82 -2
  99. package/.cursor/skills/leniu-report-standard-customization/SKILL.md +65 -2
  100. package/.cursor/skills/loki-log-query/SKILL.md +400 -0
  101. package/.cursor/skills/loki-log-query/environments.json +45 -0
  102. package/.cursor/skills/mysql-debug/SKILL.md +58 -22
  103. package/.cursor/skills/performance-doctor/SKILL.md +83 -89
  104. package/.cursor/skills/redis-cache/SKILL.md +134 -185
  105. package/.cursor/skills/scheduled-jobs/SKILL.md +187 -224
  106. package/.cursor/skills/security-guard/SKILL.md +168 -276
  107. package/.cursor/skills/skill-creator/LICENSE.txt +202 -0
  108. package/.cursor/skills/skill-creator/SKILL.md +479 -0
  109. package/.cursor/skills/skill-creator/agents/analyzer.md +274 -0
  110. package/.cursor/skills/skill-creator/agents/comparator.md +202 -0
  111. package/.cursor/skills/skill-creator/agents/grader.md +223 -0
  112. package/.cursor/skills/skill-creator/assets/eval_review.html +146 -0
  113. package/.cursor/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  114. package/.cursor/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  115. package/.cursor/skills/skill-creator/references/schemas.md +430 -0
  116. package/.cursor/skills/skill-creator/scripts/__init__.py +0 -0
  117. package/.cursor/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  118. package/.cursor/skills/skill-creator/scripts/generate_report.py +326 -0
  119. package/.cursor/skills/skill-creator/scripts/improve_description.py +248 -0
  120. package/.cursor/skills/skill-creator/scripts/package_skill.py +136 -0
  121. package/.cursor/skills/skill-creator/scripts/quick_validate.py +103 -0
  122. package/.cursor/skills/skill-creator/scripts/run_eval.py +310 -0
  123. package/.cursor/skills/skill-creator/scripts/run_loop.py +332 -0
  124. package/.cursor/skills/skill-creator/scripts/utils.py +47 -0
  125. package/.cursor/skills/sms-mail/SKILL.md +266 -228
  126. package/.cursor/skills/social-login/SKILL.md +257 -195
  127. package/.cursor/skills/sync-back-merge/SKILL.md +66 -0
  128. package/.cursor/skills/tenant-management/SKILL.md +172 -188
  129. package/.cursor/skills/utils-toolkit/SKILL.md +214 -222
  130. package/.cursor/skills/websocket-sse/SKILL.md +251 -172
  131. package/.cursor/skills/workflow-engine/SKILL.md +178 -250
  132. package/.cursor/skills/yunxiao-task-management/SKILL.md +489 -0
  133. package/AGENTS.md +49 -540
  134. package/CLAUDE.md +73 -119
  135. package/README.md +37 -6
  136. package/bin/index.js +611 -25
  137. package/package.json +1 -1
  138. package/src/platform-map.json +4 -0
  139. package/src/skills/api-development/SKILL.md +179 -130
  140. package/src/skills/architecture-design/SKILL.md +102 -212
  141. package/src/skills/backend-annotations/SKILL.md +166 -220
  142. package/src/skills/bug-detective/SKILL.md +225 -186
  143. package/src/skills/code-patterns/SKILL.md +127 -244
  144. package/src/skills/codex-code-review/SKILL.md +261 -69
  145. package/src/skills/collaborating-with-codex/SKILL.md +96 -113
  146. package/src/skills/crud-development/SKILL.md +226 -307
  147. package/src/skills/data-permission/SKILL.md +131 -202
  148. package/src/skills/database-ops/SKILL.md +158 -355
  149. package/src/skills/error-handler/SKILL.md +224 -285
  150. package/src/skills/file-oss-management/SKILL.md +174 -169
  151. package/src/skills/git-workflow/SKILL.md +123 -341
  152. package/src/skills/json-serialization/SKILL.md +121 -137
  153. package/src/skills/leniu-report-customization/SKILL.md +82 -2
  154. package/src/skills/leniu-report-standard-customization/SKILL.md +65 -2
  155. package/src/skills/loki-log-query/SKILL.md +400 -0
  156. package/src/skills/loki-log-query/environments.json +45 -0
  157. package/src/skills/mysql-debug/SKILL.md +58 -22
  158. package/src/skills/performance-doctor/SKILL.md +83 -89
  159. package/src/skills/redis-cache/SKILL.md +134 -185
  160. package/src/skills/scheduled-jobs/SKILL.md +187 -224
  161. package/src/skills/security-guard/SKILL.md +168 -276
  162. package/src/skills/skill-creator/LICENSE.txt +202 -0
  163. package/src/skills/skill-creator/SKILL.md +479 -0
  164. package/src/skills/skill-creator/agents/analyzer.md +274 -0
  165. package/src/skills/skill-creator/agents/comparator.md +202 -0
  166. package/src/skills/skill-creator/agents/grader.md +223 -0
  167. package/src/skills/skill-creator/assets/eval_review.html +146 -0
  168. package/src/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  169. package/src/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  170. package/src/skills/skill-creator/references/schemas.md +430 -0
  171. package/src/skills/skill-creator/scripts/__init__.py +0 -0
  172. package/src/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  173. package/src/skills/skill-creator/scripts/generate_report.py +326 -0
  174. package/src/skills/skill-creator/scripts/improve_description.py +248 -0
  175. package/src/skills/skill-creator/scripts/package_skill.py +136 -0
  176. package/src/skills/skill-creator/scripts/quick_validate.py +103 -0
  177. package/src/skills/skill-creator/scripts/run_eval.py +310 -0
  178. package/src/skills/skill-creator/scripts/run_loop.py +332 -0
  179. package/src/skills/skill-creator/scripts/utils.py +47 -0
  180. package/src/skills/sms-mail/SKILL.md +266 -228
  181. package/src/skills/social-login/SKILL.md +257 -195
  182. package/src/skills/sync-back-merge/SKILL.md +66 -0
  183. package/src/skills/tenant-management/SKILL.md +172 -188
  184. package/src/skills/utils-toolkit/SKILL.md +214 -222
  185. package/src/skills/websocket-sse/SKILL.md +251 -172
  186. package/src/skills/workflow-engine/SKILL.md +178 -250
  187. package/src/skills/yunxiao-task-management/SKILL.md +489 -0
@@ -11,12 +11,12 @@ description: |
11
11
  - JSON 格式验证
12
12
  - 数据类型映射与转换
13
13
 
14
- 触发词:JSON、序列化、反序列化、JsonUtils、日期格式、精度、BigDecimal、Long、类型转换、JSON验证
14
+ 触发词:JSON、序列化、反序列化、JsonUtils、日期格式、精度、BigDecimal、Long、类型转换、JSON验证、ObjectMapper、Jackson
15
15
  ---
16
16
 
17
17
  # JSON 序列化与数据转换指南
18
18
 
19
- > 模块位置:`ruoyi-common/ruoyi-common-json`
19
+ > 基于 Jackson(Spring Boot 默认 JSON 处理库)
20
20
 
21
21
  ## 快速索引
22
22
 
@@ -25,46 +25,97 @@ description: |
25
25
  | 对象转 JSON | `JsonUtils.toJsonString()` | null 返回 null |
26
26
  | JSON 转对象 | `JsonUtils.parseObject()` | 空返回 null |
27
27
  | JSON 转 List | `JsonUtils.parseArray()` | 空返回空 ArrayList |
28
- | JSON 转 Dict | `JsonUtils.parseMap()` | 非 JSON 返回 null |
29
- | JSON 数组转 Dict 列表 | `JsonUtils.parseArrayMap()` | 空返回 null |
28
+ | JSON 转 Map | `JsonUtils.parseMap()` | 非 JSON 返回 null |
30
29
  | 复杂类型转换 | `JsonUtils.parseObject(text, TypeReference)` | 支持泛型 |
31
30
  | JSON 验证 | `JsonUtils.isJson()` / `isJsonObject()` / `isJsonArray()` | |
32
- | 字段校验注解 | `@JsonPattern` | 支持 OBJECT/ARRAY/ANY |
33
31
 
34
32
  ---
35
33
 
36
- ## 核心工具类 JsonUtils
34
+ ## 核心工具类 JsonUtils(通用实现)
35
+
36
+ > 推荐封装一个项目级的 `JsonUtils`,内部使用 Jackson `ObjectMapper` 单例。
37
37
 
38
38
  ```java
39
- import org.dromara.common.json.utils.JsonUtils;
40
- ```
39
+ import com.fasterxml.jackson.databind.ObjectMapper;
40
+ import com.fasterxml.jackson.core.type.TypeReference;
41
41
 
42
- ### 序列化
42
+ public class JsonUtils {
43
43
 
44
- ```java
45
- // 对象转 JSON 字符串(null 返回 null)
46
- String json = JsonUtils.toJsonString(user);
44
+ private static final ObjectMapper MAPPER = SpringUtil.getBean(ObjectMapper.class);
45
+ // 或者:private static final ObjectMapper MAPPER = new ObjectMapper();
46
+
47
+ public static String toJsonString(Object obj) {
48
+ if (obj == null) return null;
49
+ try {
50
+ return MAPPER.writeValueAsString(obj);
51
+ } catch (Exception e) {
52
+ throw new RuntimeException("JSON序列化失败", e);
53
+ }
54
+ }
55
+
56
+ public static <T> T parseObject(String json, Class<T> clazz) {
57
+ if (json == null || json.isBlank()) return null;
58
+ try {
59
+ return MAPPER.readValue(json, clazz);
60
+ } catch (Exception e) {
61
+ throw new RuntimeException("JSON反序列化失败", e);
62
+ }
63
+ }
64
+
65
+ public static <T> T parseObject(String json, TypeReference<T> typeRef) {
66
+ if (json == null || json.isBlank()) return null;
67
+ try {
68
+ return MAPPER.readValue(json, typeRef);
69
+ } catch (Exception e) {
70
+ throw new RuntimeException("JSON反序列化失败", e);
71
+ }
72
+ }
73
+
74
+ public static <T> List<T> parseArray(String json, Class<T> clazz) {
75
+ if (json == null || json.isBlank()) return new ArrayList<>();
76
+ try {
77
+ return MAPPER.readValue(json,
78
+ MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, clazz));
79
+ } catch (Exception e) {
80
+ throw new RuntimeException("JSON反序列化失败", e);
81
+ }
82
+ }
83
+
84
+ public static boolean isJson(String str) {
85
+ return isJsonObject(str) || isJsonArray(str);
86
+ }
87
+
88
+ public static boolean isJsonObject(String str) {
89
+ if (str == null || str.isBlank()) return false;
90
+ return str.trim().startsWith("{") && str.trim().endsWith("}");
91
+ }
92
+
93
+ public static boolean isJsonArray(String str) {
94
+ if (str == null || str.isBlank()) return false;
95
+ return str.trim().startsWith("[") && str.trim().endsWith("]");
96
+ }
97
+
98
+ public static ObjectMapper getObjectMapper() {
99
+ return MAPPER;
100
+ }
101
+ }
47
102
  ```
48
103
 
49
- ### 反序列化
104
+ ---
105
+
106
+ ## 序列化与反序列化
107
+
108
+ ### 基本用法
50
109
 
51
110
  ```java
52
- // JSON 转简单对象(空返回 null)
53
- User user = JsonUtils.parseObject(json, User.class);
111
+ // 对象转 JSON 字符串
112
+ String json = JsonUtils.toJsonString(user);
54
113
 
55
- // 字节数组转对象
56
- User user = JsonUtils.parseObject(bytes, User.class);
114
+ // JSON 转简单对象
115
+ User user = JsonUtils.parseObject(json, User.class);
57
116
 
58
- // JSON 数组转 List(空返回空 ArrayList)
117
+ // JSON 数组转 List
59
118
  List<User> users = JsonUtils.parseArray(json, User.class);
60
-
61
- // JSON 转 Dict(非 JSON 返回 null)
62
- Dict dict = JsonUtils.parseMap(json);
63
- String name = dict.getStr("name");
64
- int age = dict.getInt("age");
65
-
66
- // JSON 数组转 Dict 列表
67
- List<Dict> dicts = JsonUtils.parseArrayMap(json);
68
119
  ```
69
120
 
70
121
  ### 复杂泛型类型
@@ -89,67 +140,46 @@ List<User> users = JsonUtils.parseObject(json, USER_LIST_TYPE);
89
140
  ### JSON 验证
90
141
 
91
142
  ```java
92
- // 判断是否为合法 JSON(对象或数组)
93
- JsonUtils.isJson("{\"name\":\"张三\"}"); // true
94
- JsonUtils.isJson("[1,2,3]"); // true
95
- JsonUtils.isJson("not json"); // false
96
-
97
- // 判断是否为 JSON 对象
98
- JsonUtils.isJsonObject("{\"a\":1}"); // true
99
- JsonUtils.isJsonObject("[1,2,3]"); // false
100
-
101
- // 判断是否为 JSON 数组
102
- JsonUtils.isJsonArray("[1,2,3]"); // true
103
- JsonUtils.isJsonArray("{\"a\":1}"); // false
104
- ```
105
-
106
- ### 获取 ObjectMapper
143
+ JsonUtils.isJson("{\"name\":\"test\"}"); // true
144
+ JsonUtils.isJson("[1,2,3]"); // true
145
+ JsonUtils.isJson("not json"); // false
107
146
 
108
- ```java
109
- ObjectMapper mapper = JsonUtils.getObjectMapper();
110
- JsonNode node = mapper.readTree(json);
147
+ JsonUtils.isJsonObject("{\"a\":1}"); // true
148
+ JsonUtils.isJsonArray("[1,2,3]"); // true
111
149
  ```
112
150
 
113
151
  ---
114
152
 
115
- ## @JsonPattern 校验注解
153
+ ## Jackson 自动配置
116
154
 
117
- 用于 BO 类字段的 JSON 格式校验。
155
+ ### 推荐配置类
118
156
 
119
157
  ```java
120
- import org.dromara.common.json.validate.JsonPattern;
121
- import org.dromara.common.json.validate.JsonType;
122
-
123
- public class ConfigBo {
124
-
125
- // 任意 JSON 格式(对象或数组)
126
- @JsonPattern
127
- private String configValue;
128
-
129
- // 必须是 JSON 对象
130
- @JsonPattern(type = JsonType.OBJECT, message = "配置必须是 JSON 对象格式")
131
- private String objectConfig;
132
-
133
- // 必须是 JSON 数组
134
- @JsonPattern(type = JsonType.ARRAY, message = "列表必须是 JSON 数组格式")
135
- private String arrayConfig;
158
+ @Configuration
159
+ public class JacksonConfig {
160
+
161
+ @Bean
162
+ public Jackson2ObjectMapperBuilderCustomizer customizer() {
163
+ return builder -> {
164
+ // LocalDateTime 格式化
165
+ builder.simpleDateFormat("yyyy-MM-dd HH:mm:ss");
166
+ builder.serializers(new LocalDateTimeSerializer(
167
+ DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
168
+ builder.deserializers(new LocalDateTimeDeserializer(
169
+ DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
170
+
171
+ // 大数字精度保护
172
+ SimpleModule module = new SimpleModule();
173
+ module.addSerializer(Long.class, new BigNumberSerializer());
174
+ module.addSerializer(Long.TYPE, new BigNumberSerializer());
175
+ module.addSerializer(BigInteger.class, new BigNumberSerializer());
176
+ module.addSerializer(BigDecimal.class, ToStringSerializer.instance);
177
+ builder.modules(module);
178
+ };
179
+ }
136
180
  }
137
181
  ```
138
182
 
139
- **JsonType 枚举**:
140
-
141
- | 值 | 说明 | 示例 |
142
- |----|------|------|
143
- | `ANY` | 对象或数组都可以(默认) | `{}` 或 `[]` |
144
- | `OBJECT` | 必须是 JSON 对象 | `{"a":1}` |
145
- | `ARRAY` | 必须是 JSON 数组 | `[1,2,3]` |
146
-
147
- ---
148
-
149
- ## Jackson 自动配置
150
-
151
- 配置类:`org.dromara.common.json.config.JacksonConfig`
152
-
153
183
  ### 大数字处理(BigNumberSerializer)
154
184
 
155
185
  **问题**:JavaScript 最大安全整数为 `2^53 - 1`(9007199254740991),超出范围会丢失精度。
@@ -157,11 +187,11 @@ public class ConfigBo {
157
187
  **解决方案**:自动将超出 JS 安全范围的数字序列化为字符串。
158
188
 
159
189
  ```java
160
- // 安全范围内 保持数字
190
+ // 安全范围内 -> 保持数字
161
191
  Long id = 123456L;
162
192
  // 序列化结果:{"id": 123456}
163
193
 
164
- // 超出安全范围 转为字符串
194
+ // 超出安全范围 -> 转为字符串
165
195
  Long id = 9007199254740992L;
166
196
  // 序列化结果:{"id": "9007199254740992"}
167
197
 
@@ -189,20 +219,6 @@ BigDecimal amount = new BigDecimal("123.45");
189
219
  LocalDateTime now = LocalDateTime.now();
190
220
  String json = JsonUtils.toJsonString(now);
191
221
  // 输出:"2026-02-06 14:30:45"
192
-
193
- LocalDateTime parsed = JsonUtils.parseObject("\"2026-02-06 14:30:45\"", LocalDateTime.class);
194
- ```
195
-
196
- ### Date 自动解析(CustomDateDeserializer)
197
-
198
- 使用 Hutool 的 `DateUtil.parse()` 自动识别多种日期格式:
199
-
200
- ```java
201
- // 支持的格式(自动识别)
202
- Date d1 = JsonUtils.parseObject("\"2026-02-06 14:30:45\"", Date.class);
203
- Date d2 = JsonUtils.parseObject("\"2026-02-06\"", Date.class);
204
- Date d3 = JsonUtils.parseObject("\"2026/02/06 14:30:45\"", Date.class);
205
- Date d4 = JsonUtils.parseObject("\"20260206143045\"", Date.class);
206
222
  ```
207
223
 
208
224
  ---
@@ -214,17 +230,17 @@ Date d4 = JsonUtils.parseObject("\"20260206143045\"", Date.class);
214
230
  ```java
215
231
  @Service
216
232
  @RequiredArgsConstructor
217
- public class ConfigServiceImpl implements IConfigService {
233
+ public class ConfigServiceImpl {
218
234
 
219
- private final ConfigMapper baseMapper;
235
+ private final ConfigMapper configMapper;
220
236
 
221
237
  /**
222
238
  * 获取配置为对象
223
239
  */
224
240
  public <T> T getConfig(String configKey, Class<T> clazz) {
225
- SysConfig config = baseMapper.selectOne(
226
- Wrappers.<SysConfig>lambdaQuery()
227
- .eq(SysConfig::getConfigKey, configKey));
241
+ Config config = configMapper.selectOne(
242
+ Wrappers.<Config>lambdaQuery()
243
+ .eq(Config::getConfigKey, configKey));
228
244
  if (config == null) {
229
245
  return null;
230
246
  }
@@ -235,10 +251,10 @@ public class ConfigServiceImpl implements IConfigService {
235
251
  * 保存配置
236
252
  */
237
253
  public void saveConfig(String configKey, Object value) {
238
- SysConfig config = new SysConfig();
254
+ Config config = new Config();
239
255
  config.setConfigKey(configKey);
240
256
  config.setConfigValue(JsonUtils.toJsonString(value));
241
- baseMapper.insert(config);
257
+ configMapper.insert(config);
242
258
  }
243
259
 
244
260
  /**
@@ -246,7 +262,7 @@ public class ConfigServiceImpl implements IConfigService {
246
262
  */
247
263
  public void importData(String jsonData) {
248
264
  if (!JsonUtils.isJsonArray(jsonData)) {
249
- throw new ServiceException("数据格式不正确,应为 JSON 数组");
265
+ throw new [你的异常类]("数据格式不正确,应为 JSON 数组");
250
266
  }
251
267
  List<DataBo> list = JsonUtils.parseArray(jsonData, DataBo.class);
252
268
  // 处理数据...
@@ -254,25 +270,6 @@ public class ConfigServiceImpl implements IConfigService {
254
270
  }
255
271
  ```
256
272
 
257
- ### BO 中使用 JSON 校验
258
-
259
- ```java
260
- @Data
261
- @AutoMapper(target = SysConfig.class, reverseConvertGenerate = false)
262
- public class SysConfigBo extends BaseEntity {
263
-
264
- @NotNull(message = "ID不能为空", groups = EditGroup.class)
265
- private Long id;
266
-
267
- @NotBlank(message = "配置键不能为空")
268
- private String configKey;
269
-
270
- @NotBlank(message = "配置值不能为空")
271
- @JsonPattern(type = JsonType.OBJECT, message = "配置值必须是有效的 JSON 对象")
272
- private String configValue;
273
- }
274
- ```
275
-
276
273
  ---
277
274
 
278
275
  ## 常见问题
@@ -280,12 +277,12 @@ public class SysConfigBo extends BaseEntity {
280
277
  ### 1. 什么时候用 parseObject vs parseArray?
281
278
 
282
279
  ```java
283
- // JSON 对象 parseObject
284
- String json = "{\"name\":\"张三\"}";
280
+ // JSON 对象 -> parseObject
281
+ String json = "{\"name\":\"test\"}";
285
282
  User user = JsonUtils.parseObject(json, User.class);
286
283
 
287
- // JSON 数组 parseArray
288
- String json = "[{\"name\":\"张三\"},{\"name\":\"李四\"}]";
284
+ // JSON 数组 -> parseArray
285
+ String json = "[{\"name\":\"test1\"},{\"name\":\"test2\"}]";
289
286
  List<User> users = JsonUtils.parseArray(json, User.class);
290
287
  ```
291
288
 
@@ -305,7 +302,6 @@ Map<String, User> map = JsonUtils.parseObject(json,
305
302
  ```java
306
303
  // toJsonString
307
304
  JsonUtils.toJsonString(null); // 返回 null
308
- JsonUtils.toJsonString(user); // 返回 JSON 字符串
309
305
 
310
306
  // parseObject
311
307
  JsonUtils.parseObject(null, User.class); // 返回 null
@@ -316,18 +312,6 @@ JsonUtils.parseArray(null, User.class); // 返回空 ArrayList
316
312
  JsonUtils.parseArray("", User.class); // 返回空 ArrayList
317
313
  ```
318
314
 
319
- ### 4. 如何在解析前验证 JSON?
320
-
321
- ```java
322
- public void processData(String data) {
323
- // 先验证再解析
324
- if (!JsonUtils.isJsonArray(data)) {
325
- throw new ServiceException("数据格式不正确");
326
- }
327
- List<User> users = JsonUtils.parseArray(data, User.class);
328
- }
329
- ```
330
-
331
315
  ---
332
316
 
333
317
  ## 禁止事项
@@ -337,7 +321,7 @@ public void processData(String data) {
337
321
  ObjectMapper mapper = new ObjectMapper();
338
322
  String json = mapper.writeValueAsString(user);
339
323
 
340
- // ✅ 正确:使用 JsonUtils
324
+ // ✅ 正确:使用项目统一的 JsonUtils
341
325
  String json = JsonUtils.toJsonString(user);
342
326
 
343
327
  // ❌ 禁止:不验证直接解析(可能报错)
@@ -291,7 +291,83 @@ GROUP BY d.wallet_id
291
291
 
292
292
  ---
293
293
 
294
- ## 九、开发检查清单
294
+ ## 九、MySQL only_full_group_by 规范(必须遵守)
295
+
296
+ > 生产环境 MySQL 开启了 `sql_mode=only_full_group_by`,所有报表 SQL 必须满足此规则,否则报 `BadSqlGrammarException`。
297
+
298
+ ### 核心规则
299
+
300
+ **SELECT 中所有非聚合字段,必须出现在 GROUP BY 中,且表达式必须完全一致。**
301
+
302
+ ### 常见错误:GROUP BY 表达式与 SELECT 不一致
303
+
304
+ ```sql
305
+ -- ❌ 错误:SELECT 用 DATE_FORMAT,GROUP BY 用 DATE
306
+ SELECT
307
+ DATE_FORMAT(atr.trade_time, '%Y-%m-%d') AS statisticDate,
308
+ SUM(atr.amount) AS totalAmount
309
+ FROM acc_trade atr
310
+ GROUP BY DATE(atr.trade_time) -- ❌ 表达式不同,触发 only_full_group_by 报错
311
+ ORDER BY DATE(atr.trade_time) ASC
312
+
313
+ -- ✅ 正确:GROUP BY 与 SELECT 使用完全相同的表达式
314
+ SELECT
315
+ DATE_FORMAT(atr.trade_time, '%Y-%m-%d') AS statisticDate,
316
+ SUM(atr.amount) AS totalAmount
317
+ FROM acc_trade atr
318
+ GROUP BY DATE_FORMAT(atr.trade_time, '%Y-%m-%d') -- ✅ 与 SELECT 一致
319
+ ORDER BY DATE_FORMAT(atr.trade_time, '%Y-%m-%d') ASC
320
+ ```
321
+
322
+ ### 常见错误:SELECT 包含非聚合字段未加入 GROUP BY
323
+
324
+ ```sql
325
+ -- ❌ 错误:canteen_name 未在 GROUP BY 中
326
+ SELECT
327
+ DATE(pay_time) AS orderDate,
328
+ canteen_name, -- ❌ 非聚合字段,未在 GROUP BY
329
+ SUM(real_amount) AS netAmount
330
+ FROM report_order_info
331
+ GROUP BY DATE(pay_time), canteen_id
332
+
333
+ -- ✅ 正确:所有非聚合字段都加入 GROUP BY
334
+ SELECT
335
+ DATE(pay_time) AS orderDate,
336
+ canteen_name,
337
+ SUM(real_amount) AS netAmount
338
+ FROM report_order_info
339
+ GROUP BY DATE(pay_time), canteen_id, canteen_name -- ✅ 包含 canteen_name
340
+ ```
341
+
342
+ ### fix SQL 中的正确写法
343
+
344
+ ```xml
345
+ <insert id="initFix">
346
+ INSERT INTO report_sum_xxx (id, statistic_date, canteen_id, canteen_name,
347
+ order_count, consume_amount, net_amount)
348
+ SELECT
349
+ #{id},
350
+ DATE(pay_time), -- SELECT 用 DATE(pay_time)
351
+ canteen_id,
352
+ canteen_name,
353
+ COUNT(*),
354
+ SUM(CASE WHEN consume_type = 1 THEN real_amount ELSE 0 END),
355
+ SUM(real_amount)
356
+ FROM report_order_info
357
+ WHERE pay_time BETWEEN #{startTime} AND #{endTime}
358
+ GROUP BY DATE(pay_time), canteen_id, canteen_name -- ✅ 与 SELECT 完全一致
359
+ </insert>
360
+ ```
361
+
362
+ ### 开发检查项
363
+
364
+ - [ ] SELECT 每个非聚合字段,在 GROUP BY 中都有对应
365
+ - [ ] GROUP BY 的表达式与 SELECT 中的**完全一致**(`DATE_FORMAT(x, 'Y-m-d')` ≠ `DATE(x)`)
366
+ - [ ] ORDER BY 也使用相同表达式(保持一致)
367
+
368
+ ---
369
+
370
+ ## 十、开发检查清单
295
371
 
296
372
  ### 建表
297
373
  - [ ] 分组维度字段 + 金额汇总字段 + 审计字段(crby/crtime/upby/uptime/del_flag),无 tenant_id
@@ -308,9 +384,13 @@ GROUP BY d.wallet_id
308
384
  ### 查询接口
309
385
  - [ ] 分页 + 合计行(PageVO + TotalVO)+ 三并行 CompletableFuture
310
386
 
387
+ ### SQL 合规(only_full_group_by)
388
+ - [ ] SELECT 非聚合字段全部在 GROUP BY 中
389
+ - [ ] GROUP BY 表达式与 SELECT 完全一致
390
+
311
391
  ---
312
392
 
313
- ## 十、关键代码位置
393
+ ## 十一、关键代码位置
314
394
 
315
395
  | 类型 | 路径 |
316
396
  |------|------|
@@ -286,7 +286,69 @@ public ReportBaseTotalVO<XxxVO> pageSummary(XxxParam param) {
286
286
 
287
287
  ---
288
288
 
289
- ## 九、开发检查清单
289
+ ## 九、MySQL only_full_group_by 规范(必须遵守)
290
+
291
+ > MySQL 默认开启 `sql_mode=ONLY_FULL_GROUP_BY`,SELECT 中所有非聚合列必须出现在 GROUP BY 中,且 GROUP BY 表达式必须与 SELECT 表达式**完全一致**。
292
+
293
+ ### 核心规则
294
+
295
+ **SELECT 的表达式 == GROUP BY 的表达式**(字符级别完全一致)
296
+
297
+ ### ❌ 错误示例(GROUP BY 与 SELECT 不一致)
298
+
299
+ ```xml
300
+ <!-- 报错:Expression #1 of SELECT list is not in GROUP BY clause -->
301
+ SELECT
302
+ DATE_FORMAT(roi.consume_time, '%Y-%m-%d') AS statisticDate,
303
+ SUM(roi.real_amount) AS totalAmount
304
+ FROM report_order_info roi
305
+ GROUP BY DATE(roi.consume_time) <!-- ❌ DATE() ≠ DATE_FORMAT(..., '%Y-%m-%d') -->
306
+ ORDER BY DATE(roi.consume_time)
307
+ ```
308
+
309
+ ### ✅ 正确示例(GROUP BY 与 SELECT 完全一致)
310
+
311
+ ```xml
312
+ SELECT
313
+ DATE_FORMAT(roi.consume_time, '%Y-%m-%d') AS statisticDate,
314
+ SUM(roi.real_amount) AS totalAmount
315
+ FROM report_order_info roi
316
+ GROUP BY DATE_FORMAT(roi.consume_time, '%Y-%m-%d') <!-- ✅ 与 SELECT 完全一致 -->
317
+ ORDER BY DATE_FORMAT(roi.consume_time, '%Y-%m-%d') <!-- ✅ ORDER BY 也保持一致 -->
318
+ ```
319
+
320
+ ### ❌ 错误示例(SELECT 含非聚合列未加入 GROUP BY)
321
+
322
+ ```xml
323
+ SELECT
324
+ roi.canteen_id,
325
+ roi.canteen_name, <!-- ❌ 非聚合列未在 GROUP BY 中 -->
326
+ SUM(roi.real_amount) AS totalAmount
327
+ FROM report_order_info roi
328
+ GROUP BY roi.canteen_id
329
+ ```
330
+
331
+ ### ✅ 正确示例(所有非聚合列都在 GROUP BY 中)
332
+
333
+ ```xml
334
+ SELECT
335
+ roi.canteen_id,
336
+ roi.canteen_name,
337
+ SUM(roi.real_amount) AS totalAmount
338
+ FROM report_order_info roi
339
+ GROUP BY roi.canteen_id, roi.canteen_name <!-- ✅ 所有非聚合列都在 GROUP BY -->
340
+ ```
341
+
342
+ ### 检查清单
343
+
344
+ - [ ] SELECT 中按日期分组时使用 `DATE_FORMAT(col, '%Y-%m-%d')`,**不要用 `DATE()`**
345
+ - [ ] GROUP BY 表达式与 SELECT 中对应列**逐字相同**(复制粘贴而非重写)
346
+ - [ ] ORDER BY 中同样使用与 GROUP BY 一致的表达式
347
+ - [ ] SELECT 中所有非聚合列(无 SUM/COUNT/AVG/MAX/MIN 包裹)都出现在 GROUP BY 中
348
+
349
+ ---
350
+
351
+ ## 十、开发检查清单
290
352
 
291
353
  ### 建表
292
354
  - [ ] 分组维度 + 金额汇总 + 审计字段(crby/crtime/upby/uptime/del_flag),无 tenant_id
@@ -302,10 +364,11 @@ public ReportBaseTotalVO<XxxVO> pageSummary(XxxParam param) {
302
364
 
303
365
  ### 查询
304
366
  - [ ] ReportBaseTotalVO + CompletableFuture 并行 + MgrUserAuthPO 权限
367
+ - [ ] GROUP BY / ORDER BY 表达式与 SELECT 完全一致(only_full_group_by)
305
368
 
306
369
  ---
307
370
 
308
- ## 十、关键代码位置
371
+ ## 十一、关键代码位置
309
372
 
310
373
  > 路径前缀均为 `core-report/.../statistics/`
311
374