Skip to main content

code-reviewer

Lingman-Starter 多端代码审查助手。当用户需要:(1) 检查后端或前端代码是否符合公司规范 (2) 审查 CRUD 分层、命名、权限、异常与事务 (3) 审查管理后台 Web 页面 (4) 审查 uni-app 页面、组件、API 接入、Pinia、跨端兼容和资源生命周期 (5) 发现空指针、SQL 注入、越权和敏感信息风险 时触发。审查前必须先识别项目类型并加载对应规范。不要在以下场景触发:生成代码、生成 SQL、单纯运行时错误排查。

Datos de origen

Repositorio
lingmancn/lm-skills
Última actividad en el origen
12 de agosto de 2026 a las 02:56
Idioma detectado de SKILL.md
chino
Estrellas
1
Forks
0

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
2 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
code-reviewer
description
Lingman-Starter 多端代码审查助手。当用户需要:(1) 检查后端或前端代码是否符合公司规范 (2) 审查 CRUD 分层、命名、权限、异常与事务 (3) 审查管理后台 Web 页面 (4) 审查 uni-app 页面、组件、API 接入、Pinia、跨端兼容和资源生命周期 (5) 发现空指针、SQL 注入、越权和敏感信息风险 时触发。审查前必须先识别项目类型并加载对应规范。不要在以下场景触发:生成代码、生成 SQL、单纯运行时错误排查。
# 代码审查指南 ## 审查入口与项目分流 审查前先识别目标,不能看到 `.vue` 就默认按管理后台审查: | 类型 | 主要证据 | 使用规范 | |---|---|---| | Java 后端 | `pom.xml`、Spring/MyBatis、`src/main/java` | [framework.md](../lingman-core/framework.md) | | 管理后台 Web | `src/views`、Element Plus、`@lingman/yd` | [frontend-spec.md](../lingman-core/frontend/frontend-spec.md) | | uni-app | `@dcloudio/*`、pages/manifest、`uni.scss`、小程序/APP | [uni-app-spec.md](../lingman-core/uni-app/uni-app-spec.md) | | p708 或相似项目 | uni-app 且命中对应请求、TabBar、视频架构 | [p708-verified-patterns.md](../lingman-core/uni-app/p708-verified-patterns.md) | 混合仓库按变更文件路径分别审查,禁止共用错误模板。完整检查项见 [review-checklist.md](references/review-checklist.md)。 ## 审查维度 | 维度 | 检查项 | 严重程度 | |------|--------|---------| | **规范合规** | 包名、类名、URL 是否符合约定 | 高 | | **分层正确** | Controller/Service/Mapper 是否越层调用 | 高 | | **参数校验** | 入参是否有 `@Valid` / `@NotNull` | 高 | | **权限控制** | 管理端接口是否有 `@PreAuthorize` | 高 | | **异常处理** | 是否使用 `throw exception(ErrorCode)` | 中 | | **事务配置** | 写操作是否有 `@Transactional` | 中 | | **空值安全** | 数据库查询结果是否判空 | 中 | | **SQL 安全** | 是否使用 `${}` 拼接 SQL | 高 | | **返回格式** | 是否使用 `CommonResult<T>` 包装 | 中 | | **VO 隔离** | Controller 是否直接返回 DO | 高 | | **日志规范** | 是否用 `@Slf4j`、套用 `[线程id][操作人][模块][动作] key={}` 公式、含唯一 ID、异常末位、未打大对象、未拼字符串、未泄露敏感数据 | 中 | > **管理后台 Web 审查维度**:仅在项目类型确认后使用,详见 [frontend-spec.md](../lingman-core/frontend/frontend-spec.md) > - API 层:是否从 `api/auto/` 导入自动生成的 API 对象(`import { ApiAppXxxAppAdminApiAuto }`),禁止直接手写 URL > - **API 自动生成文件保护**:`src/api/auto/` 下的文件是否为命令自动生成,是否存在手动修改的痕迹(如手动增删接口、调整参数类型等) > - 列表页:是否使用 `useTable` hook 管理列表状态,而非手动维护 `loading`/`total`/`list` > - 列表页搜索表单:字段 ≥ 2 个时是否使用 `<Search>` 组件;仅 1 个搜索字段或需自定义样式时是否合理回退 `el-form`(详见 frontend-spec.md「搜索表单」说明) > - 表单校验:`FormRules` 是否与后端 `@Valid` 规则一致(必填、格式、长度) > - 错误处理:是否使用 `useMessage()` 或 `ElMessage`/`ElMessageBox`,异常捕获是否完整(`try/finally`) > - 字典使用:表格中字典列是否使用 `<DictTag>`,下拉框是否使用 `getDictOptions` / `getIntDictOptions` > - **组件/工具优先使用 `@lingman/yd`**: > - 列表表格是否优先使用 `<Table>` 组件,而非直接使用 `<el-table>` > - 弹窗是否优先使用 `<Dialog>` 组件(或 `el-dialog`),避免自己封装弹窗 > - 日期格式化是否优先使用 `formatDate` / `dateFormatter`,避免手写日期转换 > - 文件下载是否优先使用 `download.excel` / `download.word` 等,避免自己封装下载 > - 字典查询是否优先使用 `getDictOptions` / `getDictLabel`,避免自己写字典查询逻辑 > - 表单校验是否优先使用 `useValidator()` 的 `required()` / `lengthRange()`,避免自己写通用校验规则 > - UUID/随机字符串是否优先使用 `generateUUID()` / `generateRandomStr()`,避免自己写生成逻辑 > - 树形操作是否优先使用 `eachTree` / `findNode` / `treeToList`,避免自己写树遍历 > - Token 操作是否优先使用 `getAccessToken()` / `setToken()`,避免自己写 Token 读写 > - 样式规范:是否优先使用 UnoCSS 原子类,组件样式是否加 `scoped`;数值表示间距、尺寸、宽高、`gap`、定位或平移偏移时是否显式带 CSS 单位,语义关键字、命名令牌、比例/分数等排除项按 [frontend-spec.md](../lingman-core/frontend/frontend-spec.md)「11.1 优先使用 UnoCSS 原子类」执行 > - 权限控制:按钮是否使用 `v-hasPermi`,JS 逻辑中是否使用 `checkPermi` > > **uni-app 审查维度**:仅在确认是 uni-app 后使用,详见 [uni-app-spec.md](../lingman-core/uni-app/uni-app-spec.md) 和 [review-checklist.md](references/review-checklist.md) > - 自动生成目录与 pages/manifest 配置源是否正确,未手改受保护文件 > - TabBar 导航、页面生命周期、Pinia 状态和请求桥接是否复用项目能力 > - APP/H5/小程序条件编译是否隔离,浏览器/平台 API 未越界 > - Wot/项目 UI 库、UnoCSS/rpx、主题变量、安全区和动态图标 safelist 是否正确 > - 视频、WebRTC、MediaStream、定时器和监听器是否在隐藏/卸载时释放 > - APP 优先任务是否只验证了 H5,未验证项是否如实说明 ## 审查清单 ### Controller 层 - [ ] 类上有 `@Tag` + `@RestController` + `@RequestMapping` - [ ] 管理端 URL 前缀正确:`/admin/{biz}`(管理端)、`/app/{biz}`(用户端) - [ ] 类上有 `@Validated` - [ ] 管理端方法有 `@PreAuthorize("@ss.hasPermission('xxx')")` - [ ] 入参有 `@Valid`(POST/PUT) - [ ] 接口路径全局唯一,无"同路径不同请求方式"冲突 - [ ] 非 GET 请求(POST/PUT/DELETE/PATCH)一律使用 `@RequestBody`,未误用 `@RequestParam` / `@PathVariable` - [ ] 单 ID 删除/操作统一使用公共类 `AdminDeleteReqVO`(`common_vo/AdminDeleteReqVO.java`),字段名为 `id`,未自行定义 `{Name}DeleteReqVO` - [ ] 返回类型为 `CommonResult<T>` - [ ] Swagger 注解完整:`@Operation(summary = "...")` ### Service 层 - [ ] 接口定义在 `service/admin/` 或 `service/app/` - [ ] 实现类在 `service/admin/impl/` 或 `service/app/impl/` - [ ] 实现类有 `@Service` - [ ] 写操作有 `@Transactional(rollbackFor = Exception.class)` - [ ] 使用 `throw exception(ErrorCodeConstants.XXX)` 抛业务异常 - [ ] 查询结果判空后再使用 ### 日志 - [ ] 统一使用 Lombok `@Slf4j`(字段名 `log`),未手写 `LoggerFactory.getLogger(...)` - [ ] **套用结构化公式** `[线程id] [操作人] [业务模块] [业务动作], key={}, ...`,带四要素前缀 - [ ] 每条日志**包含唯一标识符(ID)**,可追溯具体记录 - [ ] 用 `{}` 占位符,未用字符串拼接 - [ ] 异常对象作为最后一个参数,未拼进消息、未吞堆栈(不只 `e.getMessage()`) - [ ] 未打印完整大对象(DO/VO/List/Map),只打关键 ID 或摘要 - [ ] 未写自然语言长句 - [ ] 昂贵操作用 `isDebugEnabled()` / `isInfoEnabled()` 守卫 - [ ] 日志级别合理(ERROR/WARN/INFO/DEBUG) - [ ] 未记录密码、token、身份证、手机号、银行卡等敏感数据 - [ ] 循环/高频路径未打 `INFO` 及以上日志 ### VO 层 - [ ] 有 `@Schema(description = "...")` - [ ] 分页 VO 继承 `PageParam` - [ ] 时间字段有 `@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")` - [ ] 校验注解使用正确:`@NotBlank`、`@NotNull`、`@Size` ### Mapper/DO 层 - [ ] DO 继承 `BaseDO` - [ ] `@TableName` 命名正确:`t_xxx` - [ ] Mapper 继承 `BaseMapperX<T>` 且有 `@Mapper` - [ ] 字段用 `@TableField` 映射 ## 常见问题及修复 ### 问题:Controller 直接返回 DO ```java // 错误 public CommonResult<AnnouncementDO> get(Long id) { return CommonResult.success(announcementMapper.selectById(id)); } // 正确 public CommonResult<AnnouncementRespVO> get(Long id) { return CommonResult.success(announcementService.get(id)); } ``` ### 问题:缺少权限注解 ```java // 错误 @GetMapping("/delete") public CommonResult<Boolean> delete(...) { } // 正确 @GetMapping("/delete") @PreAuthorize("@ss.hasPermission('app:announcement:delete')") public CommonResult<Boolean> delete(...) { } ``` ### 问题:未判空直接使用 ```java // 错误 AdminUserDO user = adminUserMapper.selectById(userId); return user.getNickname(); // 正确 AdminUserDO user = adminUserMapper.selectById(userId); if (user == null) { throw exception(USER_NOT_EXISTS); } return user.getNickname(); ``` ### 问题:需要幂等但未加注解 ```java // 以下场景需要考虑幂等: // - 用户可能重复点击的提交操作(创建、支付、审批提交) // - 网络重试可能导致重复请求的场景 // - 表单提交、按钮点击类接口 // 错误:重复点击可能产生重复数据 @PostMapping("/submit") public CommonResult<Long> submit(@RequestBody XxxReqVO reqVO) { } // 正确:添加幂等保护 @Idempotent(timeout = 10, timeUnit = TimeUnit.SECONDS, keyResolver = UserIdempotentKeyResolver.class) @PostMapping("/submit") public CommonResult<Long> submit(@RequestBody XxxReqVO reqVO) { } // 无需幂等的场景:查询、列表、获取详情等幂等操作 @PostMapping("/page") public CommonResult<PageResult<XxxRespVO>> page(@RequestBody XxxPageReqVO reqVO) { } ``` ### 问题:VO 缺少数据翻译 ```java // 错误:字典值直接返回数字,前端无法展示文本 @Data public class XxxRespVO { private Integer status; // 前端看到 0/1,不知道含义 } // 正确:使用 @Trans 自动翻译 @Data public class XxxRespVO implements VO { @Trans(type = TransType.SIMPLE, target = DictDataDO.class, fields = "label", ref = "statusName") private Integer status; private String statusName; // 自动填充为"启用"/"禁用" } ``` ### 问题:忘记清除审计字段 ```java // 错误:更新时未清除 BaseDO 的审计字段 XxxDO updateObj = xxxConvert.convert(reqVO); xxxMapper.updateById(updateObj); // 正确:先 clean() 再更新 XxxDO updateObj = xxxConvert.convert(reqVO); updateObj.clean(); xxxMapper.updateById(updateObj); ``` ### 问题:未注册数据权限 ```java // 错误:新实体没有在 AppDataPermissionConfiguration 中注册 // 导致数据权限拦截器无法过滤该实体的查询 // 正确:在 AppDataPermissionConfiguration 中添加 @Bean public DeptDataPermissionRuleCustomizer appDeptDataPermissionRuleCustomizer() { return rule -> { rule.addUserColumn(XxxDO.class, "user_id"); rule.addDeptColumn(XxxDO.class, "dept_id"); }; } ``` ### 问题:时间字段缺少格式化 ```java // 错误:时间返回为数组格式 [2026, 1, 1, 12, 0, 0] private LocalDateTime createTime; // 正确:添加 @JsonFormat @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime createTime; ``` ### 问题:日志不符合结构化公式(缺四要素 / 长句 / 拼接 / 打印大对象) ```java // ❌ 错误:自然语言长句 + 字符串拼接 + 吞堆栈 + 打印大对象,无法追溯来源 @Service public class XxxServiceImpl implements XxxService { public void doSomething(Long id) { log.info("处理完成了,id=" + id + ",对象是" + xxxDO); log.error("处理失败: " + e.getMessage()); } } // ✅ 正确:[线程id] [操作人] [业务模块] [业务动作] + 唯一 ID + 异常末位 import lombok.extern.slf4j.Slf4j; @Slf4j @Service public class XxxServiceImpl implements XxxService { public void doSomething(Long id) { log.info("[{}] [{}] [XXX模块] [处理XXX], id={}", Thread.currentThread().threadId(), SecurityFrameworkUtils.getLoginUserId(), id); log.error("[{}] [{}] [XXX模块] [处理失败], id={}", Thread.currentThread().threadId(), SecurityFrameworkUtils.getLoginUserId(), id, e); } } ``` > 五要素(线程id + 操作人 + 模块 + 动作 + 唯一ID)齐全,才能让人 grep 追溯到具体来源。 ## 参考文档 | 场景 | 参考文档 | |------|----------| | 审查检查项清单 | [review-checklist.md](references/review-checklist.md) | | 后端框架规范 | [framework.md](../lingman-core/framework.md) | | 管理后台 Web 规范 | [frontend-spec.md](../lingman-core/frontend/frontend-spec.md) | | uni-app 通用规范 | [uni-app-spec.md](../lingman-core/uni-app/uni-app-spec.md) | | p708 已验证模式 | [p708-verified-patterns.md](../lingman-core/uni-app/p708-verified-patterns.md) | | 代码模板 | [code-template.md](../crud-generator/references/code-template.md) |
Ver en GitHub