ai-engineering-init 1.6.0 → 1.7.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.
- package/.claude/agents/code-reviewer.md +3 -130
- package/.claude/hooks/skill-forced-eval.js +2 -0
- package/.claude/hooks/stop.js +24 -1
- package/.claude/skills/codex-code-review/SKILL.md +327 -0
- package/.claude/skills/leniu-report-customization/SKILL.md +82 -2
- package/.claude/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/.claude/skills/loki-log-query/SKILL.md +400 -0
- package/.claude/skills/mysql-debug/SKILL.md +58 -22
- package/.claude/skills/skill-creator/LICENSE.txt +202 -0
- package/.claude/skills/skill-creator/SKILL.md +479 -0
- package/.claude/skills/skill-creator/agents/analyzer.md +274 -0
- package/.claude/skills/skill-creator/agents/comparator.md +202 -0
- package/.claude/skills/skill-creator/agents/grader.md +223 -0
- package/.claude/skills/skill-creator/assets/eval_review.html +146 -0
- package/.claude/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.claude/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.claude/skills/skill-creator/references/schemas.md +430 -0
- package/.claude/skills/skill-creator/scripts/__init__.py +0 -0
- package/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.claude/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.claude/skills/skill-creator/scripts/improve_description.py +248 -0
- package/.claude/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.claude/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.claude/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.claude/skills/skill-creator/scripts/run_loop.py +332 -0
- package/.claude/skills/skill-creator/scripts/utils.py +47 -0
- package/.claude/skills/sync-back-merge/SKILL.md +66 -0
- package/.claude/skills/yunxiao-task-management/SKILL.md +489 -0
- package/.codex/skills/leniu-report-customization/SKILL.md +82 -2
- package/.codex/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/.codex/skills/loki-log-query/SKILL.md +400 -0
- package/.codex/skills/loki-log-query/environments.json +45 -0
- package/.codex/skills/mysql-debug/SKILL.md +58 -22
- package/.codex/skills/skill-creator/LICENSE.txt +202 -0
- package/.codex/skills/skill-creator/SKILL.md +479 -0
- package/.codex/skills/skill-creator/agents/analyzer.md +274 -0
- package/.codex/skills/skill-creator/agents/comparator.md +202 -0
- package/.codex/skills/skill-creator/agents/grader.md +223 -0
- package/.codex/skills/skill-creator/assets/eval_review.html +146 -0
- package/.codex/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.codex/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.codex/skills/skill-creator/references/schemas.md +430 -0
- package/.codex/skills/skill-creator/scripts/__init__.py +0 -0
- package/.codex/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.codex/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.codex/skills/skill-creator/scripts/improve_description.py +248 -0
- package/.codex/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.codex/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.codex/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.codex/skills/skill-creator/scripts/run_loop.py +332 -0
- package/.codex/skills/skill-creator/scripts/utils.py +47 -0
- package/.codex/skills/sync-back-merge/SKILL.md +66 -0
- package/.codex/skills/yunxiao-task-management/SKILL.md +489 -0
- package/.cursor/hooks/stop.js +23 -1
- package/.cursor/skills/leniu-report-customization/SKILL.md +82 -2
- package/.cursor/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/.cursor/skills/loki-log-query/SKILL.md +400 -0
- package/.cursor/skills/loki-log-query/environments.json +45 -0
- package/.cursor/skills/mysql-debug/SKILL.md +58 -22
- package/.cursor/skills/skill-creator/LICENSE.txt +202 -0
- package/.cursor/skills/skill-creator/SKILL.md +479 -0
- package/.cursor/skills/skill-creator/agents/analyzer.md +274 -0
- package/.cursor/skills/skill-creator/agents/comparator.md +202 -0
- package/.cursor/skills/skill-creator/agents/grader.md +223 -0
- package/.cursor/skills/skill-creator/assets/eval_review.html +146 -0
- package/.cursor/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/.cursor/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/.cursor/skills/skill-creator/references/schemas.md +430 -0
- package/.cursor/skills/skill-creator/scripts/__init__.py +0 -0
- package/.cursor/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/.cursor/skills/skill-creator/scripts/generate_report.py +326 -0
- package/.cursor/skills/skill-creator/scripts/improve_description.py +248 -0
- package/.cursor/skills/skill-creator/scripts/package_skill.py +136 -0
- package/.cursor/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/.cursor/skills/skill-creator/scripts/run_eval.py +310 -0
- package/.cursor/skills/skill-creator/scripts/run_loop.py +332 -0
- package/.cursor/skills/skill-creator/scripts/utils.py +47 -0
- package/.cursor/skills/sync-back-merge/SKILL.md +66 -0
- package/.cursor/skills/yunxiao-task-management/SKILL.md +489 -0
- package/bin/index.js +606 -24
- package/package.json +1 -1
- package/src/platform-map.json +4 -0
- package/src/skills/codex-code-review/SKILL.md +261 -69
- package/src/skills/leniu-report-customization/SKILL.md +82 -2
- package/src/skills/leniu-report-standard-customization/SKILL.md +65 -2
- package/src/skills/loki-log-query/SKILL.md +400 -0
- package/src/skills/loki-log-query/environments.json +45 -0
- package/src/skills/mysql-debug/SKILL.md +58 -22
- package/src/skills/skill-creator/LICENSE.txt +202 -0
- package/src/skills/skill-creator/SKILL.md +479 -0
- package/src/skills/skill-creator/agents/analyzer.md +274 -0
- package/src/skills/skill-creator/agents/comparator.md +202 -0
- package/src/skills/skill-creator/agents/grader.md +223 -0
- package/src/skills/skill-creator/assets/eval_review.html +146 -0
- package/src/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/src/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/src/skills/skill-creator/references/schemas.md +430 -0
- package/src/skills/skill-creator/scripts/__init__.py +0 -0
- package/src/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/src/skills/skill-creator/scripts/generate_report.py +326 -0
- package/src/skills/skill-creator/scripts/improve_description.py +248 -0
- package/src/skills/skill-creator/scripts/package_skill.py +136 -0
- package/src/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/src/skills/skill-creator/scripts/run_eval.py +310 -0
- package/src/skills/skill-creator/scripts/run_loop.py +332 -0
- package/src/skills/skill-creator/scripts/utils.py +47 -0
- package/src/skills/sync-back-merge/SKILL.md +66 -0
- package/src/skills/yunxiao-task-management/SKILL.md +489 -0
|
@@ -5,135 +5,8 @@ model: sonnet
|
|
|
5
5
|
tools: Read, Grep, Glob
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
你是 leniu-tengyun-core
|
|
8
|
+
你是 leniu-tengyun-core(云食堂)的代码审查助手。
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
## 触发场景
|
|
15
|
-
|
|
16
|
-
1. `/dev` 或 `/crud` 命令完成后
|
|
17
|
-
2. 用户说"审查代码"、"检查代码"、"review"
|
|
18
|
-
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## 后端审查清单
|
|
22
|
-
|
|
23
|
-
### 🔴 严重问题(必须修复)
|
|
24
|
-
|
|
25
|
-
#### 1. 包名规范
|
|
26
|
-
```bash
|
|
27
|
-
Grep pattern: "package org\.dromara\." path: [目标目录] # ❌ 必须为 0 个
|
|
28
|
-
Grep pattern: "package net\.xnzn\." path: [目标目录] # ✅ 应有结果
|
|
29
|
-
```
|
|
30
|
-
- ❌ `package org.dromara.xxx`
|
|
31
|
-
- ✅ `package net.xnzn.core.xxx`
|
|
32
|
-
|
|
33
|
-
#### 2. 禁止使用 RuoYi 工具类
|
|
34
|
-
```bash
|
|
35
|
-
Grep pattern: "MapstructUtils" path: [目标目录] glob: "*.java"
|
|
36
|
-
Grep pattern: "ServiceException" path: [目标目录] glob: "*.java"
|
|
37
|
-
Grep pattern: "import javax\.validation" path: [目标目录] glob: "*.java"
|
|
38
|
-
```
|
|
39
|
-
- ❌ `MapstructUtils.convert()` → ✅ `BeanUtil.copyProperties()`
|
|
40
|
-
- ❌ `throw new ServiceException()` → ✅ `throw new LeException()`
|
|
41
|
-
- ❌ `javax.validation.*` → ✅ `jakarta.validation.*`(JDK 21)
|
|
42
|
-
|
|
43
|
-
#### 3. 审计字段名称
|
|
44
|
-
```bash
|
|
45
|
-
Grep pattern: "private.*createBy\|private.*updateBy\|private.*createTime\|private.*updateTime" path: [目标目录] glob: "*.java"
|
|
46
|
-
```
|
|
47
|
-
- ❌ `createBy / updateBy / createTime / updateTime`
|
|
48
|
-
- ✅ `crby / upby / crtime / uptime`
|
|
49
|
-
|
|
50
|
-
#### 4. del_flag 值语义
|
|
51
|
-
```bash
|
|
52
|
-
Grep pattern: "delFlag.*=.*0\|del_flag.*=.*0" path: [目标目录] glob: "*.java"
|
|
53
|
-
```
|
|
54
|
-
- ❌ `delFlag = 0`(RuoYi 的正常值)
|
|
55
|
-
- ✅ `delFlag = 2`(leniu 的正常值,1=删除)
|
|
56
|
-
|
|
57
|
-
#### 5. Entity 不含 tenant_id
|
|
58
|
-
```bash
|
|
59
|
-
Grep pattern: "tenantId\|tenant_id" path: [目标目录] glob: "*.java"
|
|
60
|
-
```
|
|
61
|
-
- ❌ Entity 中有 `tenantId` 字段(双库物理隔离,无需此字段)
|
|
62
|
-
|
|
63
|
-
#### 6. 禁止 Map 传递业务数据
|
|
64
|
-
```bash
|
|
65
|
-
Grep pattern: "Map<String,\s*Object>" path: [目标目录] glob: "*.java"
|
|
66
|
-
```
|
|
67
|
-
- ❌ 返回 `Map<String, Object>` → ✅ 使用 VO 类
|
|
68
|
-
|
|
69
|
-
### 🟡 警告问题(建议修复)
|
|
70
|
-
|
|
71
|
-
#### 7. 请求体封装
|
|
72
|
-
```bash
|
|
73
|
-
Grep pattern: "@RequestBody [^L]" path: [目标目录] glob: "*Controller.java"
|
|
74
|
-
```
|
|
75
|
-
- 建议所有 POST 请求使用 `@RequestBody LeRequest<T>` 封装
|
|
76
|
-
|
|
77
|
-
#### 8. 依赖注入
|
|
78
|
-
```bash
|
|
79
|
-
Grep pattern: "@Autowired" path: [目标目录] glob: "*.java"
|
|
80
|
-
```
|
|
81
|
-
- 跨模块循环依赖时使用 `@Autowired @Lazy`
|
|
10
|
+
**审查流程**:请读取 `.claude/skills/codex-code-review/SKILL.md` 获取完整的审查清单和工作流,然后按照其中的 Phase 2(本地规范检查)执行审查。
|
|
82
11
|
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
Grep pattern: "@Transactional" path: [目标目录] glob: "*Service*.java"
|
|
86
|
-
```
|
|
87
|
-
- 写操作应使用 `@Transactional(rollbackFor = Exception.class)`
|
|
88
|
-
|
|
89
|
-
#### 10. 国际化异常
|
|
90
|
-
```bash
|
|
91
|
-
Grep pattern: 'new LeException\("[^"]*[\u4e00-\u9fa5]' path: [目标目录] glob: "*.java"
|
|
92
|
-
```
|
|
93
|
-
- 建议使用 `I18n.getMessage()` 替代硬编码中文
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
## 前端审查(如涉及)
|
|
98
|
-
|
|
99
|
-
前端项目路径:`/Users/xujiajun/Developer/frontProj/web`
|
|
100
|
-
|
|
101
|
-
### 🔴 严重问题
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
# 检查是否正确处理响应码
|
|
105
|
-
Grep pattern: "\.code\s*==\s*200\|\.code\s*===\s*200" path: [前端目录] # ❌ 应为 10000
|
|
106
|
-
Grep pattern: "Admin-Token" path: [前端目录] glob: "*.js" # Token key 验证
|
|
107
|
-
```
|
|
108
|
-
- 成功码:`10000`(不是 200)
|
|
109
|
-
- Token:`Admin-Token`(localStorage)
|
|
110
|
-
- 租户:`MERCHANT-ID`(请求头)
|
|
111
|
-
- 金额:后端返回分,前端用 `money()` 转元显示
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
## 审查报告格式
|
|
116
|
-
|
|
117
|
-
```
|
|
118
|
-
# 代码审查报告
|
|
119
|
-
|
|
120
|
-
审查范围: [文件/模块]
|
|
121
|
-
|
|
122
|
-
## 严重问题(X 项)
|
|
123
|
-
1. [问题类型]
|
|
124
|
-
文件: path/to/file.java:行号
|
|
125
|
-
问题: 描述
|
|
126
|
-
修复: 代码示例
|
|
127
|
-
|
|
128
|
-
## 警告问题(X 项)
|
|
129
|
-
...
|
|
130
|
-
|
|
131
|
-
## 通过项
|
|
132
|
-
- [x] 包名规范 (net.xnzn.core.*)
|
|
133
|
-
- [x] 使用 LeException
|
|
134
|
-
- [x] 审计字段正确 (crby/crtime/upby/uptime)
|
|
135
|
-
- [x] del_flag 语义正确 (2=正常)
|
|
136
|
-
...
|
|
137
|
-
|
|
138
|
-
结论: ✅ 通过 / ⚠️ 需修复 / ❌ 不通过
|
|
139
|
-
```
|
|
12
|
+
**核心架构**:四层架构(Controller → Business → Service → Mapper),包名 `net.xnzn.core.*`,JDK 21,双库物理隔离(无 tenant_id 字段)。
|
|
@@ -86,6 +86,7 @@ const instructions = `## 强制技能激活流程(必须执行)
|
|
|
86
86
|
- brainstorm: 头脑风暴/创意/方案设计
|
|
87
87
|
- collaborating-with-codex: Codex协作/多模型/算法分析
|
|
88
88
|
- collaborating-with-gemini: Gemini协作/前端原型/UI设计
|
|
89
|
+
- codex-code-review: 代码审查/review/代码检查/code review/审查代码/检查代码/代码质量
|
|
89
90
|
- workflow-engine: 工作流/审批流/Flowable/流程
|
|
90
91
|
- test-development: 测试/单元测试/@Test/JUnit5/Mockito
|
|
91
92
|
- json-serialization: JSON/序列化/反序列化/JsonUtils/日期格式/BigDecimal/精度/类型转换
|
|
@@ -122,6 +123,7 @@ const instructions = `## 强制技能激活流程(必须执行)
|
|
|
122
123
|
- leniu-data-permission: 多租户/数据权限/@UseSystem/Executors.doInTenant/readInSystem/TenantContextHolder/MERCHANT-ID/双库隔离/数据源切换
|
|
123
124
|
- leniu-redis-cache: Redis/缓存/RedisUtil/分布式锁/RLock/getLock/setNx/ZSet/限流/缓存击穿
|
|
124
125
|
- leniu-security-guard: 安全认证/SQL注入防护/XSS防护/数据脱敏/SM4加密/接口安全/限流
|
|
126
|
+
- loki-log-query: 查日志/traceId/链路追踪/Loki/日志查询/线上日志/生产日志/错误日志/异常堆栈/日志排查
|
|
125
127
|
- leniu-mealtime: 餐次/mealtime/mealtimeType/早餐/午餐/晚餐/下午茶/夜宵/AllocMealtimeTypeEnum
|
|
126
128
|
- leniu-marketing-price-rule-customizer: 营销计费/计价规则/RulePriceHandler/RulePriceEnum/折扣规则/满减规则/限额规则/补贴规则
|
|
127
129
|
- leniu-marketing-recharge-rule-customizer: 营销充值/充值规则/RuleRechargeHandler/RuleRechargeEnum/满赠规则/充值赠送/管理费规则
|
package/.claude/hooks/stop.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
3
|
* Stop Hook - Claude 回答结束时触发
|
|
4
|
-
* 功能: nul 文件清理 + 智能完成通知(音效/系统通知/TTS)
|
|
4
|
+
* 功能: nul 文件清理 + 代码审查提示 + 智能完成通知(音效/系统通知/TTS)
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const fs = require('fs');
|
|
8
8
|
const path = require('path');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
9
10
|
|
|
10
11
|
// 清理可能误创建的 nul 文件(Windows 下 > nul 可能创建该文件)
|
|
11
12
|
const findAndDeleteNul = (dir, depth = 0) => {
|
|
@@ -27,6 +28,28 @@ const findAndDeleteNul = (dir, depth = 0) => {
|
|
|
27
28
|
};
|
|
28
29
|
findAndDeleteNul(process.cwd());
|
|
29
30
|
|
|
31
|
+
// 代码审查提示:检测是否有未提交的代码变更
|
|
32
|
+
try {
|
|
33
|
+
const cwd = process.cwd();
|
|
34
|
+
const diff = execSync('git diff --name-only HEAD 2>/dev/null || true', { cwd, encoding: 'utf8' }).trim();
|
|
35
|
+
const staged = execSync('git diff --cached --name-only 2>/dev/null || true', { cwd, encoding: 'utf8' }).trim();
|
|
36
|
+
const allChanged = [diff, staged].filter(Boolean).join('\n');
|
|
37
|
+
|
|
38
|
+
if (allChanged) {
|
|
39
|
+
// 检查是否有业务代码变更(Java/XML/SQL/Vue/JS 等)
|
|
40
|
+
const codeExtensions = /\.(java|xml|sql|vue|js|ts|jsx|tsx|py|go|rs|kt)$/i;
|
|
41
|
+
const changedFiles = allChanged.split('\n').filter(f => codeExtensions.test(f));
|
|
42
|
+
|
|
43
|
+
if (changedFiles.length > 0) {
|
|
44
|
+
console.error(`\n💡 检测到 ${changedFiles.length} 个代码文件变更,建议执行代码审查:`);
|
|
45
|
+
console.error(` → 输入 "review" 或 "审查代码" 使用 code-reviewer 进行规范检查`);
|
|
46
|
+
console.error(` → 输入 "codex review" 调用 Codex 进行深度代码审查\n`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
} catch {
|
|
50
|
+
// git 不可用或非 git 仓库,静默跳过
|
|
51
|
+
}
|
|
52
|
+
|
|
30
53
|
// 执行智能通知
|
|
31
54
|
require('./lib/notify.js').run(process.cwd())
|
|
32
55
|
.then(() => process.exit(0))
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: codex-code-review
|
|
3
|
+
description: |
|
|
4
|
+
代码审查工作流。分两阶段:先执行本地规范检查(Grep 即时完成)+ 代码逻辑审查(Read 逐文件),再可选调用 Codex CLI 深度审查。
|
|
5
|
+
|
|
6
|
+
触发场景:
|
|
7
|
+
- /dev 或 /crud 命令完成代码生成后
|
|
8
|
+
- Bug 修复完成后
|
|
9
|
+
- 用户说"审查代码"、"review"、"代码审查"、"检查代码"
|
|
10
|
+
- 用户说"检查一下刚写的代码"
|
|
11
|
+
- Stop Hook 提示后用户输入"review"
|
|
12
|
+
|
|
13
|
+
触发词:代码审查、review、审查代码、检查代码、code review、代码质量、codex审查、codex review
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# 代码审查工作流
|
|
17
|
+
|
|
18
|
+
> 两阶段审查:**本地检查**(规范 + 逻辑) + **Codex 深度审查**(可选)。
|
|
19
|
+
|
|
20
|
+
## Phase 1: 收集变更范围
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git diff --name-only HEAD
|
|
24
|
+
git diff --cached --name-only
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
如果没有变更文件,提示"没有检测到代码变更"并终止。
|
|
28
|
+
|
|
29
|
+
将变更文件按类型分组:
|
|
30
|
+
- **Java 文件**:Controller / Business / Service / Mapper / Entity / VO / DTO
|
|
31
|
+
- **XML 文件**:Mapper XML
|
|
32
|
+
- **SQL 文件**:建表/变更脚本
|
|
33
|
+
- **其他**:配置文件等
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Phase 2: 本地检查(必做)
|
|
38
|
+
|
|
39
|
+
分两步执行:**Step A** 用 Grep 批量扫描规范问题(秒级),**Step B** 用 Read 逐文件审查代码逻辑。
|
|
40
|
+
|
|
41
|
+
### Step A: 项目规范扫描(Grep 批量检查)
|
|
42
|
+
|
|
43
|
+
#### 🔴 A1. 包名规范
|
|
44
|
+
```bash
|
|
45
|
+
Grep pattern: "package org\.dromara\." path: [目标目录] glob: "*.java"
|
|
46
|
+
```
|
|
47
|
+
- ❌ `package org.dromara.xxx` → ✅ `package net.xnzn.core.xxx`
|
|
48
|
+
|
|
49
|
+
#### 🔴 A2. 禁止 RuoYi 工具类
|
|
50
|
+
```bash
|
|
51
|
+
Grep pattern: "MapstructUtils" path: [目标目录] glob: "*.java"
|
|
52
|
+
Grep pattern: "ServiceException" path: [目标目录] glob: "*.java"
|
|
53
|
+
Grep pattern: "import javax\.validation" path: [目标目录] glob: "*.java"
|
|
54
|
+
```
|
|
55
|
+
- ❌ `MapstructUtils` → ✅ `BeanUtil.copyProperties()`
|
|
56
|
+
- ❌ `ServiceException` → ✅ `LeException`
|
|
57
|
+
- ❌ `javax.validation.*` → ✅ `jakarta.validation.*`(JDK 21)
|
|
58
|
+
|
|
59
|
+
#### 🔴 A3. 审计字段名称
|
|
60
|
+
```bash
|
|
61
|
+
Grep pattern: "private.*createBy|private.*updateBy|private.*createTime|private.*updateTime" path: [目标目录] glob: "*.java"
|
|
62
|
+
```
|
|
63
|
+
- ❌ `createBy/updateBy/createTime/updateTime` → ✅ `crby/upby/crtime/uptime`
|
|
64
|
+
|
|
65
|
+
#### 🔴 A4. del_flag 值语义
|
|
66
|
+
```bash
|
|
67
|
+
Grep pattern: "delFlag.*=.*0|del_flag.*=.*0" path: [目标目录] glob: "*.java"
|
|
68
|
+
```
|
|
69
|
+
- ❌ `delFlag = 0`(RuoYi 正常值) → ✅ `delFlag = 2`(leniu 正常值,1=删除)
|
|
70
|
+
|
|
71
|
+
#### 🔴 A5. Entity 不含 tenant_id
|
|
72
|
+
```bash
|
|
73
|
+
Grep pattern: "tenantId|tenant_id" path: [目标目录] glob: "*.java"
|
|
74
|
+
```
|
|
75
|
+
- ❌ 双库物理隔离,无需 `tenant_id` 字段
|
|
76
|
+
|
|
77
|
+
#### 🔴 A6. 禁止 Map 传递业务数据
|
|
78
|
+
```bash
|
|
79
|
+
Grep pattern: "Map<String,\s*Object>" path: [目标目录] glob: "*.java"
|
|
80
|
+
```
|
|
81
|
+
- ❌ `Map<String, Object>` → ✅ 使用 VO/DTO 类
|
|
82
|
+
|
|
83
|
+
#### 🟡 A7. 事务注解缺少 rollbackFor
|
|
84
|
+
```bash
|
|
85
|
+
Grep pattern: "@Transactional\b" path: [目标目录] glob: "*.java"
|
|
86
|
+
# 对命中文件二次检查:是否缺少 rollbackFor
|
|
87
|
+
Grep pattern: "@Transactional\((?!.*rollbackFor)" path: [命中文件]
|
|
88
|
+
```
|
|
89
|
+
- ❌ `@Transactional` → ✅ `@Transactional(rollbackFor = Exception.class)`
|
|
90
|
+
|
|
91
|
+
#### 🟡 A8. 请求体封装
|
|
92
|
+
```bash
|
|
93
|
+
Grep pattern: "@RequestBody [^L]" path: [目标目录] glob: "*Controller.java"
|
|
94
|
+
```
|
|
95
|
+
- 建议 POST 请求使用 `@RequestBody LeRequest<T>` 封装
|
|
96
|
+
|
|
97
|
+
#### 🟡 A9. 金额类型错误
|
|
98
|
+
```bash
|
|
99
|
+
Grep pattern: "Double|Float|double|float" path: [目标目录] glob: "*.java"
|
|
100
|
+
# 在命中行中检查是否涉及金额字段(amount/price/money/fee/cost)
|
|
101
|
+
```
|
|
102
|
+
- ❌ `Double/Float` 处理金额 → ✅ `Long`(分)或 `BigDecimal`
|
|
103
|
+
|
|
104
|
+
#### 🟡 A10. BigDecimal 比较错误
|
|
105
|
+
```bash
|
|
106
|
+
Grep pattern: "BigDecimal.*==|==.*BigDecimal" path: [目标目录] glob: "*.java"
|
|
107
|
+
```
|
|
108
|
+
- ❌ `bigDecimal1 == bigDecimal2` → ✅ `bigDecimal1.compareTo(bigDecimal2) == 0`
|
|
109
|
+
|
|
110
|
+
#### 🟡 A11. SELECT * 查询
|
|
111
|
+
```bash
|
|
112
|
+
Grep pattern: "SELECT \*|select \*" path: [目标目录] glob: "*.xml"
|
|
113
|
+
```
|
|
114
|
+
- ❌ `SELECT *` → ✅ 明确列出需要的字段
|
|
115
|
+
|
|
116
|
+
#### 🟡 A12. SQL 注入风险
|
|
117
|
+
```bash
|
|
118
|
+
Grep pattern: '\$\{' path: [目标目录] glob: "*.xml"
|
|
119
|
+
```
|
|
120
|
+
- ❌ `${}` 拼接参数 → ✅ `#{}` 参数化查询(ORDER BY 等特殊场景除外)
|
|
121
|
+
|
|
122
|
+
#### 🟡 A13. 国际化异常
|
|
123
|
+
```bash
|
|
124
|
+
Grep pattern: 'new LeException\("[^"]*[\u4e00-\u9fa5]' path: [目标目录] glob: "*.java"
|
|
125
|
+
```
|
|
126
|
+
- 建议使用 `I18n.getMessage()` 替代硬编码中文
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### Step B: 代码逻辑审查(Read 逐文件检查)
|
|
131
|
+
|
|
132
|
+
对每个变更的 Java 文件执行 Read,按以下清单逐项审查。
|
|
133
|
+
|
|
134
|
+
#### Java 必检项(所有 Java 文件)
|
|
135
|
+
|
|
136
|
+
| # | 检查项 | 检查要点 | 严重级 |
|
|
137
|
+
|---|--------|---------|--------|
|
|
138
|
+
| B1 | **空指针风险** | `selectOne`/`getOne`/`selectById` 返回值是否有 null 判断;Optional 是否正确处理 | 🔴 |
|
|
139
|
+
| B2 | **参数校验** | 入参是否校验非空和合法性(`@NotNull`/`@NotEmpty`/`Objects.requireNonNull`/手动 if 判断) | 🔴 |
|
|
140
|
+
| B3 | **并发安全** | 查询+新增/查询+更新的组合操作是否有竞态条件;是否需要分布式锁 | 🔴 |
|
|
141
|
+
| B4 | **事务边界** | 多表写操作是否加了 `@Transactional(rollbackFor = Exception.class)` | 🔴 |
|
|
142
|
+
| B5 | **资源关闭** | Stream/IO流/数据库连接是否用 try-with-resources 或 finally 关闭 | 🔴 |
|
|
143
|
+
| B6 | **集合并发修改** | `forEach` 内是否有 remove/add 操作;应使用 `Iterator` 或 `removeIf` | 🔴 |
|
|
144
|
+
| B7 | **分页泄漏** | `PageMethod.startPage()` 是否紧贴查询语句,中间不能有其他 SQL 查询 | 🔴 |
|
|
145
|
+
|
|
146
|
+
#### Java 安全项
|
|
147
|
+
|
|
148
|
+
| # | 检查项 | 检查要点 | 严重级 |
|
|
149
|
+
|---|--------|---------|--------|
|
|
150
|
+
| B8 | **租户隔离(仅定时任务)** | 定时任务中是否使用 `Executors.doInTenant()`/`doInAllTenant()` 切换到商户库;普通接口默认在商户库,无需额外处理 | 🔴 |
|
|
151
|
+
| B9 | **SQL 注入** | 动态 SQL 是否使用参数化查询;拼接 SQL 是否转义 | 🔴 |
|
|
152
|
+
| B10 | **越权访问** | 删除/修改操作是否校验数据归属(检查 where 条件是否包含归属字段) | 🔴 |
|
|
153
|
+
| B11 | **敏感信息** | 日志中是否打印了密码、token、身份证、银行卡等敏感信息 | 🔴 |
|
|
154
|
+
| B12 | **批量操作限制** | 批量删除/更新是否限制了最大数量,防止误操作全表 | 🟡 |
|
|
155
|
+
|
|
156
|
+
#### Java 跨模块调用项
|
|
157
|
+
|
|
158
|
+
| # | 检查项 | 检查要点 | 严重级 |
|
|
159
|
+
|---|--------|---------|--------|
|
|
160
|
+
| B13 | **返回值兜底** | 返回 `List`/`Map` 时是否有空集合兜底(`Collections.emptyList()`),避免调用方 NPE | 🟡 |
|
|
161
|
+
| B14 | **集合参数防御** | 集合入参(`List`/`Set`)是否判空,空集合的 `IN()` 会导致 SQL 异常 | 🔴 |
|
|
162
|
+
| B15 | **异常透传** | 是否吞掉异常不抛出(空 catch 块);跨模块调用需要明确的异常传递 | 🔴 |
|
|
163
|
+
| B16 | **日志追踪** | 关键操作或异常分支是否有日志(`log.info`/`log.error`),便于跨模块问题排查 | 🟡 |
|
|
164
|
+
|
|
165
|
+
#### Java 代码规范项
|
|
166
|
+
|
|
167
|
+
| # | 检查项 | 检查要点 | 严重级 |
|
|
168
|
+
|---|--------|---------|--------|
|
|
169
|
+
| B17 | **魔法值** | 是否存在未定义的常量(状态码 1/2/3 必须用枚举,字符串必须定义常量) | 🟡 |
|
|
170
|
+
| B18 | **方法长度** | 方法是否过长(>50 行),需要拆分为子方法 | 🔵 |
|
|
171
|
+
| B19 | **注释完整性** | 公共 API(Controller/Business 方法)是否有 JavaDoc 注释 | 🔵 |
|
|
172
|
+
| B20 | **空 catch 块** | catch 块是否为空或仅打印日志而不处理/不抛出 | 🟡 |
|
|
173
|
+
| B21 | **过时 API** | 是否使用了 `@Deprecated` 的方法或类 | 🔵 |
|
|
174
|
+
| B22 | **返回值一致性** | Controller 层是否统一返回 `LeResponse<T>`,不能裸返回 | 🟡 |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
#### MyBatis XML 检查(仅 XML 文件)
|
|
179
|
+
|
|
180
|
+
| # | 检查项 | 检查要点 | 严重级 |
|
|
181
|
+
|---|--------|---------|--------|
|
|
182
|
+
| X1 | **SQL 注入** | 使用 `${}` 而非 `#{}` 进行参数拼接(ORDER BY 等场景需白名单校验) | 🔴 |
|
|
183
|
+
| X2 | **IN 查询防护** | IN 查询是否用 `<foreach>` 且考虑集合为空的情况(空 IN 会 SQL 异常) | 🔴 |
|
|
184
|
+
| X3 | **动态 SQL 语法** | `<if>`/`<where>`/`<choose>` 标签使用是否正确,是否会产生多余的 AND/OR | 🟡 |
|
|
185
|
+
| X4 | **SELECT *** | 是否使用 `SELECT *`,应明确列出需要的字段 | 🟡 |
|
|
186
|
+
| X5 | **缺少 WHERE** | UPDATE/DELETE 是否缺少 WHERE 条件(全表操作风险) | 🔴 |
|
|
187
|
+
| X6 | **索引失效** | WHERE 条件是否对索引字段使用了函数(`DATE(crtime)`)或隐式类型转换 | 🟡 |
|
|
188
|
+
| X7 | **LIKE 前模糊** | `LIKE '%xxx%'` 或 `LIKE CONCAT('%', #{}, '%')` 前模糊导致全表扫描 | 🟡 |
|
|
189
|
+
| X8 | **大表无分页** | 大表查询是否遗漏分页,可能造成 OOM | 🟡 |
|
|
190
|
+
| X9 | **namespace 匹配** | namespace 是否与 Mapper 接口全限定名完全匹配 | 🔴 |
|
|
191
|
+
| X10 | **resultMap 映射** | 是否正确定义 resultMap,字段名和属性名是否对应 | 🟡 |
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### 本地检查结果展示
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
# 代码审查报告
|
|
199
|
+
|
|
200
|
+
审查范围: [变更文件列表]
|
|
201
|
+
|
|
202
|
+
## 🔴 严重问题(X 项)
|
|
203
|
+
1. [B1 空指针风险]
|
|
204
|
+
文件: OrderServiceImpl.java:42
|
|
205
|
+
问题: selectById 返回值未做 null 判断
|
|
206
|
+
修复: if (ObjectUtil.isNull(entity)) throw new LeException("数据不存在");
|
|
207
|
+
|
|
208
|
+
2. [A2 禁止 RuoYi 工具类]
|
|
209
|
+
文件: UserServiceImpl.java:15
|
|
210
|
+
问题: 使用了 MapstructUtils
|
|
211
|
+
修复: 替换为 BeanUtil.copyProperties()
|
|
212
|
+
|
|
213
|
+
## 🟡 警告问题(X 项)
|
|
214
|
+
...
|
|
215
|
+
|
|
216
|
+
## 🔵 建议(X 项)
|
|
217
|
+
...
|
|
218
|
+
|
|
219
|
+
## ✅ 通过项
|
|
220
|
+
- [x] A1 包名规范 (net.xnzn.core.*)
|
|
221
|
+
- [x] A3 审计字段正确 (crby/crtime/upby/uptime)
|
|
222
|
+
- [x] A4 del_flag 语义正确 (2=正常)
|
|
223
|
+
- [x] B8 租户隔离正确
|
|
224
|
+
...
|
|
225
|
+
|
|
226
|
+
结论: ✅ 通过 / ⚠️ 需修复 X 项 / ❌ 不通过
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
如果全部通过 → 展示"本地检查通过",询问是否需要 Codex 深度审查。
|
|
230
|
+
如果有问题 → 先修复严重问题,修复后再询问是否需要 Codex 深度审查。
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Phase 3: Codex 深度审查(可选)
|
|
235
|
+
|
|
236
|
+
> 依赖 `collaborating-with-codex` skill 的 `codex_bridge.py` 脚本。
|
|
237
|
+
> Codex 擅长发现本地规则难以覆盖的**逻辑 Bug、复杂并发问题、架构缺陷**。
|
|
238
|
+
|
|
239
|
+
Phase 2 完成后询问用户:"是否需要 Codex 深度审查?"
|
|
240
|
+
- 用户同意 → 执行以下流程
|
|
241
|
+
- 用户拒绝 → 跳到 Phase 5
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
python3 .claude/skills/collaborating-with-codex/scripts/codex_bridge.py \
|
|
245
|
+
--cd . \
|
|
246
|
+
--sandbox read-only \
|
|
247
|
+
--PROMPT "Review the following changed files for code quality issues:
|
|
248
|
+
|
|
249
|
+
FILES TO REVIEW:
|
|
250
|
+
{变更文件列表,含相对路径}
|
|
251
|
+
|
|
252
|
+
REVIEW FOCUS (beyond basic lint):
|
|
253
|
+
1. Logic bugs: race conditions, off-by-one, incorrect state transitions, edge cases
|
|
254
|
+
2. Security: privilege escalation, data leakage across tenants, missing auth checks
|
|
255
|
+
3. Architecture: Controller calling Mapper directly, Business layer bypassed, circular dependencies
|
|
256
|
+
4. Performance: N+1 queries, missing pagination on large tables, unnecessary DB calls in loops
|
|
257
|
+
5. Concurrency: check-then-act without locking, shared mutable state, CompletableFuture error handling
|
|
258
|
+
|
|
259
|
+
PROJECT CONTEXT:
|
|
260
|
+
- Package: net.xnzn.core.* (NOT org.dromara.*)
|
|
261
|
+
- 4-layer: Controller → Business → Service → Mapper
|
|
262
|
+
- Dual-database: tenant DB is default (by MERCHANT-ID header); only scheduled tasks need Executors.doInTenant()/doInAllTenant() to switch; Executors.doInSystem() for system DB access
|
|
263
|
+
- Audit fields: crby/crtime/upby/uptime
|
|
264
|
+
- del_flag: 1=deleted, 2=normal
|
|
265
|
+
- Exception: LeException (NOT ServiceException)
|
|
266
|
+
- Object copy: BeanUtil.copyProperties() (NOT MapstructUtils)
|
|
267
|
+
- Amount: stored as Long (fen/cents), NOT Double/Float
|
|
268
|
+
- Pagination: PageMethod.startPage() must be immediately before query
|
|
269
|
+
|
|
270
|
+
OUTPUT FORMAT:
|
|
271
|
+
For each issue:
|
|
272
|
+
- [SEVERITY] CRITICAL / WARNING / SUGGESTION
|
|
273
|
+
- [FILE] filepath:line_number
|
|
274
|
+
- [ISSUE] Description
|
|
275
|
+
- [FIX] Recommended fix
|
|
276
|
+
|
|
277
|
+
If no issues: ALL CLEAR
|
|
278
|
+
|
|
279
|
+
IMPORTANT: All comments in Chinese, code/paths in English."
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**关键约束**:
|
|
283
|
+
- 始终使用 `--sandbox read-only`,Codex 不直接修改文件
|
|
284
|
+
- 变更文件过多时(>10 个),按模块分批审查
|
|
285
|
+
- 使用 `run_in_background` 避免阻塞
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Phase 4: 用户确认后修复
|
|
290
|
+
|
|
291
|
+
合并 Phase 2 和 Phase 3 的所有问题,等待用户确认:
|
|
292
|
+
- **全部修复**:"修复所有问题" → 逐个修复所有 🔴 + 🟡
|
|
293
|
+
- **选择性修复**:"只修复严重问题" → 仅修复 🔴
|
|
294
|
+
- **跳过**:"不需要修复" → 终止
|
|
295
|
+
|
|
296
|
+
修复时:
|
|
297
|
+
1. 按文件逐个修复,使用 Edit 工具
|
|
298
|
+
2. 每修复一个文件,简要说明改动
|
|
299
|
+
3. 🔵 建议级别默认跳过,除非用户明确要求
|
|
300
|
+
4. 修复完成后运行 `git diff` 展示所有变更
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Phase 5: 最终确认
|
|
305
|
+
|
|
306
|
+
修复完成后询问:"是否需要再次审查确认?"
|
|
307
|
+
- 如果用户同意 → 回到 Phase 2 重新审查
|
|
308
|
+
- 如果用户拒绝 → 输出最终结论并终止
|
|
309
|
+
|
|
310
|
+
```
|
|
311
|
+
结论: ✅ 通过 / ⚠️ 需修复 / ❌ 不通过
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
## 前端审查(如涉及前端文件变更)
|
|
317
|
+
|
|
318
|
+
前端项目路径:`/Users/xujiajun/Developer/frontProj/web`
|
|
319
|
+
|
|
320
|
+
| # | 检查项 | 检查要点 |
|
|
321
|
+
|---|--------|---------|
|
|
322
|
+
| F1 | 响应码 | 成功码是 `10000`(不是 200) |
|
|
323
|
+
| F2 | Token | `Admin-Token`(localStorage) |
|
|
324
|
+
| F3 | 租户头 | `MERCHANT-ID`(请求头) |
|
|
325
|
+
| F4 | 金额显示 | 后端返回分,前端用 `money()` 转元 |
|
|
326
|
+
| F5 | 权限指令 | 按钮权限使用 `v-hasPerm` |
|
|
327
|
+
| F6 | 加密 | 敏感字段使用 SM4 加密 |
|
|
@@ -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
|
|------|------|
|