add 增加 ai编程支持 支持codex与claude的skill

This commit is contained in:
疯狂的狮子Li
2026-03-30 17:31:31 +08:00
parent 175a02f49c
commit 19abd82fa3
9 changed files with 688 additions and 0 deletions
@@ -0,0 +1,221 @@
# 后端约定
## 优先参考的代码来源
- `ruoyi-modules/ruoyi-generator/src/main/resources/vm/java/*.vm`
- `ruoyi-modules/ruoyi-demo/...`
- `ruoyi-modules/ruoyi-system/...`
- `ruoyi-common/ruoyi-common-mybatis/...`
## 决策顺序
写代码时按下面顺序取样:
1. 当前业务模块下最近似实现。
2. 当前仓库公共能力模块中的统一约定。
3. generator 模板。
4. 通用 Spring / MyBatis-Plus 默认习惯。
如果规则冲突,优先相信当前仓库真实代码。
## 分层结构
标准 CRUD 代码应优先遵循下面这套结构:
- `domain/Entity.java`
- `domain/bo/EntityBo.java`
- `domain/vo/EntityVo.java`
- `mapper/EntityMapper.java`
- `service/IEntityService.java`
- `service/impl/EntityServiceImpl.java`
- `controller/EntityController.java`
## Entity 规则
- 除非所在模块明显另有约定,否则实体类继承 `org.dromara.common.mybatis.core.domain.BaseEntity`
- 使用 Lombok `@Data``@EqualsAndHashCode(callSuper = true)`
- 使用 `@TableName("table_name")`
- 主键使用 `@TableId`
- 存在 `delFlag` 时保留 `@TableLogic`,存在乐观锁字段时保留 `@Version`
- 如果附近实体已经使用 `@OrderBy` 等额外注解,应继续保持。
## BO 规则
- 实现 `Serializable`
- 添加 `@AutoMapper(target = Entity.class, reverseConvertGenerate = false)`
- 请求专用字段、查询专用字段放在 BO 中,包括 `params`
- 在生成器或附近代码已有分组校验时,继续使用:`AddGroup``EditGroup``QueryGroup`
- `@Xss``@Email``@Size``@NotBlank``@NotNull` 要按真实业务语义添加,不要一股脑全套上。
- 查询存在日期范围或扩展条件时,保留 `params = new HashMap<>()`
## VO 规则
- 实现 `Serializable`
- 添加 `@AutoMapper(target = Entity.class)`
- 生成器风格的导出对象通常带 `@ExcelIgnoreUnannotated`
- `@ExcelProperty``@ExcelDictFormat``ExcelDictConvert``@ExcelRequired``@ExcelNotation``@DateTimeFormat` 只在导入导出场景下使用。
- 如果附近代码会把 ID 翻译成展示字段,沿用 `@Translation(type = TransConstant.USER_ID_TO_NAME, mapper = "createBy")` 这类写法。
- 展示型派生字段放在 VO,不放在 Entity。
## Mapper 规则
- 默认形式是 `interface XxxMapper extends BaseMapperPlus<Xxx, XxxVo>`
- 不要为简单的 entity 转 vo 手写重复代码,优先依赖 `BaseMapperPlus`
- 模块已经使用 `@DataPermission` 时,在重写方法和自定义查询上继续保留。
- 复杂模块里 mapper 可能同时继承 `MPJBaseMapper<Entity>` 并使用 `JoinWrappers.lambda(...)`,遇到这种风格要延续,不要换一种写法。
- 只有在 `selectVoList/selectVoPage` 不够用时,才补 XML 或自定义 mapper 方法。
### Mapper 建议结构
标准 mapper 一般按这个顺序组织:
1. 接口声明
2. 默认查询方法
3. 自定义分页或列表方法
4. 特殊数据权限重写
5. 辅助构造方法
### 什么时候需要 XML
- 复杂联表 SQL 无法仅靠 wrapper 清晰表达时。
- 需要手写查询列和结果映射时。
- 项目当前模块已经大量使用 XML 时。
如果 `BaseMapperPlus + wrapper` 已足够,优先不要补 XML。
## Service 规则
- 类声明通常是 `@RequiredArgsConstructor``@Service`,按需补 `@Slf4j`
- mapper 注入字段命名为 `private final XxxMapper baseMapper;`
- 读操作通常返回 `Vo``List<Vo>``PageResult<Vo>`
- BO 转实体用 `MapstructUtils.convert(bo, Entity.class)`
- 查询条件优先用 `LambdaQueryWrapper``Wrappers.lambdaQuery()`
- 在 wrapper 条件里直接写 `StringUtils.isNotBlank(...)` 和 null 判断。
- 分页查询优先采用:
`Page<Vo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);`
`return PageResult.build(result.getRecords(), result.getTotal());`
- 生成器风格模块保留 `validEntityBeforeSave(...)` 这种扩展点。
- 多表写操作使用 `@Transactional(rollbackFor = Exception.class)`
- 明确的业务失败,尤其是权限、数据完整性、删除校验,使用 `ServiceException`
- 不要绕过模块现有的数据权限、角色校验、删除前校验。
### Service 建议结构
标准 service impl 一般按下面顺序组织:
1. 查询单条
2. 分页查询
3. 列表查询
4. 构建查询条件
5. 新增
6. 修改
7. 保存前校验
8. 删除前校验与删除
9. 其他扩展业务方法
### 查询逻辑建议
- 单表查询优先使用 `LambdaQueryWrapper`
- 条件判断直接放在 wrapper 上,不要额外写大量 if 套壳。
- 日期范围统一从 `bo.getParams()` 取 begin/end。
- 复杂联表查询优先查同模块是否已有 MPJ 风格可复用。
### 写入逻辑建议
- BO 转实体统一走 `MapstructUtils.convert`
- 批量关系维护时优先拆成私有方法,例如角色、岗位、用户关联。
- 修改前优先保留已有防误删、防越权、防并发覆盖逻辑。
## Controller 规则
- 继承 `BaseController`
- 类上通常带 `@Validated``@RestController``@RequiredArgsConstructor``@RequestMapping`
- 返回值使用 `R<T>``R<Void>`
- 标准 CRUD 接口通常是:`GET /list``POST /export``GET /{id}``POST``PUT``DELETE /{ids}`
- `@SaCheckPermission` 权限格式遵循 `${module}:${business}:${action}`
- 写操作、导入导出接口通常加 `@Log(title = "...", businessType = BusinessType.X)`
- 附近接口已有防重时,写接口继续使用 `@RepeatSubmit`
- 适合分组校验时,使用 `@Validated(AddGroup.class)``@Validated(EditGroup.class)`
- 特殊接口直接复用模块内现成做法,例如导入导出、`@ApiEncrypt`、multipart 上传、数据权限检查、写入前唯一性校验。
### Controller 建议结构
标准 controller 一般按下面顺序组织:
1. 列表
2. 导出
3. 详情
4. 新增
5. 修改
6. 删除
7. 特殊接口
### Controller 边界
- controller 负责接参、校验、权限、日志、返回值转换。
- 重业务逻辑尽量放 service,不要在 controller 里堆长逻辑。
- 但前置权限检查、唯一性提示、显式业务失败提示可以留在 controller,前提是同模块已有这种习惯。
## 查询与工具规则
- 分页统一使用 `PageQuery``PageResult`,不要无故引入新的分页 DTO。
- 优先使用项目工具类:`MapstructUtils``StringUtils``StreamUtils``ValidatorUtils``SpringUtils``RedisUtils`
- 数组转列表按附近代码习惯使用 `List.of(ids)``Arrays.asList(ids)`
- 日期范围查询通常从 `bo.getParams()` 中读取 `beginTime``endTime``beginFieldName``endFieldName`
## 前后端联动规则
- 新增后端接口时,路径和权限前缀尽量保持 generator 约定,方便前端目录和 API 命名同步。
- 新增日期范围查询时,记得保留 `bo.params` 结构,避免前端 `addDateRange` 无法对接。
- 导出接口通常保持 `POST /export` 风格,便于前端直接复用现有下载逻辑。
- 批量删除接口通常使用 `DELETE /{ids}`,便于前端直接传数组或逗号串。
## 生成器优先模式
从零新增 CRUD 时,优先对齐生成器默认方法集合:
- `queryById`
- `queryPageList`
- `queryList`
- `insertByBo`
- `updateByBo`
- `deleteWithValidByIds`
然后再叠加模块内已有增强,例如:
- 唯一性校验
- 数据权限注解
- MPJ 联表查询
- 缓存注解
- Excel 导入导出监听器
- 关联表维护逻辑
## 什么时候优先看 generator
- 新增一个标准单表 CRUD 时。
- 只有表结构和基本接口需求,没有现成业务模块可参考时。
- 需要快速补齐整套骨架代码时。
## 什么时候优先看现有模块
- 目标模块已经有类似业务。
- 涉及数据权限、联表、缓存、角色岗位关系、导入导出、工作流扩展时。
- 任务是“修改已有模块”而不是“新建模块”时。
## 避免事项
- 不要在 controller 里直接暴露 entity 代替 BO/VO。
- 不要给新的管理接口漏掉权限注解。
- 没有明确必要时,不要从 `BaseMapperPlus` 风格退回手工映射。
- 前端查询页用了日期范围时,不要删掉后端 `params` 相关处理。
- 不要把 `ruoyi-system` 这类复杂逻辑强行简化成生成器式单表 CRUD。
## 交付前自检
交付前至少检查这些点:
- CRUD 主链路是否完整。
- BO / VO / Entity 职责是否清晰。
- 分页、查询、删除校验是否与前端对得上。
- 权限、日志、防重、事务是否遗漏。
- 是否只是 generator 裸产物,如果是,需要继续补齐同模块已有增强。
@@ -0,0 +1,101 @@
# 使用案例
## 案例 1:新增标准单表 CRUD
### 用户提问示例
```text
使用 $ruoyi-plus-ai-coding 在 system 模块新增一个 client 管理的标准 CRUD。
请参考 generator 模板和现有 system 模块写法,补齐 entity、bo、vo、mapper、service、controller。
```
### 期望执行方式
- 先读 generator 的 `domain/bo/vo/service/serviceImpl/controller` 模板。
- 再读 `system` 模块里最接近的现有管理模块。
- 先生成骨架,再补权限、日志、校验、导出等细节。
## 案例 2:修改已有复杂模块
### 用户提问示例
```text
使用 $ruoyi-plus-ai-coding 修改 workflow/category 的查询和导出逻辑,保持现有模块风格,不要简化成模板式单表 CRUD。
```
### 期望执行方式
- 先读当前 workflow 模块同类代码。
- 判断这是“复杂模块增强”,不是“从零生成”。
- 增量修改原逻辑,不要重写整个 service/controller。
## 案例 3:补唯一性校验与删除前校验
### 用户提问示例
```text
使用 $ruoyi-plus-ai-coding 为 demo/demo 模块补充新增和修改时的唯一性校验,并补充删除前校验。
```
### 期望执行方式
- 优先修改 `validEntityBeforeSave(...)`
- 根据模块现有风格补 `ServiceException` 或显式失败返回。
- 删除逻辑只补必要校验,不重构整套 CRUD。
## 案例 4:补数据权限与联表查询
### 用户提问示例
```text
使用 $ruoyi-plus-ai-coding 为 system 模块某个列表查询增加部门数据权限和联表字段返回,参考现有 user mapper 的 MPJ 与 DataPermission 写法。
```
### 期望执行方式
- 先看 `SysUserMapper` 和相关 service。
- 判断需要 `BaseMapperPlus` 重写还是 MPJ 联表。
- 保持权限注解和联表风格一致。
## 案例 5:新增后端接口并同步前端骨架
### 用户提问示例
```text
使用 $ruoyi-plus-ai-coding 为 monitor/cache 新增一个导出接口,并同步补齐前端 api/types 调用骨架。
```
### 期望执行方式
- 先补后端 `controller/service`
- 再根据后端路由补前端 `src/api` 或 generator 风格的前端骨架。
- 保证导出接口路径和前端下载调用一致。
## 案例 6:推荐的高质量任务描述
下面这种描述最容易得到稳定结果:
```text
使用 $ruoyi-plus-ai-coding 在 workflow 模块新增一个标准列表管理功能:
1. 需要分页、导出、详情、增删改
2. 查询包含状态和创建时间范围
3. 保持现有 workflow 模块风格
4. 参考 generator 模板生成基础骨架
5. 删除前需要做业务校验
```
## 不推荐的任务描述
下面这种描述太模糊,容易导致产物偏离项目:
```text
帮我加个后端接口
```
更好的写法至少要补充:
- 模块名
- 表或业务名
- 是新增还是修改
- 是否需要分页、导出、权限、数据范围、联表
- 想参考哪个现有模块
@@ -0,0 +1,71 @@
# 前端约定
## 优先参考的代码来源
- `ruoyi-modules/ruoyi-generator/src/main/resources/vm/ts/*.vm`
- `ruoyi-modules/ruoyi-generator/src/main/resources/vm/vue/*.vm`
- 前端工程中与目标模块最接近的现有页面
如果任务涉及前端,先看仓库里实际使用的前端目录和同类页面,不要直接套通用 Vue 习惯。
## API 文件规则
-`@/utils/request` 引入 `request`
-`axios` 引入 `AxiosPromise`
-`@/api/<module>/<business>/types` 引入本模块类型。
- 列表接口通常返回 `AxiosPromise<PageResult<Vo>>`
- 常规接口命名和路由保持:
`listXxx` -> `GET /<module>/<business>/list`
`getXxx` -> `GET /<module>/<business>/{id}`
`addXxx` -> `POST /<module>/<business>`
`updateXxx` -> `PUT /<module>/<business>`
`delXxx` -> `DELETE /<module>/<business>/{id or ids}`
## 类型文件规则
- 定义 `VO``Form``Query`
- `Form` 通常继承 `BaseEntity`
- 非树表页面的 `Query` 通常继承 `PageQuery`
- 各类 ID 字段通常用 `string | number`
- Java 数值类型通常映射为 `number`
- Boolean 映射为 `boolean`
- 其他生成字段默认多为 `string`
- 存在日期范围查询时保留 `params?: any`
## Vue 页面规则
- 使用 `<script setup lang="ts">`
- 常见 import 来自本模块 API 和本地 `types`
- 通过 `getCurrentInstance()``proxy`,使用项目注入的公共工具。
- 字典通常通过 `proxy?.useDict(...)` 获取,再用 `toRefs` 解构。
- 常见状态包括:列表数组、`loading``buttonLoading``showSearch``ids``single``multiple``total`
- 查询和表单状态通常放在 `reactive<PageData<Form, Query>>({...})` 中。
- 弹窗状态通常使用 `dialog.visible``dialog.title`
- 表单引用通常命名为 `queryFormRef``<business>FormRef`
## 页面行为规则
- `getList` 负责设置 loading、处理日期范围参数、调用列表接口、回填 `rows``total`
- `handleQuery` 通常先把 `pageNum` 重置为 `1`,再重新查询。
- `resetQuery` 负责清空日期范围和查询表单,然后重新加载。
- `handleSelectionChange` 更新 `ids``single``multiple`
- `handleAdd` 先重置表单,再打开弹窗。
- `handleUpdate` 先查详情,再把数据赋值到表单。
- `submitForm` 校验表单、切换 `buttonLoading`、根据主键判断调用新增还是更新、提示成功并刷新列表。
- `handleDelete` 使用 `proxy?.$modal.confirm(...)` 确认,再调用删除接口并刷新。
- `handleExport` 使用 `proxy?.download(...)`
## 模板结构规则
- 优先保持生成器的页面布局结构:搜索区卡片、表格区卡片、工具栏、分页、弹窗表单。
- 保留 `v-hasPermi="['module:business:add']"` 这类权限指令。
- 继续使用仓库已有组件:`right-toolbar``pagination``dict-tag``image-preview``image-upload``file-upload``editor`
- 已有页面对时间列使用 `parseTime` 时,新页面保持一致。
- BETWEEN 日期查询继续使用 `el-date-picker``proxy?.addDateRange(...)`
## 避免事项
- 生成器风格页面不要突然换成完全不同的状态管理方式,除非该前端目录本身已经这么做。
- 模块已使用字典时,不要把选项文案硬编码到页面里。
- 不要让 API 函数名和路由段偏离后端约定。
- 后端 BO/service 依赖 begin/end 参数时,不要从查询对象里删掉 `params` 和日期范围处理。