Commit 4ed4e00a by xiaowei

添加了工程ai cursor及trae约束

parent 3b46fab7
---
description: 全项目代码通用强制自检清单,所有Java、Vue、UniApp、SQL文件全局生效
globs: ["**/*.java","**/*.vue","**/*.ts","**/*.sql","**/*.xml","**/*.vue"]
alwaysApply: true
---
# 冲突优先级声明
若本规则与其他专项规则冲突,专项业务规则优先级高于本文件;达梦数据库、Java编码禁令、信创约束拥有最高不可覆盖优先级。
# 通用代码强制自检清单(若依微服务+达梦8+信创,无会议/BPM)
## 一、Java 通用红线
1. 依赖注入统一 @Resource,禁止 @Autowired;
2. 禁止连环set赋值,DO/VO全部使用@Builder链式构建;
3. 禁止手写getter/setter,统一Lombok @Data;
4. 非空判断统一Hutool工具类(StrUtil/CollUtil),禁止裸判空;
5. 禁止魔法数字/字符串,统一枚举、常量类;
6. 多层if嵌套改用卫语句,禁止深度嵌套;
7. 循环内禁止调用Mapper,统一批量操作;
8. 时间统一 LocalDateTime,禁止 Date/Timestamp;
9. 所有业务异常统一 ServiceExceptionUtil,禁止直接new RuntimeException;
10. Service查询无数据必须抛异常,禁止return null;
11. Controller禁止try-catch,使用若依全局异常处理器;
12. Controller禁止直接注入Mapper,仅允许注入Service;
13. 微服务跨模块调用仅允许Feign DTO远程调用,禁止直接依赖对方server模块;
14. 所有新增表/字段必须适配达梦8语法,禁止MySQL专属函数;
15. 项目无BPM流程、会议预约相关业务,禁止新增Flowable依赖、审批监听、流程表单代码。
## 二、SQL & 达梦8 强制红线
1. 主键统一String雪花ID,达梦8禁止自增ID,不使用序列作为业务主键;
2. 时间字段使用达梦 TIMESTAMP,禁止 TIMESTAMPTZ;
3. 分页使用达梦分页语法,禁止MySQL LIMIT/OFFSET逗号写法;
4. 表名、字段名全部小写蛇形,规避达梦关键字;
5. 必须包含租户、软删除、创建人、创建时间等框架字段;
6. 字典初始化SQL适配达梦insert语法,兼容信创达梦驱动;
7. 禁止使用MySQL专属函数:IFNULL、DATE_FORMAT等,替换达梦对应函数;
8. 不创建会议、审批流程相关数据表、索引、初始化数据。
## 三、前端双端通用红线(管理后台Vue3 + UniApp APP)
1. ID统一string类型,禁止number,避免雪花ID精度丢失;
2. 表单基础校验使用el-form/uni-form内置提示,业务逻辑弹窗提示;
3. 禁止页面硬编码魔法状态、文本,统一枚举/字典翻译;
4. API请求统一封装若依axios请求,禁止原生fetch/axios裸调用;
5. 所有删除、批量操作增加二次确认弹窗;
6. APP端适配国产安卓系统,避免闭源第三方SDK;
7. 页面类型区分:管理后台页面、APP表单页面,规范目录拆分;
8. 不开发流程审批、会议预约类页面、弹窗、表单组件。
## 四、信创强制约束(全代码通用)
1. 第三方依赖优先选用国产化开源包,剔除国外闭源组件;
2. SQL脚本、配置文件兼容国产服务器(鲲鹏、飞腾CPU);
3. JDK统一使用国产龙芯/鲲鹏适配OpenJDK,禁止Oracle JDK;
4. 中间件使用国产东方通、金蝶,不使用Tomcat商业版、WebLogic;
5. 打包产物支持信创容器镜像,无海外镜像依赖;
6. 所有功能无依赖境外API、境外存储服务。
## 五、微服务通用约束
1. 多模块拆分遵循若依微服务标准:gateway、system、business、api;
2. 远程调用统一Feign接口,DTO隔离,server模块不互相依赖;
3. 配置全部存入Nacos,禁止本地yml硬编码环境配置;
4. 接口路径统一 /api/{模块}/{功能},网关统一路由转发;
5. 权限标识遵循 模块:业务:操作 格式,适配若依Sa-Token鉴权;
6. 分布式防重复提交使用Redis幂等注解,适配微服务多实例。
---
description: 达梦8 DM8数据库全局强制规范,信创数据库最高优先级规则
globs: ["**/*.sql","**/*DO.java","**/*Mapper.xml"]
alwaysApply: true
---
# 达梦8(DM8)数据库规范 信创适配
## 一、达梦 8 字段类型强制约束
1. 雪花 ID 主键:Java String,达梦 `VARCHAR(20)`;**禁止 BIGINT 自增、禁止序列做主键**;
2. 状态、枚举值:Java Integer,达梦 `INT`;
3. 短文本名称:`VARCHAR(100)`,长描述 `VARCHAR(500)`;
4. 时间统一 `TIMESTAMP`;**禁止 TIMESTAMPTZ、DATE 单独存储时分秒**;
5. 布尔值使用 `BIT`,0/1;
6. JSON 数组、复杂集合存储使用 `TEXT`,配合 MyBatis-Plus JacksonTypeHandler;
7. 不使用达梦大字段 CLOB/BLOB,业务文本统一 VARCHAR/TEXT。
## 二、DDL 脚本达梦专属规范
1. 表名、字段名全部小写蛇形命名,规避达梦系统关键字;
2. 注释使用 `COMMENT ON TABLE` / `COMMENT ON COLUMN` 达梦标准语法;
3. 新增字段使用 `ALTER TABLE 表名 ADD COLUMN xxx 类型 约束 COMMENT '注释'`;
4. 建表语句包裹 `BEGIN;` 和 `COMMIT;`,事务执行;
5. 索引创建语法:`CREATE INDEX idx_xxx ON table_name(col);`;唯一索引 `CREATE UNIQUE INDEX`;
6. 达梦分页语法:`OFFSET x LIMIT y`,禁止 MySQL LIMIT 0,10 逗号写法;
7. 达梦函数替换 MySQL 函数:
- IFNULL → NVL
- DATE_FORMAT → TO_CHAR
- NOW() → SYSDATE
- SUBSTRING → SUBSTR
## 三、MyBatis-Plus 适配达梦 8
1. Mapper 继承 `BaseMapperX`(项目封装适配达梦),禁止原生 BaseMapper;
2. 分页使用 `LambdaQueryWrapperX` 空值安全条件,达梦分页自动适配;
3. 禁止 MySQL 专属 XML SQL,所有原生 SQL 必须兼容达梦;
4. 主键注解统一 `@TableId(type = IdType.ASSIGN_ID)`,达梦全局关闭自增;
5. 软删除使用 MyBatis-Plus 逻辑删除,达梦 BIT 字段自动适配。
## 四、达梦 8 信创部署约束
1. 驱动包使用达梦官方国产化驱动 DmJdbcDriver,不使用兼容 MySQL 驱动;
2. 数据库字符集统一 GB18030,适配信创中文存储;
3. 排序规则统一达梦中文排序,避免中文查询乱序;
4. 生产环境达梦 8 部署在鲲鹏 / 飞腾国产服务器,禁止 x86 海外服务器;
5. 数据库备份脚本适配达梦 dexp/dimp 工具,不使用 mysqldump;
6. 账号权限最小化,业务账号仅拥有 DML 权限,DDL 仅 DBA 可执行,满足等保信创要求。
## 五、数据库开发禁止事项
❌ 禁止使用自增主键、序列作为业务主键;
❌ 禁止 MySQL 专属函数、分页语法;
❌ 禁止字段名、表名使用达梦保留关键字不加转义;
❌ 禁止存储过程、触发器承载大量业务逻辑,业务全部下沉 Java 服务层;
❌ 禁止 TEXT/CLOB 存储超长业务文本,拆分字段;
❌ 禁止手动更新 deleted 软删除字段,使用框架内置逻辑删除方法;
❌ 禁止达梦数据库存储境外加密、境外第三方数据;
❌ 禁止创建会议、审批流程相关数据表、存储过程、触发器。
---
description: 若依微服务前后端协作规范(Vue管理后台 + UniApp APP双端,无会议/BPM)
globs: ["**/*.java","**/*.vue","**/*.ts","**/*.sql","**/*.js"]
alwaysApply: true
---
# 冲突优先级声明
达梦数据库、Java编码、信创部署规则优先级高于本文件;若依微服务专项架构规则冲突时以专项文件为准。
# 若依微服务全栈协作规范
## 一、前后端字段映射标准(统一适配达梦8)
### TS类型 → Java类型 → 达梦8字段映射
| 前端TS类型 | Java实体类型 | 达梦8列类型 | 说明 |
| ---- | ---- | ---- | ---- |
| string(雪花ID) | String | VARCHAR(20) | 主键,防止精度丢失 |
| number(状态枚举) | Integer | INT | 业务状态、字典值 |
| string(名称文本) | String | VARCHAR(100) | 名称、标题 |
| string(长描述) | String | VARCHAR(500) | 备注、描述 |
| string(ISO时间) | LocalDateTime | TIMESTAMP | 统一时间类型 |
| boolean | Boolean | BIT | 布尔标识 |
| string[] | List<String> | TEXT | JSON数组存储,JacksonTypeHandler |
## 二、前端页面推导后端代码流程
1. 管理后台Vue页面、UniApp APP页面,先提取全部表单字段、列表查询条件、接口请求;
2. 区分双端接口隔离:管理后台接口、APP移动端独立接口,禁止复用同一套Controller;
3. 后端分层严格遵循:SQL DDL(达梦语法)→ DO → Mapper → VO → Controller → Service;
4. 跨模块查询使用Feign远程调用,不直接操作其他业务Mapper;
5. 字典、枚举前后端同步,后端存数字code,前端通过若依字典组件自动翻译中文;
6. 分页统一PageResult返回,前端PageReqVO继承若依PageParam。
## 三、微服务接口路径规范
1. 管理后台接口前缀:`/api/admin/{module}/{business}`
2. APP移动端接口前缀:`/api/app/{module}/{business}`
3. 公共基础模块接口:`/api/common/{function}`
4. CRUD固定后缀:/create /update /delete /get /page /export-excel
## 四、双端代码产出区分
1. Vue管理后台:基于Element Plus,SqSearchTableFrame标准列表框架;
2. UniApp APP端:uni-form、uni-data-select、uni-list等原生组件,适配移动端触控;
3. 公共类型统一抽离api/types.ts,后台与APP类型文件隔离,不共用;
4. APP端不展示复杂后台管理字段(租户ID、创建人、操作日志等)。
## 五、数据库字段对齐强制要求
1. DO驼峰字段 ↔ 达梦表下划线字段完全一一对应;
2. SaveReqVO覆盖前端所有可编辑字段,不含框架内置字段;
3. RespVO增加富化展示字段(关联名称、字典中文),DO不存储;
4. 新增字段必须同步:达梦ALTER脚本、DO实体、前后端VO类型。
## 六、信创前后端适配要求
1. 前端打包产物无海外CDN资源,静态资源本地化;
2. UniApp打包支持国产安卓系统、国产芯片设备;
3. 前端加密、工具类使用国产加密算法(SM2/SM3/SM4),禁用RSA国际算法;
4. 接口日志脱敏手机号、身份证等敏感信息,满足信创等保规范。
---
description: Java编码八大强制红线禁令(最高优先级Java规则,达梦、信创规则除外,无BPM/会议)
globs: ["**/*.java"]
alwaysApply: false
---
# 冲突优先级声明
本文件为Java代码最高强制约束,仅达梦数据库、信创部署规则优先级高于本文件,其余所有Java相关规则冲突时以本文件为准。
# Java编码强制八大禁令(若依微服务+达梦8+信创)
## 禁令1:禁止连环set硬赋值,统一@Builder链式构建
❌ 错误:new DO() 后逐行setXxx
✅ 正确:DO实体添加@Builder、@NoArgsConstructor、@AllArgsConstructor,使用DO.builder().field(val).build()
## 禁令2:禁止手写getter/setter,统一Lombok @Data
❌ 手动编写get/set方法
✅ 所有DO、VO、DTO统一使用@Data,配合@EqualsAndHashCode(callSuper = true)
## 禁令3:依赖注入统一@Resource,完全禁止@Autowired
❌ 混用@Autowired和@Resource
✅ Controller、ServiceImpl中所有Mapper、Service、Feign接口全部使用@Resource注入
## 禁令4:非空判断禁止裸判断,统一Hutool工具类
❌ if(str != null && !str.equals("")) / if(list != null && list.size()>0)
✅ 字符串:StrUtil.isNotBlank();集合:CollUtil.isNotEmpty();对象:ObjectUtil.isNotNull()
## 禁令5:禁止魔法数字、魔法字符串,统一枚举/常量类
❌ 直接写if(status == 0)、return "goods_offline"
✅ 业务状态定义枚举,固定文本、阈值写入XXXConstants常量类
## 禁令6:禁止多层if-else嵌套,卫语句优先,复杂状态使用策略模式
❌ 超过2层if嵌套
✅ 所有边界、校验条件前置,提前return/抛异常,消除else分支;状态机多分支采用策略模式
## 禁令7:循环内部禁止调用Mapper单条操作,统一批量方法
❌ for循环中mapper.insert() / mapper.deleteById()
✅ 批量插入insertBatch、批量删除deleteBatchIds、条件批量更新wrapper更新,单次DB交互
## 禁令8:时间类型统一LocalDateTime,完全禁止Date、Timestamp
❌ java.util.Date、java.sql.Timestamp
✅ DO、VO、DTO时间字段全部使用LocalDateTime,达梦8 TIMESTAMP字段对应
# 补充强制编码约束
1. 业务异常统一 ServiceExceptionUtil.exception(ErrorCode),禁止直接new RuntimeException、IllegalArgumentException;
2. Service查询无数据必须抛不存在异常,禁止return null区分不存在;
3. Controller禁止编写try-catch捕获业务异常,使用若依全局异常处理器;
4. Controller禁止直接注入Mapper,仅允许注入对应Service;
5. 跨模块调用仅允许注入Feign API接口,禁止依赖对方ServiceImpl;
6. 所有类、Service接口方法、DO字段必须添加中文Javadoc注释;
7. 错误提示文案使用业务操作人员易懂中文,禁止技术术语、数据库字段名、英文编码;
8. 新增/修改/删除/导出接口必须添加@ApiAccessLog操作日志注解;
9. 创建、状态变更接口必须添加@Idempotent幂等注解防重复提交;
10. 所有DO主键统一String雪花ID,@TableId(type = IdType.ASSIGN_ID),适配达梦8;
11. 禁止引入Flowable、BPM流程审批相关类、注解、依赖。
---
description: 对象转换Convert类规范,DO/VO/DTO分层隔离转换
globs: ["**/*Convert.java"]
alwaysApply: false
---
# 冲突优先级声明
Java编码规范、达梦实体规则优先级高于本文件。
# 对象转换Convert类开发规范
## 一、基础规范
1. 存放路径:convert包下,命名 XxxConvert;
2. 类添加 @Mapper(componentModel = "spring") 注解,使用MapStruct自动生成转换实现;
3. 所有转换方法为静态/实例抽象方法,禁止手动编写set赋值转换逻辑;
4. 转换类只做对象属性拷贝,不编写业务计算、数据查询逻辑。
## 二、标准转换方法定义
### 1. DO ↔ RespVO
RespVO toRespVO(DO entity);
List<RespVO> toRespVOList(List<DO> list);
### 2. SaveReqVO → DO
DO toDO(SaveReqVO reqVO);
### 3. DO ↔ Feign DTO(跨服务传输)
DTO toDTO(DO entity);
DO toDO(DTO dto);
List<DTO> toDTOList(List<DO> list);
## 三、特殊字段转换处理规则
1. 字典翻译、关联名称等富化字段:转换基础拷贝后,在Service层单独赋值,Convert不处理;
2. 时间字段 LocalDateTime 自动映射,无需额外转换配置;
3. 雪花ID String类型自动映射,无精度丢失问题;
4. 枚举字段:统一存储Integer编码,转换时直接拷贝数字,中文翻译在VO层处理;
5. 集合List<String> JSON字段:MyBatis类型处理器处理,转换层直接拷贝。
## 四、MapStruct 注解配置规范
1. 字段名称完全一致时,无需额外@Mapping;
2. 字段名称不一致时,添加映射注解:
@Mapping(source = "userId", target = "uid")
3. 忽略不需要拷贝的字段:
@Mapping(target = "richName", ignore = true)
4. 禁止使用复杂表达式在@Mapping中,复杂逻辑交给Service处理。
## 五、Convert通用禁止项
❌ 禁止手动new对象+连环set做转换,必须MapStruct自动生成;
❌ 禁止在转换方法中调用Mapper、Feign、Service查询数据;
❌ 禁止转换类添加业务工具方法、常量;
❌ 禁止跨模块直接转换VO与DO,跨服务只能通过DTO中转;
❌ 禁止转换方法返回null,空集合统一返回空列表Collections.emptyList()。
---
description: 业务枚举、数据字典前后端同步规范,适配若依字典+达梦初始化SQL
globs: ["**/*Enum.java","**/*.sql"]
alwaysApply: false
---
# 冲突优先级声明
达梦数据库规范、Java编码规范优先级高于本文件。
# 枚举 & 数据字典同步开发规范
## 一、业务枚举开发规范
1. 存放路径:enums包,命名 XxxEnum;
2. 枚举固定结构:code(Integer编码)、desc(中文描述);
3. 基础方法:getCode()、getDesc(),提供静态工具方法根据code获取枚举;
4. 所有业务状态、类型、标识全部使用枚举,禁止硬编码魔法数字;
5. 枚举添加中文类注释、每个实例添加单行注释说明业务含义;
6. 禁止枚举中编写数据库查询、远程调用、复杂业务逻辑。
示例标准枚举:
public enum GoodsStatusEnum {
UP(1, "上架"),
DOWN(2, "下架");
private final Integer code;
private final String desc;
GoodsStatusEnum(Integer code, String desc) {
this.code = code;
this.desc = desc;
}
// getter、根据code查询工具方法
}
## 二、若依数据字典规范
1. 系统字典复用内置两张表:sys_dict_type(字典类型)、sys_dict_data(字典项);
2. 字典类型编码规则:`business_xxx`,区分系统字典与业务字典;
3. 达梦初始化SQL规范:
1. 先判断字典类型不存在再插入;
2. 批量插入字典项,适配达梦INSERT多行语法;
3. 所有字符串值使用单引号,注释符合达梦语法;
4. 前后端同步规则:
- 后端存储数字code;
- 管理后台Vue使用 <dict-tag /> 组件自动翻译中文;
- UniApp APP端封装全局字典翻译工具,根据code展示中文;
5. 区分使用场景:
- 固定不变、全项目通用状态:优先使用Java枚举;
- 支持后台动态新增修改的分类、标签:使用数据库数据字典。
## 三、枚举与字典同步约束
1. 若业务同时使用枚举+字典,必须保证code编码完全一致,避免前后端翻译错乱;
2. 新增业务状态时,同步更新枚举类、字典初始化SQL、前端字典选项;
3. 禁止枚举code与字典项value不一致,统一Integer数字编码;
4. 生产环境字典初始化脚本仅执行新增,不修改已有字典项,避免线上数据变更风险。
## 四、禁止事项
❌ 禁止业务状态硬编码数字,必须枚举/字典;
❌ 禁止字典初始化SQL使用MySQL专属语法,严格适配达梦;
❌ 禁止枚举存储字符串编码,统一Integer;
❌ 禁止前端硬编码状态文本,全部依赖枚举/字典翻译;
❌ 禁止动态可变业务分类使用Java枚举,必须数据库字典。
---
description: DO/ReqVO/RespVO/DTO实体规范,适配达梦8雪花ID、字段类型映射
globs: ["**/*DO.java","**/*VO.java","**/*DTO.java"]
alwaysApply: false
---
# 冲突优先级声明
达梦数据库全局规则、Java编码禁令优先级高于本文件。
# DO、VO、DTO 实体开发规范(达梦8适配)
## 一、DO 数据库实体规范
1. 存放路径:domain/dataobject,命名 Xxx;
2. 基础注解:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("xxx")
3. 主键字段统一:
@TableId(type = IdType.ASSIGN_ID)
private String id;
4. 必须包含框架通用字段:creator、createTime、updater、updateTime、deleted;
5. 字段类型严格遵循达梦8映射规则,时间统一LocalDateTime,布尔使用Boolean;
6. 复杂数组/集合字段添加类型处理器注解:
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> tagList;
7. 禁止在DO中添加业务计算字段、字典翻译字段,翻译逻辑统一在RespVO处理;
8. 所有字段添加中文注释,说明业务含义。
## 二、ReqVO 请求VO规范
### 1. SaveReqVO(新增/编辑共用)
1. 命名:XxxSaveReqVO;
2. 仅包含前端可编辑业务字段,**不包含id、租户、创建人、创建时间、软删除**等框架字段;
3. 字段校验注解统一使用Hibernate Validator:@NotBlank、@NotNull、@Size、@Min、@Max;
4. 时间字段统一LocalDateTime;ID、编码类文本统一String;
### 2. PageReqVO(分页查询)
1. 命名:XxxPageReqVO,继承若依框架 PageParam;
2. 仅包含分页参数、业务模糊查询、状态筛选条件;
3. 禁止分页VO携带大文本、复杂数组参数;
4. 所有查询条件允许为空,不强制@NotNull。
## 三、RespVO 返回VO规范
1. 命名:XxxRespVO;
2. 包含DO全部基础字段,额外增加富化展示字段(如分类名称、字典中文名称、关联业务名称);
3. 富化字段仅用于前端展示,不参与新增/编辑保存;
4. 时间统一LocalDateTime,序列化输出标准ISO格式;
5. 字典状态字段同时返回数字编码和中文翻译,方便前端展示。
## 四、Feign DTO 传输对象规范
1. 命名:XxxDTO,存放于ruoyi-business-api模块;
2. DTO仅存储跨服务传输必要字段,精简冗余字段;
3. 禁止将DO、VO直接作为Feign接口入参/返回值;
4. DTO不添加数据库相关注解(@TableName、@TableId等);
5. 基础注解仅保留@Data、@Builder,按需构造无参/全参构造。
## 五、实体通用禁止项
❌ 禁止DO直接返回前端,必须通过RespVO转换;
❌ 禁止SaveReqVO携带主键ID做新增操作;
❌ 禁止DTO中使用LocalDate、Date,统一LocalDateTime;
❌ 禁止实体字段使用基本类型(int、long、boolean),统一包装类型(Integer、Long、Boolean);
❌ 禁止在VO/DTO中编写业务逻辑方法,实体仅做数据载体。
---
description: 全局错误码分段管理规范,微服务多模块隔离
globs: ["**/ErrorCodeConstants.java"]
alwaysApply: false
---
# 冲突优先级声明
Java编码规范优先级高于本文件。
# 全局错误码常量规范
## 一、错误码分段规则(无BPM分段)
采用三段式数字编码:`模块段_子模块_序号`
1. system系统模块:1_001_001 ~ 1_001_999
用户、部门、角色、菜单、字典、登录权限相关错误;
2. business业务模块:1_100_001 ~ 1_999_999
所有自定义业务模块错误码,每个业务子模块分配100个序号区间;
3. 通用框架错误:1_000_001 ~ 1_000_999
参数校验、幂等、文件上传、导出、远程调用通用异常。
## 二、常量定义规范
1. 统一存放于 `ErrorCodeConstants.java` 常量类;
2. 常量命名:全大写,下划线分隔,业务含义清晰;
3. 常量值严格遵循分段编码,注释写明异常提示文案;
4. 示例:
// 商品模块-商品不存在
public static final Integer GOODS_NOT_EXIST = 1_100_001;
5. 同一业务模块错误码按业务流程顺序递增,预留间隔序号便于后续扩展;
6. 禁止重复错误码,新增错误码前检查已存在常量。
## 三、异常文案规范
1. 错误提示面向业务操作人员,使用通俗中文;
2. 禁止文案包含数据库字段名、技术术语、英文编码;
3. 参数校验类文案清晰指明错误字段,例:"商品名称不能为空";
4. 远程调用、服务异常文案屏蔽底层技术细节,统一友好提示。
## 四、使用规范
1. 业务抛出异常统一使用工具类:
ServiceExceptionUtil.exception(ErrorCodeConstants.GOODS_NOT_EXIST);
2. 禁止直接在代码中写数字错误码,全部引用常量;
3. 捕获Feign远程调用异常时,透传远端错误码与提示文案;
4. 前端接收错误码,可根据特定错误码做页面特殊处理(如跳转登录、弹窗提示)。
## 五、禁止事项
❌ 禁止使用重复错误码;
❌ 禁止硬编码数字错误码,必须引用常量;
❌ 禁止文案暴露底层技术、数据库、服务名称;
❌ 禁止跨模块混用错误码分段,严格按区间分配;
❌ 禁止新增BPM流程相关错误码分段。
---
description: 分布式幂等注解 @Idempotent 使用规范,基于Redis实现微服务防重复提交
globs: ["**/controller/**/*.java"]
alwaysApply: false
---
# 冲突优先级声明
Controller三层规范、Java编码规范优先级高于本文件。
# 分布式幂等防重复提交规范
## 一、注解基础说明
使用项目自定义 `@Idempotent` 注解,基于Redis实现分布式幂等控制,防止用户快速重复点击、网络重试造成重复新增、重复扣款、重复生成数据问题,适配微服务多实例集群环境。
## 二、注解属性配置规范
1. expireTime:幂等key过期时间,单位秒;
- 新增、编辑表单:默认5秒;
- 提交复杂业务、导出任务:设置30~60秒;
2. message:重复提交时返回的提示文案,示例:"请勿重复提交表单";
3. keyType:幂等key生成策略:
- TOKEN:基于用户登录Token + 接口路径(表单页面通用);
- PARAM:基于指定请求参数(唯一编码、订单号等唯一性字段)。
## 三、强制添加幂等注解的接口
1. POST /create 新增业务数据接口;
2. PUT /update 修改核心业务数据接口;
3. 状态变更、数据生成、批量处理接口;
4. APP端表单提交、订单创建类接口;
## 四、使用约束
1. 注解仅添加在Controller接口方法上;
2. 所有面向用户提交、可重复点击的写接口,必须配置@Idempotent;
3. 读接口(分页查询、详情查询、导出)无需添加幂等注解;
4. Redis统一使用国产化分布式缓存,不依赖境外Redis商业版本;
5. 幂等key自动绑定当前登录用户,用户之间互不干扰。
## 五、禁止事项
❌ 新增、编辑、业务提交接口不添加幂等注解,存在重复提交风险;
❌ 自定义本地内存锁替代分布式Redis幂等,集群多实例失效;
❌ 幂等提示文案使用技术术语,必须使用通俗易懂业务提示;
❌ 导出、单纯查询接口滥用@Idempotent注解,浪费Redis资源。
---
description: Mapper接口与XML规范,适配达梦8分页、函数、语法
globs: ["**/*Mapper.java","**/*Mapper.xml"]
alwaysApply: false
---
# 冲突优先级声明
达梦数据库全局规则优先级最高,其次为Java编码规范。
# Mapper层开发规范(达梦8专属适配)
## 一、Mapper接口规范
1. 存放路径:mapper,命名 XxxMapper;
2. 自定义查询方法命名规范:
- selectXxxByXxx:单条件查询列表
- countXxxByXxx:统计数量
- deleteXxxBatch:批量删除
- updateXxxBatch:批量更新
4. 方法入参:单参数直接传;多参数使用@Param("xxx")注解;
5. 禁止在Mapper接口编写业务逻辑,仅做数据库CRUD操作。
## 二、Mapper XML 文件规范
1. XML与Mapper接口同目录,文件名与接口名完全一致 XxxMapper.xml;
2. namespace 严格对应Mapper接口全类名;
3. 通用字段复用sql片段,抽取公共查询列、通用条件:
<sql id="common_column">
id, creator, create_time, updater, update_time, deleted
</sql>
4. 分页查询统一使用达梦分页语法 OFFSET #{offset} LIMIT #{pageSize},禁止MySQL逗号分页;
5. 函数统一使用达梦内置函数 NVL、TO_CHAR、SYSDATE,禁止IFNULL、DATE_FORMAT、NOW();
6. 所有SQL关键字大写(SELECT、FROM、WHERE、LEFT JOIN、ORDER BY),字段、表名下划线小写;
7. 禁止写SELECT *,必须明确查询需要的字段,减少IO开销。
## 三、MyBatis-Plus Wrapper 查询规范
1. 业务查询统一使用 LambdaQueryWrapperX、LambdaUpdateWrapperX,项目封装适配达梦;
2. 等值查询:eq;模糊查询:like;范围查询:ge、le;
3. 多条件拼接使用链式调用,禁止硬编码SQL字符串;
4. 分页查询调用 mapper.selectPage(page, wrapper),分页参数由上层PageParam转换;
5. 批量操作优先使用BaseMapperX提供的批量方法:insertBatch、updateBatchById。
## 四、达梦适配强制约束
1. 不使用自增主键、序列,主键由框架雪花ID生成;
2. 关联查询多表时,表别名简洁(t1、t2),避免关键字冲突;
3. 文本模糊查询长度适配达梦VARCHAR,超长文本使用TEXT字段查询;
4. 批量操作单次数据量控制在500条以内,防止达梦事务压力过大;
5. 禁止在XML中使用MySQL专属注释、引擎、字符集配置。
## 五、Mapper开发禁止项
❌ 禁止继承原生BaseMapper,必须BaseMapperX;
❌ 禁止SELECT * 查询所有字段;
❌ 禁止MySQL分页、MySQL专属函数;
❌ 禁止循环调用Mapper单条操作,统一批量方法;
❌ 禁止在XML中硬编码租户ID、软删除条件,统一框架自动填充;
❌ 禁止存储过程、复杂函数在XML中调用,业务逻辑下沉Service层。
---
description: Java类、方法、数据库表、接口路径、权限标识全量命名规范(若依微服务+达梦8,无会议/BPM)
globs: ["**/*.java","**/*.sql","**/*.yml"]
alwaysApply: false
---
# 冲突优先级声明
达梦数据库规范、Java编码禁令优先级高于本文件。
# 全项目统一命名规范
## 一、Java类命名
| 类类型 | 命名格式 | 示例 |
| ---- | ---- | ---- |
| 数据库DO实体 | {业务}DO | GoodsDO |
| 创建更新请求VO | {业务}SaveReqVO | GoodsSaveReqVO |
| 分页查询请求VO | {业务}PageReqVO | GoodsPageReqVO |
| 响应VO | {业务}RespVO | GoodsRespVO |
| Feign远程DTO | {业务}DTO | GoodsDTO |
| Service接口 | {业务}Service | GoodsService |
| Service实现 | {业务}ServiceImpl | GoodsServiceImpl |
| Mapper接口 | {业务}Mapper | GoodsMapper |
| 转换类Convert | {业务}Convert | GoodsConvert |
| 枚举类 | {业务}Enum | GoodsStatusEnum |
| 错误码常量 | ErrorCodeConstants | 统一文件追加 |
| Controller后台 | {业务}AdminController | GoodsAdminController |
| Controller移动端APP | {业务}AppController | GoodsAppController |
## 二、Service方法命名统一标准
| 功能 | 方法名 | 返回值 |
| ---- | ---- | ---- |
| 新增创建 | create{Entity} | String(雪花ID) |
| 更新 | update{Entity} | void |
| 删除单条 | delete{Entity} | void |
| 批量删除 | delete{Entity}ListByIds | void |
| 根据ID查询(不存在抛异常) | get{Entity} | DO实体 |
| 根据ID查询(允许空) | get{Entity}IfExists | DO实体 |
| 分页查询 | get{Entity}Page | PageResult<DO> |
## 三、达梦8数据库命名规范
1. 业务表前缀 `business_`,格式 `business_{模块}_{业务}`,全小写蛇形;
示例:`business_goods_info`、`business_user_address`
2. 字段全小写蛇形,与DO驼峰字段一一映射;
3. 索引命名:普通索引 `idx_字段名`;唯一索引 `uk_字段名`;
4. 字典系统表复用若依自带 `sys_dict_type`、`sys_dict_data`,不新建字典表。
## 四、微服务接口路径命名
1. 管理后台接口:`/api/admin/{模块}/{业务}`
示例:`/api/admin/business/goods`
2. APP移动端接口:`/api/app/{模块}/{业务}`
示例:`/api/app/business/goods`
3. CRUD固定后缀:
创建 POST `/create`;更新 PUT `/update`;删除 DELETE `/delete`;
查询单条 GET `/get`;分页 GET `/page`;导出 GET `/export-excel`
## 五、权限标识命名(Sa-Token)
格式:`{模块}:{业务}:{操作}`
操作固定枚举:create / update / delete / query / export
示例:`business:goods:create`、`business:goods:query`
## 六、常量&魔法值命名
1. 业务状态全部枚举类,禁止硬编码数字;
2. 全局固定阈值、模板ID、字典Key统一放入XXXConstants常量类;
3. 错误码分段规范:
- system系统模块:1_001_xxx_xxx
- business业务模块:1_100_xxx_xxx
## 七、前端文件命名
1. Vue后台列表页面:index.vue;表单抽屉:XxxFormDrawer.vue;详情抽屉:XxxDetailDrawer.vue;
2. UniApp APP页面:短横线kebab-case命名;
3. API类型文件:types.ts;接口请求文件:index.ts。
---
description: 若依框架操作日志注解 @ApiAccessLog 使用规范
globs: ["**/controller/**/*.java"]
alwaysApply: false
---
# 冲突优先级声明
Controller三层规范、Java编码规范优先级高于本文件。
# 操作日志 @ApiAccessLog 使用规范
## 一、注解基础说明
使用若依内置注解 `@ApiAccessLog`,自动记录操作人、操作时间、接口地址、请求参数、操作类型、耗时,满足信创等保审计日志要求。
## 二、注解必填属性规范
1. title:必填,模块业务中文名称,例:"商品管理";
2. operateType:操作类型枚举,可选值:
- CREATE:新增
- UPDATE:编辑修改
- DELETE:删除
- EXPORT:导出Excel
- QUERY:查询(分页/详情)
3. saveRequestData:布尔值,默认true,记录请求参数;敏感接口(含身份证、手机号)设置为false,防止日志泄露隐私。
## 三、接口注解使用强制规则
1. 以下接口**必须添加@ApiAccessLog**:
- POST /create 新增
- PUT /update 编辑
- DELETE /delete 删除
- GET /export-excel 导出
2. 查询接口(分页、详情)按需添加,内部管理系统建议全部记录;APP端普通查询可省略日志注解;
3. 注解仅允许添加在Controller接口方法上,禁止在Service、Mapper层使用。
## 四、日志脱敏规范
1. 接口参数包含手机号、身份证、银行卡、家庭地址等敏感字段时:
1. @ApiAccessLog(saveRequestData = false) 关闭参数记录;
2. 或全局配置日志脱敏规则,自动隐藏敏感信息中间字符;
2. 生产环境日志持久化存储,保留至少6个月审计日志,符合信创等保三级要求。
## 五、禁止事项
❌ 新增/修改/删除/导出接口不添加操作日志注解;
❌ 在Service、Mapper、Convert等非Controller层使用日志注解;
❌ 敏感隐私接口完整记录明文身份证、手机号;
❌ 自定义日志打印替代框架统一@ApiAccessLog日志,分散审计日志。
## 4、01_java_ruoyi_cloud_architecture.mdc
```mdc
---
description: 若依RuoYi-Vue-Cloud微服务工程分层、模块分包、Nacos/Feign/Gateway规范(无BPM模块)
globs: ["**/*.java","**/pom.xml","**/application.yml","**/bootstrap.yml"]
alwaysApply: false
---
# 冲突优先级声明
达梦数据库、Java编码禁令优先级高于本文件;本文件规范优先级高于通用全栈协作规则。
# 若依微服务工程架构规范(RuoYi-Vue-Cloud)
## 一、标准模块拆分(移除ruoyi-bpm流程模块)
1. `ruoyi-gateway` 网关模块:路由转发、鉴权、跨域、限流、请求日志;
2. `ruoyi-system` 系统基础模块:用户、部门、角色、菜单、字典、操作日志;
3. `ruoyi-business-api` 业务公共API模块:Feign远程调用DTO、接口定义(仅接口、DTO,无业务实现);
4. `ruoyi-business-server` 业务实现服务模块:所有业务CRUD、ServiceImpl、Mapper、DO;
5. `ruoyi-common` 通用工具模块:常量、工具类、异常、枚举、全局返回体;
6. `ruoyi-admin` 管理后台前端;`ruoyi-app` UniApp移动端前端。
## 二、包结构标准(business-server业务模块)
com.ruoyi.business.{业务模块名}
├── controller 业务控制器(统一继承 BaseController,区分后台 / APP 接口)
├── domain 数据库实体 DO(达梦表映射实体,替换旧 dal/dataobject)
├── domain/vo 各类vo
├── mapper Mapper 接口(MyBatis-Plus 接口)
├── service
│ ├── impl ServiceImpl 业务实现类
│ └── 业务 Service 接口
├── convert 对象转换 Convert 类
├── enums 业务枚举、错误码常量
├── util 业务工具类
ruoyi-modules/ruoyi-busi/src/main/resources
├── mapper/busi Mapper.xml SQL 映射文件
├── application-dev.yml 开发环境配置
├── bootstrap.yml 启动配置
## 三、微服务核心组件规范
### 1. Nacos配置中心
1. 所有环境配置(数据库连接、Redis、Feign超时、线程池)存入Nacos;
2. bootstrap.yml仅配置Nacos地址、命名空间、集群;application.yml仅少量本地默认值;
3. 区分开发、测试、生产Nacos命名空间,生产配置加密存储(国产加密算法);
4. 达梦数据库连接池配置统一在Nacos,适配达梦驱动参数。
### 2. Feign远程调用(跨模块)
1. 跨服务调用仅允许通过 \`ruoyi-business-api\` 定义Feign接口;
2. API模块仅存放接口、DTO数据传输对象,无任何业务实现代码;
3. Server模块之间禁止直接依赖,只能依赖对应API模块;
4. Feign调用异常统一捕获,使用若依全局异常处理,返回标准化CommonResult;
5. Feign超时、重试策略在Nacos统一配置,适配微服务分布式场景。
### 3. Gateway网关
1. 所有接口请求统一经过网关,不允许服务直连访问;
2. 网关统一处理Sa-Token鉴权、跨域、接口限流、请求参数脱敏;
3. 路由规则区分admin后台、app移动端、内部服务接口;
4. 网关日志记录请求来源、耗时、操作人,满足信创等保审计要求。
### 4. Sa-Token 微服务鉴权
1. 管理后台、APP端使用两套独立Token体系,权限隔离;
2. 接口必须添加 \`@PreAuthorize("@ss.hasPermission('模块:业务:操作')")\` 权限校验;
3. APP移动端仅开放查询、提交保存等基础权限,禁止后台管理类权限;
4. 分布式会话存储Redis,适配多实例微服务集群。
## 四、微服务部署&信创适配
1. 所有服务打包为jar镜像,支持鲲鹏/飞腾国产CPU容器化部署;
2. 中间件国产化:Nacos国产适配版、东方通/TongWeb替代Tomcat;
3. Redis使用国产分布式缓存,禁用海外Redis企业版;
4. 服务日志输出适配国产日志采集工具,日志脱敏敏感信息;
5. 容器镜像不依赖海外Docker镜像源,全部本地化信创镜像。
## 五、模块依赖禁止事项
❌ 禁止server模块互相直接依赖;跨模块仅依赖xxx-api;
❌ 禁止将业务实现代码写入api模块;
❌ 禁止硬编码环境地址、数据库连接,全部Nacos配置;
❌ 禁止Feign接口传DO数据库实体,统一使用隔离DTO;
❌ 禁止APP端Controller开放后台管理权限接口;
❌ 禁止微服务多实例本地缓存存储状态,分布式状态统一Redis;
❌ 禁止引入Flowable、BPM流程相关依赖包。
\ No newline at end of file
---
description: Controller、Service、ServiceImpl三层代码模板规范,微服务鉴权、多租户适配
globs: ["**/controller/**/*.java","**/service/**/*.java"]
alwaysApply: false
---
# 冲突优先级声明
Java编码、达梦实体规范优先级高于本文件。
# Controller & Service & ServiceImpl 三层开发规范
## 一、Controller 分层规范
### 1. 基础约束
1. 存放路径:controller/;
2. AdminController:@RestController + @RequestMapping("/api/admin/business/xxx");
3. AppController:@RestController + @RequestMapping("/api/app/business/xxx");
4. 统一添加 @Tag 接口文档注解,标注模块名称;
5. 依赖注入仅注入对应Service,禁止直接注入Mapper、Feign(Feign在Service层注入);
6. 接口权限校验:@PreAuthorize("@ss.hasPermission('business:goods:query')");
7. APP端接口不添加后台管理类权限标识,仅做登录Token校验。
### 2. 标准CRUD接口模板
1. 新增 POST /create:入参SaveReqVO,返回雪花ID;添加@Idempotent、@ApiAccessLog;
2. 更新 PUT /update:入参SaveReqVO(携带id);添加@Idempotent、@ApiAccessLog;
3. 删除 DELETE /delete/{id}:路径ID,添加@ApiAccessLog;
4. 分页查询 GET /page:入参PageReqVO,返回PageResult<XxxRespVO>;
5. 单条详情 GET /get/{id}:返回XxxRespVO;
6. 导出 GET /export-excel:分页查询数据,导出Excel,添加导出权限校验。
### 3. Controller禁止项
❌ 禁止Controller编写业务逻辑、数据库查询;
❌ 禁止Controller捕获业务异常,全局统一异常处理器处理;
❌ 禁止Controller直接注入Mapper、Feign接口;
❌ 禁止Admin与APP接口写在同一个Controller;
❌ 禁止接口路径、权限标识混用后台与移动端。
## 二、Service 接口规范
1. 存放路径:service包,命名 XxxService;
2. 仅定义业务抽象方法,不编写实现逻辑;
3. 方法返回值规范:
- 新增:String(雪花ID)
- 更新/删除:void
- 单条查询:XxxDO(不存在抛异常)
- 分页查询:PageResult<XxxDO>
4. 所有方法添加中文Javadoc注释,写明入参、返回值、异常场景;
5. 跨服务远程调用方法,在Service接口定义对应方法。
## 三、ServiceImpl 实现类规范
1. 存放路径:service/impl,命名 XxxServiceImpl,实现XxxService;
2. 添加 @Service 注解;
3. 依赖注入:@Resource 注入Mapper、Feign接口、其他Service;
4. 业务分层逻辑:
1. 参数校验(非空、长度、状态合法性);
2. 数据库CRUD操作,批量数据处理;
3. 跨服务Feign远程调用;
4. 数据转换DO ↔ VO/DTO;
5. 组装分页、返回结果;
5. 多租户自动过滤:使用MyBatis-Plus租户插件,无需手动拼接租户条件;
6. 不存在数据统一抛出业务异常,禁止返回null。
## 四、通用三层统一约束
1. 入参校验统一使用Hibernate Validator注解,Controller层自动校验;
2. 所有分页返回统一包装 PageResult,包含总条数、当前页、数据列表;
3. 时间、创建人等公共字段由MyBatis-Plus自动填充,无需手动set;
4. 软删除统一框架逻辑删除,ServiceImpl不手动修改deleted字段。
---
description: 若依Vue3管理后台前端规范(Element Plus)
globs: ["**/ruoyi-admin/**/*.vue","**/ruoyi-admin/**/*.ts"]
alwaysApply: false
---
# 冲突优先级声明
全局前后端协作规范优先级高于本文件。
# 若依Vue3后台前端开发规范
## 一、页面目录结构规范
页面存放路径 `views/{业务模块}/`,目录拆分:
1. index.vue:列表主页面(搜索栏、表格、新增/编辑弹窗入口);
2. XxxFormDrawer.vue:新增、编辑抽屉表单;
3. XxxDetailDrawer.vue:详情查看抽屉;
4. components/:页面内部复用小型组件,不全局公用;
5. api/:当前模块接口请求文件;
6. types.ts:当前模块TS类型定义。
## 二、页面基础框架规范
统一使用项目封装通用列表组件 `SqSearchTableFrame`,内置搜索区、表格、分页、新增/删除按钮插槽;
1. 搜索表单使用el-form-item,搜索项控制在6个以内,多余折叠;
2. 表格列使用el-table-column,字典状态列使用 <dict-tag /> 自动翻译;
3. 表格操作列统一封装操作按钮组件,区分查看、编辑、删除;
4. 删除、批量删除按钮绑定二次确认弹窗,提示用户确认操作;
5. 分页统一使用框架封装分页组件,参数pageNum、pageSize与后端PageReqVO对齐。
## 三、表单抽屉规范
1. 新增/编辑共用一套FormDrawer组件,通过入参id区分新增/编辑;
2. 表单校验使用el-form内置rules校验,必填项标红*;
3. 下拉选择、状态选择统一使用字典接口回显,禁止硬编码选项;
4. 表单提交统一调用封装api,成功后关闭抽屉并刷新表格列表;
5. 复杂多行数据使用el-table内嵌表单行,支持新增、删除子行。
## 四、TS类型规范
1. types.ts 统一定义PageReq、SaveReq、Resp类型,与后端VO字段完全一致;
2. 所有ID字段定义为string,避免雪花ID数字精度丢失;
3. 状态枚举直接复用后端字典编码,前端不单独维护状态数字;
4. 接口请求统一封装axios工具,请求参数、返回值绑定TS类型。
## 五、前端通用禁止项
❌ 禁止页面硬编码字典状态、业务枚举数字;
❌ 禁止手动拼接接口地址,统一api文件导出请求方法;
❌ 禁止表单不做前端必填校验,仅依赖后端校验;
❌ 禁止表格操作无二次确认弹窗(删除、批量删除);
❌ 禁止TS类型中ID使用number类型,防止雪花ID精度丢失。
---
description: AI 生成代码审查 Checklist 与禁止事项,始终激活(基于 RuoYi Cloud 3.6.8 现有框架)
globs: ["**/*.java", "**/*.vue", "**/*.js", "**/*.sql", "**/*.xml"]
alwaysApply: true
---
# AI 生成代码规范 — 核心约束(始终生效)
> **框架基线**:RuoYi Cloud 3.6.8 + MyBatis + PageHelper + 达梦 DM8 + Vue2/Element UI。
> 若本文件与其他规则冲突,以**本文件反映的现有框架能力**为准;达梦 8、信创约束不可覆盖。
## 必须遵守的强制规则
### 异常处理
- ✅ 业务异常使用 `throw new ServiceException("用户可读的业务语言")`
- ✅ 由 `GlobalExceptionHandler` 统一处理,Controller 不写 try-catch
- ❌ `throw new RuntimeException("xxx")` — 绝对禁止
- ❌ Controller 中 catch 后只打日志不抛出 — 绝对禁止
### 返回值
- ✅ 单条/操作结果返回 `AjaxResult`(`success()` / `toAjax(rows)` / `error(msg)`)
- ✅ 分页列表返回 `TableDataInfo`(`startPage()` + `getDataTable(list)`)
- ✅ 微服务内部调用返回 `R<T>`
- ❌ Controller 直接返回 Domain/Map/POJO — 绝对禁止
### 时间类型
- ✅ 实体继承 `BaseEntity`,时间字段使用 `java.util.Date`
- ✅ 写入时间使用 `DateUtils.getNowDate()` 或 `SecurityUtils.getUsername()` 填充审计字段
- ❌ 在现有实体层强行改为 `LocalDateTime` — 禁止(与框架 `BaseEntity` 不一致)
### 依赖注入
- ✅ 字段注入使用 `@Autowired`(与现有 RuoYi 代码一致)
- ✅ Controller 只注入 Service,Service 只注入 Mapper
- ❌ Controller 直接注入 Mapper — 绝对禁止
### 数据权限
- ✅ 涉及部门/用户数据隔离的列表查询(如 system 模块),Service 方法加 `@DataScope(deptAlias = "d", userAlias = "u")`
- ✅ Mapper XML 中配合 `${params.dataScope}` 拼接权限条件
- ✅ 纯业务数据模块(如 `ruoyi-busi`)按实际需求决定是否启用,不强制所有列表都加
### 数据库操作
- ✅ Mapper 为独立接口 + `*Mapper.xml`,使用 MyBatis 动态 SQL(`<if>` / `<where>` / `<foreach>`)
- ✅ 分页由 Controller 调用 `startPage()`,底层 PageHelper 自动拦截
- ✅ 多表查询在 XML 中编写 JOIN,参数全部 `#{}` 占位,禁止字符串拼接
- ❌ `BaseMapperX` / `LambdaQueryWrapperX` / MyBatis-Plus — **项目未引入,禁止使用**
- ❌ MySQL 专属语法(`LIMIT 0,10`、`IFNULL`、`DATE_FORMAT`、`FIND_IN_SET` 等)— 绝对禁止
- ✅ 模糊查询可沿用若依现有写法 `concat('%', #{field}, '%')`(项目 Mapper 已广泛使用)
### 事务
- ✅ `@Transactional(rollbackFor = Exception.class)` 只加在 ServiceImpl 方法上
- ❌ `@Transactional` 加在 Controller / Mapper 上 — 绝对禁止
### 代码注释
- ✅ 每个 Java 类(Controller / Service / ServiceImpl / Domain / Mapper)必须有中文 Javadoc
- ✅ Service 接口方法必须有 `@param` / `@return` 注释
- ✅ Domain 业务字段必须有 `/** 中文说明 */` 注释
- ✅ Mapper 接口每个方法必须有中文注释说明用途
- ❌ 禁止只写英文注释
- ❌ 禁止无意义注释(如 `// 获取用户` 配 `getUser()`)
### 日志
- ✅ 继承 `BaseController` 使用 `logger`,或类上使用 Slf4j
- ❌ `System.out.println` — 绝对禁止
### 跨模块调用
- ✅ 通过 `ruoyi-api` 模块的 `@FeignClient` 远程接口
- ❌ 各 `ruoyi-modules` 的 server 模块之间直接依赖 — 绝对禁止
### 操作日志
- ✅ 增删改、导入导出接口加 `@Log(title = "...", businessType = BusinessType.XXX)`
- ❌ 使用 `@ApiAccessLog` — **项目未引入,禁止使用**
### 权限控制
- ✅ 接口加 `@RequiresPermissions("模块:业务:操作")`,格式如 `system:user:list`
- ❌ 使用 `@PreAuthorize("@ss.hasPermission('...')")` — **项目未引入,禁止使用**
### 错误提示语言规范
- ✅ 错误信息以**用户视角**、**业务语言**描述
- ❌ 禁止暴露技术术语、数据库字段名、堆栈信息
- ✅ 示例:「该字典类型已分配,不能删除」
- ❌ 禁止:「空指针异常」「SQL 执行失败」「ID 不存在」
### 项目边界
- ✅ 本项目为**智慧矫正**业务,模块放在 `ruoyi-modules/ruoyi-busi` 等现有结构
- ❌ 禁止引入 yudao 框架类(`CommonResult`、`TenantBaseDO`、`ServiceExceptionUtil` 等)
---
## AI 生成代码自检 Checklist
> 每次生成或修改代码后,按此清单检查:
### 分层 & 架构
- [ ] 新业务代码在 `ruoyi-modules/ruoyi-{module}`,包路径 `com.ruoyi.{module}.{layer}`
- [ ] Domain 继承 `BaseEntity`(含 createBy/createTime/updateBy/updateTime/remark/params)
- [ ] Controller 继承 `BaseController`,未直接注入 Mapper
- [ ] Service 遵循 `I{Entity}Service` 接口 + `{Entity}ServiceImpl` 实现
- [ ] 跨模块调用通过 `ruoyi-api` 的 Feign 接口
### 注解完整性
- [ ] Controller 类有 `@RestController`、`@RequestMapping`
- [ ] 需权限控制的接口有 `@RequiresPermissions("模块:业务:操作")`
- [ ] 增删改/导入/导出有 `@Log(title, businessType)`
- [ ] 入参校验使用 `@Validated` / `@Valid`(按现有模块风格)
### 安全 & 正确性
- [ ] 修改/删除前校验数据存在性,不存在时 `throw new ServiceException("...")`
- [ ] 业务规则冲突(重复名称、已分配不可删等)抛 `ServiceException`
- [ ] SQL 全部参数化,无 `${}` 拼接用户输入(`${params.dataScope}` 除外)
### 数据库(达梦 DM8)
- [ ] 表名、字段名小写蛇形,规避达梦关键字
- [ ] 主键类型与项目约定一致(业务表优先 String/VARCHAR,禁止 MySQL 自增写法)
- [ ] 时间字段使用达梦 `TIMESTAMP`,禁止 MySQL 专属函数
- [ ] 分页兼容达梦语法(PageHelper 配置 DM,XML 中禁止 MySQL `LIMIT` 逗号写法)
- [ ] Mapper 为接口 + XML,**未**使用 MyBatis-Plus 注解或 Wrapper
### 多表关联查询
- [ ] 在 `*Mapper.xml` 中编写 JOIN / 子查询
- [ ] 动态条件用 `<if test="...">`,null 安全判断写在 XML 或 Service 层
- [ ] 禁止引入 `MPJLambdaWrapperX` / `selectJoinPage`(项目未引入)
### 前端校验提示风格(ruoyi-ui / Vue2 + Element UI)
- [ ] 基础校验(不能为空、长度超限):`el-form` rules,表单项下方红字提示
- [ ] 业务逻辑校验(名称重复、状态冲突):`this.$modal.msgError()` 或 `this.$message.error()`
- [ ] API 请求走 `@/utils/request` 封装,禁止裸 axios/fetch
- [ ] 主键/雪花 ID 前端用 **string**,禁止 number(防精度丢失)
- [ ] 状态/字典展示使用 `dict-tag` 或 `getDicts()`,禁止页面硬编码魔法值
### Controller 整洁性
- [ ] Controller 中没有 try-catch
- [ ] Controller 只调用 Service,不含业务 if/else 逻辑
- [ ] 列表:`startPage()` → Service 查询 → `getDataTable(list)`
- [ ] 导出:使用 `ExcelUtil<T>` + `HttpServletResponse`
### 数据字典
- [ ] 可配置展示值同步维护 `sys_dict_type` + `sys_dict_data`
- [ ] 新增字典类型在 `sql/` 目录提供达梦兼容初始化脚本
- [ ] 前端通过字典 API 渲染,**未**使用 `@DictFormat` / `DictTypeConstants`(项目未引入)
### 代码质量
- [ ] 无 `System.out.println`
- [ ] 无魔法字符串(状态值提取为常量或字典)
- [ ] 使用 `@Autowired` 注入(与现有代码一致)
- [ ] Service 只注入本模块 Mapper,不跨实体混用 Mapper
- [ ] 错误提示是用户能看懂的业务语言
- [ ] 每个类、Service 方法、Domain 字段、Mapper 方法有中文注释
### 微服务 & 配置
- [ ] 配置优先 Nacos,避免在代码中硬编码环境地址/密钥
- [ ] 网关路由与模块服务名遵循现有 RuoYi Cloud 约定
- [ ] 敏感字段(手机号、身份证)展示/导出按项目脱敏规范处理
### 前台 ↔ 后台 ↔ 数据库字段对齐
- [ ] Domain 字段名与数据库列名(resultMap 映射)一致
- [ ] 前台表单 `v-model` 绑定名与后台字段一致
- [ ] 前台有但数据库没有的字段,已提供 `sql/` 下 DDL 脚本
- [ ] 系统字段(createTime、updateBy 等)由后端维护,前台表单不暴露编辑
---
description: Cursor 对话框 Prompt 提示词参考(手动复制使用,非自动激活)
globs: []
alwaysApply: false
---
# Cursor 新功能开发 Prompt 提示词(RuoYi Cloud)
> 复制以下内容到 Cursor 对话框中使用。
> 框架:RuoYi Cloud 3.6.8 + MyBatis + 达梦 DM8 + Vue2/Element UI。
---
## 普通功能开发
```
【任务】根据下面的页面生成完整的 RuoYi 后台 + 前端功能代码
【页面文件】
{粘贴 .vue 文件路径或代码}
【框架约束】
- 后端:RuoYi Cloud,AjaxResult/TableDataInfo,@RequiresPermissions,@Log,ServiceException
- Mapper:MyBatis 接口 + XML,禁止 MyBatis-Plus
- 前端:Vue2 + Element UI,@/utils/request
- 数据库:达梦 DM8 语法
- 禁止:CommonResult、BaseMapperX、SaveReqVO(除非明确要求)
【操作要求】严格按五阶段推进:
### 阶段一:分析页面
输出:模块名称、字段表、接口清单、业务规则、字典需求
(不生成代码)
完成后说:「【阶段一完成】,请确认。」
### 阶段二:输出文件清单
按 RuoYi 结构列出:
1. sql/*.sql
2. domain/{Entity}.java
3. mapper/{Entity}Mapper.java
4. resources/mapper/busi/{Entity}Mapper.xml
5. service/I{Entity}Service.java
6. service/impl/{Entity}ServiceImpl.java
7. controller/{Entity}Controller.java
8. ruoyi-ui/src/api/{module}/{business}.js
9. ruoyi-ui/src/views/{module}/{business}/index.vue
10. sql/dict_*.sql(如有)
完成后说:「【阶段二完成】,共 X 个文件。」
### 阶段三:逐文件生成
每次只生成一个文件,等待「继续」。
### 阶段四:清理 Mock
删除前端 mock 数据、硬编码假数据。
### 阶段五:功能验证
逐条对比前端 api 路径与 Controller 路径是否一致。
开始执行阶段一。
```
---
## 快捷指令
| 指令 | 含义 |
|-----|------|
| `继续` | 生成下一个文件 |
| `全部继续` | 一次性生成剩余文件 |
| `跳过` | 跳过当前文件 |
| `重新生成` | 重做当前文件 |
| `查看清单` | 输出进度 |
---
## 注意事项
- Controller 必须继承 `BaseController`
- 分页:`startPage()` + `getDataTable()`
- 权限格式:`busi:OBJECT:list`
- 前端主键用 string 类型
---
description: RuoYi Cloud 前后端协作规范(Vue2 + Element UI + 达梦 DM8)
globs: ["**/*.vue", "**/*.java", "**/*.js", "**/*.sql"]
alwaysApply: true
---
# 全栈协作规范(RuoYi Cloud 3.6.8)
## 技术栈
| 层级 | 技术 |
|------|------|
| 后端 | Spring Boot 4 + Spring Cloud + Nacos + MyBatis + PageHelper |
| 数据库 | 达梦 DM8 |
| 前端 | Vue 2 + Element UI + Vuex + Vue Router 3 |
| 请求 | `@/utils/request`(axios 封装) |
## 字段类型映射
| 前端 JS | Java Domain | 达梦列类型 | 说明 |
|---------|-------------|-----------|------|
| string | String | VARCHAR(N) | 主键/文本 |
| string | String | VARCHAR(20) | 雪花 ID(前端必须 string) |
| string | String | CHAR(1) | 状态/标志位 |
| string | Date | TIMESTAMP | 时间(ISO 字符串传输) |
| number | Integer/Long | INT/BIGINT | 数值(非主键场景) |
## 前后端接口对应
| 前端 API 方法 | HTTP | 后端 Controller | 返回类型 |
|-------------|------|----------------|---------|
| `listXxx(query)` | GET `/list` | `list(query)` | `TableDataInfo` |
| `getXxx(id)` | GET `/{id}` | `getInfo(id)` | `AjaxResult` |
| `addXxx(data)` | POST `/` | `add(data)` | `AjaxResult` |
| `updateXxx(data)` | PUT `/` | `edit(data)` | `AjaxResult` |
| `delXxx(ids)` | DELETE `/{ids}` | `remove(ids)` | `AjaxResult` |
| `exportXxx(query)` | POST `/export` | `export(response, query)` | 文件流 |
## 分页参数
- 前端:`queryParams.pageNum`、`queryParams.pageSize`
- 后端:Controller 调用 `startPage()`,PageHelper 自动读取分页参数
- 返回:`TableDataInfo`(rows + total)
## 权限标识
- 后端:`@RequiresPermissions("busi:OBJECT:list")`
- 前端:`v-hasPermi="['busi:OBJECT:add']"`
## 生成代码顺序
```
1. sql/ DDL(达梦语法)
2. domain/{Entity}.java
3. mapper/{Entity}Mapper.java
4. resources/mapper/{module}/{Entity}Mapper.xml
5. service/I{Entity}Service.java
6. service/impl/{Entity}ServiceImpl.java
7. controller/{Entity}Controller.java
8. ruoyi-ui/src/api/{module}/{business}.js
9. ruoyi-ui/src/views/{module}/{business}/index.vue
10. sql/ 字典初始化(如有状态字段)
```
## 字段对齐 Checklist
- [ ] Domain 字段 ↔ 数据库列(resultMap 映射)一致
- [ ] 前端 `v-model` 绑定名 ↔ Domain 字段名一致
- [ ] 新增字段已同步:DDL + Domain + Mapper XML + 前端表单
- [ ] 时间字段前端 `value-format="yyyy-MM-dd HH:mm:ss"` 与后端 Date 匹配
- [ ] 字典字段前后端 value 一致,前端用 `dict-tag` 展示
## 禁止事项
- ❌ 引入 yudao 路径风格(`/create`、`CommonResult`)
- ❌ 前端裸 axios/fetch,不走 `@/utils/request`
- ❌ MySQL 专属 SQL 语法
---
description: RuoYi Cloud 3.6.8 工程分层架构与模块归属规范
globs: ["**/*.java", "**/pom.xml"]
alwaysApply: false
---
# 工程分层架构规范(RuoYi Cloud 3.6.8)
> 框架基线:Spring Boot 4.x + Spring Cloud + Nacos + MyBatis + PageHelper + 达梦 DM8。
> 与 `ai-checklist.mdc` 冲突时,以 `ai-checklist.mdc` 为准。
## 模块归属
```
platform/
├── ruoyi-gateway # 网关 [8080]
├── ruoyi-auth # 认证中心 [9200]
├── ruoyi-api # Feign 接口定义(ruoyi-api-system 等)
├── ruoyi-common # 公共工具、安全、日志、Redis 等
├── ruoyi-modules/
│ ├── ruoyi-system # 系统模块 [9201]
│ ├── ruoyi-gen # 代码生成 [9202]
│ ├── ruoyi-job # 定时任务 [9203]
│ ├── ruoyi-file # 文件服务 [9300]
│ └── ruoyi-busi # 智慧矫正业务模块
├── ruoyi-visual # 监控中心
└── ruoyi-ui # Vue2 管理后台
```
新业务代码放在 `ruoyi-modules/ruoyi-busi`(或新建 `ruoyi-xxx` 模块),包路径:
```
com.ruoyi.{module}/
├── controller/
├── domain/ # 实体(继承 BaseEntity)
├── mapper/
├── service/
│ └── impl/
└── resources/mapper/{module}/
└── XxxMapper.xml
```
跨模块 RPC 接口定义在 `ruoyi-api/ruoyi-api-{module}`,**禁止** server 模块之间直接依赖。
## 标准包结构
```
com.ruoyi.busi/
├── controller/
│ └── JzObjectController.java
├── domain/
│ └── JzObject.java # 继承 BaseEntity
├── mapper/
│ └── JzObjectMapper.java
├── service/
│ ├── IJzObjectService.java # 接口以 I 开头
│ └── impl/
│ └── JzObjectServiceImpl.java
└── resources/mapper/busi/
└── JzObjectMapper.xml
```
## 三层职责边界
### Controller 层
- ✅ 继承 `BaseController`,接收参数、调用 Service、返回 `AjaxResult` / `TableDataInfo`
- ❌ 禁止直接注入 Mapper
- ❌ 禁止含业务 if/else 逻辑
- ❌ 禁止 try-catch 吞掉异常
### Service 层
- ✅ 业务逻辑、调用 Mapper、事务、`throw new ServiceException(...)`
- ✅ 需要数据权限的列表查询加 `@DataScope`
- ❌ 禁止在 Service 中拼接 SQL
- ❌ 禁止 Controller 直接操作 Mapper
### Mapper 层
- ✅ 接口 + XML,CRUD 与动态 SQL
- ❌ 禁止含业务逻辑
- ❌ 禁止加 `@Transactional`
## 关键框架能力
| 能力 | 框架类 | 说明 |
|------|--------|------|
| 统一响应 | `AjaxResult` | 单条/操作结果 |
| 分页列表 | `TableDataInfo` | `startPage()` + `getDataTable(list)` |
| 分页插件 | PageHelper | Controller 调用 `startPage()` |
| 实体基类 | `BaseEntity` | createBy/createTime/updateBy/updateTime/remark/params |
| 数据权限 | `@DataScope` | Service 方法 + XML `${params.dataScope}` |
| 操作日志 | `@Log` | title + BusinessType |
| 权限控制 | `@RequiresPermissions` | 格式 `模块:业务:操作` |
| 业务异常 | `ServiceException` | 中文业务语言 |
| 跨模块调用 | `@FeignClient` | 定义在 ruoyi-api 模块 |
| 内部调用 | `@InnerAuth` + `R<T>` | 服务间内部接口 |
| Excel 导出 | `ExcelUtil<T>` | 配合 `@Excel` 注解 |
| 工具类 | `StringUtils` / `DateUtils` | `com.ruoyi.common.core.utils` |
## 禁止引入
- ❌ MyBatis-Plus(`BaseMapperX`、`LambdaQueryWrapperX` 等)
- ❌ yudao 框架类(`CommonResult`、`TenantBaseDO`、`ServiceExceptionUtil` 等)
---
description: Java 编码红线禁令(RuoYi Cloud 强制),编辑任何 Java 文件时检查
globs: ["**/*.java"]
alwaysApply: true
---
# Java 编码红线禁令(RuoYi Cloud 3.6.8)
> 以下禁令生成 Java 代码时必须遵守。达梦 8、信创约束优先级更高。
> 与 `ai-checklist.mdc` 保持一致。
---
## 禁令一:禁止手动 new 容器 Bean
```java
// ❌ 禁止
JzObjectService svc = new JzObjectServiceImpl();
// ✅ 正确
@Autowired
private IJzObjectService jzObjectService;
```
---
## 禁令二:禁止 Controller 直接注入 Mapper
```java
// ❌ 禁止
@Autowired
private JzObjectMapper jzObjectMapper;
// ✅ 正确
@Autowired
private IJzObjectService jzObjectService;
```
---
## 禁令三:禁止裸抛 RuntimeException,统一 ServiceException
```java
// ❌ 禁止
throw new RuntimeException("数据不存在");
throw new IllegalArgumentException("name is null");
// ✅ 正确
throw new ServiceException("该记录不存在,请刷新后重试");
throw new ServiceException("名称不能为空");
```
---
## 禁令四:禁止 Controller 中 try-catch 吞异常
```java
// ❌ 禁止
try {
service.doSomething();
} catch (Exception e) {
log.error("失败", e);
return error("失败");
}
// ✅ 正确:抛 ServiceException,由 GlobalExceptionHandler 统一处理
service.doSomething();
```
---
## 禁令五:禁止非空裸判断,统一框架工具类
```java
// ❌ 禁止
if (str != null && !str.equals(""))
if (list != null && list.size() > 0)
// ✅ 正确(优先使用 RuoYi 工具类)
import com.ruoyi.common.core.utils.StringUtils;
if (StringUtils.isNotEmpty(name))
if (StringUtils.isNotEmpty(list)) // 集合也适用
if (StringUtils.isNotNull(obj))
```
---
## 禁令六:禁止魔法数字/字符串
```java
// ❌ 禁止
if ("0".equals(status))
// ✅ 正确:常量类或枚举
public class BusiConstants {
public static final String STATUS_NORMAL = "0";
public static final String STATUS_DISABLE = "1";
}
// 或使用数据字典 + 前端 dict-tag 展示
```
---
## 禁令七:禁止多层 if-else 嵌套,改用卫语句
```java
// ✅ 正确
public void process(String id) {
Entity entity = mapper.selectById(id);
if (entity == null) {
throw new ServiceException("记录不存在");
}
if (!isValidStatus(entity.getStatus())) {
throw new ServiceException("当前状态不允许此操作");
}
doProcess(entity);
}
```
---
## 禁令八:禁止循环内单条调用 Mapper
```java
// ❌ 禁止
for (String id : ids) {
mapper.deleteById(id);
}
// ✅ 正确:XML 批量删除
mapper.deleteByIds(ids);
// XML:
// DELETE FROM t WHERE id IN <foreach ...>
```
---
## 补充强制约束
| # | 约束 | 说明 |
|---|------|------|
| 1 | 依赖注入 | `@Autowired`(与现有 RuoYi 代码一致) |
| 2 | 时间类型 | `java.util.Date` + `DateUtils.getNowDate()` |
| 3 | HTTP 响应 | `AjaxResult` / `TableDataInfo`,禁止裸返回 Domain |
| 4 | 权限 | `@RequiresPermissions("模块:业务:操作")` |
| 5 | 操作日志 | 增删改/导入/导出加 `@Log` |
| 6 | 数据权限 | 业务列表 Service 加 `@DataScope` |
| 7 | 事务 | `@Transactional(rollbackFor = Exception.class)` 只加 ServiceImpl |
| 8 | 注释 | 类、Service 方法、Domain 字段、Mapper 方法必须有中文 Javadoc |
| 9 | SQL | 全部 `#{}` 参数化,禁止拼接用户输入 |
| 10 | 框架边界 | 禁止 MyBatis-Plus、yudao 相关类 |
## 违规自检清单
| # | 检查项 | 通过标准 |
|---|--------|---------|
| 1 | Controller 是否注入 Mapper | 无 Mapper 注入 |
| 2 | 异常类型 | 全部 `ServiceException` |
| 3 | Controller try-catch | 无 try-catch |
| 4 | 空值判断 | 使用 `StringUtils`,无裸判空 |
| 5 | 魔法值 | 无硬编码状态/类型字符串 |
| 6 | if 嵌套 | 不超过 2 层 |
| 7 | 循环 Mapper | 无循环单条 DB 操作 |
| 8 | 框架类 | 无 BaseMapperX / CommonResult 等 |
---
description: 对象转换规范(RuoYi 可选,字段不一致时使用)
globs: ["**/*ServiceImpl.java", "**/*Controller.java"]
alwaysApply: false
---
# 对象转换规范(RuoYi Cloud)
> RuoYi 标准 CRUD **直接使用 Domain 实体**,Controller 入参/出参即为 Domain。
> 仅在以下场景需要显式转换:
> - Domain 字段名与前端字段名不一致
> - 出参需要脱敏或富化(关联名称等)
> - Feign 跨模块传输需精简 DTO
## 标准模式:直接使用 Domain(推荐)
```java
// Controller 直接接收/返回 Domain
@PostMapping
public AjaxResult add(@RequestBody JzObject jzObject) {
return toAjax(jzObjectService.insertJzObject(jzObject));
}
@GetMapping("/{id}")
public AjaxResult getInfo(@PathVariable String id) {
return success(jzObjectService.selectJzObjectBySQJZDXBH(id));
}
```
## 字段不一致时:Service 层组装
```java
// ServiceImpl 中手动映射(简单场景)
public Map<String, Object> getDetailVo(String id) {
JzObject obj = mapper.selectById(id);
if (obj == null) {
throw new ServiceException("记录不存在");
}
Map<String, Object> vo = new HashMap<>();
vo.put("id", obj.getSQJZDXBH());
vo.put("name", obj.getXM());
return vo;
}
```
## 字段不一致时:独立 Vo 类(复杂场景)
```java
// domain/vo/JzObjectDetailVo.java
public class JzObjectDetailVo {
private String id;
private String name;
// getter/setter
}
// ServiceImpl
public JzObjectDetailVo buildDetailVo(JzObject obj) {
JzObjectDetailVo vo = new JzObjectDetailVo();
vo.setId(obj.getSQJZDXBH());
vo.setName(obj.getXM());
return vo;
}
```
## Bean 复制(字段名一致时)
```java
import org.springframework.beans.BeanUtils;
JzObject target = new JzObject();
BeanUtils.copyProperties(source, target);
```
> RuoYi 也提供 `com.ruoyi.common.core.utils.bean.BeanUtils`,按项目已有用法选择。
## 关键约束
1. **默认**直接使用 Domain,不额外建 Convert 类
2. 转换逻辑放 **Service 层**,Controller 只调用 Service
3. **禁止**在 Convert/组装方法中写业务校验(校验属于 Service 主流程)
4. Feign DTO 与 Domain 严格隔离,禁止 Feign 接口传 Domain
5. **禁止**引入 yudao 的 `XxxConvert` + `BeanUtils.toBean()` 模式作为强制要求
---
description: 枚举与数据字典同步规范(RuoYi sys_dict_type / sys_dict_data)
globs: ["**/*Enum.java", "**/*.sql", "**/dict/**"]
alwaysApply: false
---
# 枚举与数据字典同步规范
## 核心判断:枚举 vs 字典
| 场景 | 使用方式 |
|------|---------|
| 值固定不变,代码逻辑依赖 | Java 枚举或常量类 |
| 值可后台配置,前端展示翻译 | 数据字典(`sys_dict_type` + `sys_dict_data`) |
| 既有代码逻辑又需运营维护 | 枚举/常量 + 字典同步(code 必须一致) |
## 枚举标准模板
```java
/**
* 业务状态枚举
*/
public enum JzStatusEnum
{
NORMAL("0", "正常"),
DISABLE("1", "停用");
private final String code;
private final String info;
JzStatusEnum(String code, String info) {
this.code = code;
this.info = info;
}
public String getCode() { return code; }
public String getInfo() { return info; }
}
```
## 数据字典规范
- 字典类型表:`sys_dict_type`
- 字典数据表:`sys_dict_data`
- 业务字典类型编码建议:`busi_xxx`(与系统字典区分)
- 后端存储字典 **value**(字符串),前端通过字典 API 翻译
## 达梦初始化 SQL 模板
```sql
-- sql/dict_busi_xxx.sql
BEGIN;
INSERT INTO sys_dict_type(dict_id, dict_name, dict_type, status, create_by, create_time, remark)
SELECT seq_sys_dict_type.NEXTVAL, '业务状态', 'busi_status', '0', 'admin', SYSDATE, '业务状态字典'
FROM DUAL
WHERE NOT EXISTS (SELECT 1 FROM sys_dict_type WHERE dict_type = 'busi_status');
INSERT INTO sys_dict_data(dict_code, dict_sort, dict_label, dict_value, dict_type, status, create_by, create_time)
VALUES (seq_sys_dict_data.NEXTVAL, 1, '正常', '0', 'busi_status', '0', 'admin', SYSDATE);
INSERT INTO sys_dict_data(dict_code, dict_sort, dict_label, dict_value, dict_type, status, create_by, create_time)
VALUES (seq_sys_dict_data.NEXTVAL, 2, '停用', '1', 'busi_status', '0', 'admin', SYSDATE);
COMMIT;
```
> 具体序列名、字段以项目现有 `sql/` 脚本为准,**禁止**使用 MySQL 专属语法。
## 前端字典使用(ruoyi-ui)
```vue
<!-- 下拉选择 -->
<el-select v-model="form.status">
<el-option
v-for="dict in dict.type.busi_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
<!-- 表格展示 -->
<dict-tag :options="dict.type.busi_status" :value="scope.row.status"/>
```
```javascript
// 页面 dicts 声明
export default {
dicts: ['busi_status'],
// ...
}
```
## 同步 Checklist
- [ ] 新增状态/类型已在 `sys_dict_type` 注册
- [ ] `sys_dict_data` 已写入各选项(label + value)
- [ ] `sql/` 目录有达梦兼容初始化脚本
- [ ] 前端页面 `dicts: ['xxx']` 已声明
- [ ] 后端 Java 常量/枚举 code 与字典 value 一致
- [ ] **禁止**页面硬编码状态文本
## 禁止事项
- ❌ 使用 `@DictFormat` / `DictTypeConstants`(yudao 专属,项目未引入)
- ❌ 字典 SQL 使用 MySQL 专属语法
- ❌ 前端用 number 存主键/雪花 ID(必须 string)
---
description: Domain 实体与 VO 对象规范(RuoYi BaseEntity
globs: ["**/domain/**/*.java", "**/*Controller.java"]
alwaysApply: false
---
# Domain / VO 对象规范
> RuoYi 代码生成器默认产出 **Domain 实体**(继承 `BaseEntity`),Controller 直接使用 Domain 作为入参/出参。
> 仅在字段需要隔离或脱敏时,才额外引入 VO 类。
## Domain 实体标准模板
```java
package com.ruoyi.busi.domain;
import com.ruoyi.common.core.annotation.Excel;
import com.ruoyi.common.core.web.domain.BaseEntity;
/**
* {中文业务名称}对象 {TABLE_NAME}
*
* @author ruoyi
*/
public class {Entity} extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 主键 */
private String id;
/** 名称 */
@Excel(name = "名称")
private String name;
/** 状态(0正常 1停用) */
@Excel(name = "状态", readConverterExp = "0=正常,1=停用")
private String status;
// getter / setter(代码生成器产出传统 JavaBean
}
```
## BaseEntity 继承字段(框架自带,无需重复定义)
| 字段 | 类型 | 说明 |
|------|------|------|
| createBy | String | 创建者 |
| createTime | Date | 创建时间 |
| updateBy | String | 更新者 |
| updateTime | Date | 更新时间 |
| remark | String | 备注 |
| params | Map | 请求参数(含 dataScope 等) |
## 关键约束
- 实体继承 `BaseEntity`,时间字段使用 `java.util.Date`
- 需要导出的字段加 `@Excel(name = "...")`
- 每个业务字段必须有 `/** 中文说明 */` 注释
- 主键类型与数据库一致(业务表优先 String/VARCHAR
- **禁止** 使用 `@TableName``@TableId` MyBatis-Plus 注解
- **禁止** 使用 `TenantBaseDO`(本项目无多租户插件)
- **禁止** Domain 中放无对应数据库列的富化字段
## 何时需要额外 VO
| 场景 | 做法 |
|------|------|
| 标准 CRUD(代码生成器产出) | 直接使用 Domain,无需 VO |
| 入参字段与 Domain 不完全一致 | 新建 `{Entity}Vo` 或在 Service 层组装 |
| 出参需要脱敏/富化 | 新建响应 VO 或在 Controller 组装 Map |
| 跨模块 Feign 传输 | `ruoyi-api` 模块定义独立 DTO |
## Feign DTO 规范
```java
// 位置:ruoyi-api/ruoyi-api-system/.../domain/
public class Remote{Entity}DTO implements Serializable
{
private String id;
private String name;
// 仅放跨服务传输必要字段
}
```
## Domain vs VO vs DTO
| 维度 | Domain | VO(可选) | Feign DTO |
|------|--------|-----------|-----------|
| 位置 | `domain/` | `domain/vo/` 或同级 | `ruoyi-api/.../domain/` |
| 用途 | 数据库映射 + API 入参出参 | 字段隔离/脱敏 | 跨模块远程调用 |
| 基类 | `BaseEntity` | | |
| 注解 | `@Excel` | 校验注解(按需) | DB 注解 |
---
description: 业务异常与错误提示规范(RuoYi ServiceException)
globs: ["**/*ServiceImpl.java", "**/*Controller.java"]
alwaysApply: false
---
# 业务异常规范(RuoYi Cloud)
> 本项目使用 `com.ruoyi.common.core.exception.ServiceException`,**未引入** yudao 的 `ErrorCodeConstants` / `ServiceExceptionUtil`。
## 抛出方式
```java
import com.ruoyi.common.core.exception.ServiceException;
// 简单消息
throw new ServiceException("该字典类型已分配,不能删除");
// 带占位符(参考 SysRoleServiceImpl 写法)
throw new ServiceException(String.format("%1$s已分配,不能删除", role.getRoleName()));
```
## 错误信息规范
| 要求 | 示例 |
|------|------|
| ✅ 用户视角、业务语言 | 「该记录已被引用,无法删除」 |
| ✅ 说明原因和操作建议 | 「名称已被使用,请更换后重试」 |
| ❌ 技术术语 | 「空指针异常」「SQL 执行失败」 |
| ❌ 英文字段名 | 「name is null」「ID 不存在」 |
| ❌ 内部编码 | 「RESERVATION_CONFLICT」 |
## ServiceImpl 中使用场景
```java
private void validateBeforeDelete(String id)
{
JzObject obj = jzObjectMapper.selectJzObjectBySQJZDXBH(id);
if (obj == null)
{
throw new ServiceException("社区矫正对象不存在");
}
if (hasRelatedData(id))
{
throw new ServiceException("该对象存在关联数据,无法删除");
}
}
```
## 常量类(可选,复杂模块推荐)
若同一错误消息多处复用,可在模块内建常量类:
```java
/**
* 业务模块错误消息常量
*/
public class BusiErrorMessages
{
public static final String OBJECT_NOT_EXISTS = "社区矫正对象不存在";
public static final String OBJECT_HAS_RELATION = "该对象存在关联数据,无法删除";
}
// 使用
throw new ServiceException(BusiErrorMessages.OBJECT_NOT_EXISTS);
```
## 关键约束
- ✅ 所有业务校验失败抛 `ServiceException`
- ✅ Controller 不写 try-catch,由 `GlobalExceptionHandler` 统一处理
- ❌ 禁止 `throw new RuntimeException(...)`
- ❌ 禁止引入 `ErrorCodeConstants` / `ServiceExceptionUtil.exception()`
---
description: 防重复提交规范(RuoYi 前端防抖 + 后端约束)
globs: ["**/*Controller.java", "**/*.vue"]
alwaysApply: false
---
# 防重复提交规范
> 本项目 **未引入** yudao 的 `@Idempotent` 注解。
> 防重复提交主要依赖 **前端按钮防抖**,后端通过业务校验兜底。
## 前端(必须做)
```vue
<!-- 提交按钮:请求期间禁用 -->
<el-button type="primary" :loading="submitLoading" :disabled="submitLoading" @click="submitForm">
确 定
</el-button>
```
```javascript
submitForm() {
this.$refs.form.validate(valid => {
if (!valid) return;
this.submitLoading = true;
addObject(this.form).then(() => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
}).finally(() => {
this.submitLoading = false;
});
});
}
```
## 前端关键约束
- ✅ 提交/删除按钮请求发出后立即 `loading` + `disabled`
- ✅ 删除、批量操作使用 `this.$modal.confirm()` 二次确认
- ✅ API 走 `@/utils/request` 统一封装
- ❌ 禁止不做前端防抖,完全依赖后端
## 后端(业务层兜底)
```java
// 创建前唯一性校验(防止重复数据)
private void validateNameUnique(JzObject entity) {
JzObject existing = mapper.selectByName(entity.getName());
if (existing != null && !existing.getId().equals(entity.getId())) {
throw new ServiceException("名称已存在,请勿重复提交");
}
}
```
## 后端可选增强(需自行实现)
若业务对幂等性要求极高,可:
1. 使用 Redis 分布式锁(参考 `ruoyi-common-redis`)
2. 数据库唯一索引约束
3. 自行封装重复提交拦截器
**禁止**引入不存在的 `@Idempotent` / `@RepeatSubmit` 注解(除非项目已显式添加对应依赖)。
## 禁止事项
- ❌ 使用 `@Idempotent`(项目未引入)
- ❌ 对 GET 查询接口做"幂等"拦截
- ❌ 在 Service 层加前端防抖逻辑
---
description: Mapper 接口与 XML 编写规范(MyBatis + 达梦 DM8
globs: ["**/*Mapper.java", "**/*Mapper.xml"]
alwaysApply: false
---
# Mapper 规范(MyBatis + XML
> 本项目使用 **MyBatis 原生接口 + XML**,未引入 MyBatis-Plus
> **禁止** 使用 `BaseMapperX``LambdaQueryWrapperX``MPJLambdaWrapperX`
## Mapper 接口标准模板
```java
package com.ruoyi.busi.mapper;
import java.util.List;
import com.ruoyi.busi.domain.{Entity};
/**
* {中文业务名称}Mapper接口
*
* @author ruoyi
*/
public interface {Entity}Mapper
{
/**
* 查询{中文名称}
*
* @param id 主键
* @return {中文名称}
*/
public {Entity} select{Entity}ById(String id);
/**
* 查询{中文名称}列表
*
* @param query 查询条件
* @return 集合
*/
public List<{Entity}> select{Entity}List({Entity} query);
/**
* 新增{中文名称}
*/
public int insert{Entity}({Entity} entity);
/**
* 修改{中文名称}
*/
public int update{Entity}({Entity} entity);
/**
* 删除{中文名称}
*/
public int delete{Entity}ById(String id);
/**
* 批量删除{中文名称}
*/
public int delete{Entity}ByIds(String[] ids);
}
```
## Mapper XML 标准模板
```xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.busi.mapper.{Entity}Mapper">
<resultMap type="{Entity}" id="{Entity}Result">
<result property="id" column="id" />
<result property="name" column="name" />
<result property="createBy" column="create_by"/>
<result property="createTime" column="create_time"/>
<!-- 其他字段 -->
</resultMap>
<sql id="select{Entity}Vo">
SELECT id, name, create_by, create_time, update_by, update_time, remark
FROM {table_name}
</sql>
<select id="select{Entity}List" parameterType="{Entity}" resultMap="{Entity}Result">
<include refid="select{Entity}Vo"/>
<where>
<if test="name != null and name != ''">
AND name LIKE concat('%', #{name}, '%')
</if>
<if test="status != null and status != ''">
AND status = #{status}
</if>
<!-- 数据权限过滤 -->
${params.dataScope}
</where>
</select>
<select id="select{Entity}ById" parameterType="String" resultMap="{Entity}Result">
<include refid="select{Entity}Vo"/>
WHERE id = #{id}
</select>
<insert id="insert{Entity}" parameterType="{Entity}">
INSERT INTO {table_name}
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">id,</if>
<if test="name != null">name,</if>
<if test="createTime != null">create_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">#{id},</if>
<if test="name != null">#{name},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
<update id="update{Entity}" parameterType="{Entity}">
UPDATE {table_name}
<trim prefix="SET" suffixOverrides=",">
<if test="name != null">name = #{name},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
WHERE id = #{id}
</update>
<delete id="delete{Entity}ById" parameterType="String">
DELETE FROM {table_name} WHERE id = #{id}
</delete>
<delete id="delete{Entity}ByIds" parameterType="String">
DELETE FROM {table_name} WHERE id IN
<foreach item="id" collection="array" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
```
## 关键约束
1. XML 路径:`resources/mapper/{module}/XxxMapper.xml`
2. `namespace` 必须与 Mapper 接口全类名一致
3. 动态条件用 `<if test="...">`null 安全写在 XML Service
4. 多表 JOIN XML 中编写,参数全部 `#{}` 占位
5. 数据权限:列表查询 XML `${params.dataScope}`(配合 Service `@DataScope`
6. **禁止** SELECT *,显式列出字段
7. **禁止** MySQL 专属语法(`LIMIT 0,10``IFNULL``DATE_FORMAT``FIND_IN_SET`
8. 达梦函数:`NVL` 替代 `IFNULL``TO_CHAR` 替代 `DATE_FORMAT`
9. **禁止** Mapper 中加 `@Transactional` 或业务逻辑
10. 批量操作优先 `<foreach>`**禁止** 循环单条调用 Mapper
## 分页说明
分页由 Controller 调用 `startPage()` 触发 PageHelper 拦截,Mapper XML **不需要** LIMIT 子句(PageHelper 自动适配达梦)。
---
description: 类名、方法名、数据库表名、HTTP 路径命名规范(RuoYi Cloud)
globs: ["**/*.java", "**/*.sql"]
alwaysApply: false
---
# 命名规范(RuoYi Cloud)
## 类命名
| 类型 | 规范 | 示例 |
|------|------|------|
| 实体 | `{Entity}` | `JzObject` |
| Service 接口 | `I{Entity}Service` | `IJzObjectService` |
| Service 实现 | `{Entity}ServiceImpl` | `JzObjectServiceImpl` |
| Mapper | `{Entity}Mapper` | `JzObjectMapper` |
| Controller | `{Entity}Controller` | `JzObjectController` |
| 可选 VO | `{Entity}Vo` | `JzObjectVo` |
| Feign DTO | `Remote{Entity}DTO` | `RemoteUserDTO` |
## Service 方法命名(若依代码生成器风格)
| 场景 | 方法名 | 返回类型 |
|------|--------|----------|
| 按 ID 查询 | `select{Entity}By{IdField}(String id)` | `{Entity}` |
| 列表查询 | `select{Entity}List({Entity} query)` | `List<{Entity}>` |
| 新增 | `insert{Entity}({Entity} entity)` | `int` |
| 修改 | `update{Entity}({Entity} entity)` | `int` |
| 删除单条 | `delete{Entity}ById(String id)` | `int` |
| 批量删除 | `delete{Entity}ByIds(String[] ids)` | `int` |
> 内部校验方法以 `validate` 开头,`private`,放在 ServiceImpl 末尾。
## 数据库表命名
- 格式:小写蛇形或业务标准表名(如 `jz_object`)
- 智慧矫正标准表可沿用司法部标准字段名(大写蛇形,如 `JZ_OBJECT`)
- 规避达梦关键字
- 必须含审计字段:`create_by`、`create_time`、`update_by`、`update_time`(通过 BaseEntity 映射)
- 需要逻辑删除时加 `del_flag`(CHAR(1),0=存在 2=删除)
## HTTP 路径命名
- Controller:`@RequestMapping("/{businessPath}")`
- 示例:`/OBJECT`、`/user`、`/dept`
- 网关路由后完整路径由模块服务名 + Controller 路径组成
| 操作 | 方法 | 路径模式 |
|------|------|---------|
| 分页列表 | GET | `/list` |
| 详情 | GET | `/{id}` |
| 新增 | POST | `/` |
| 修改 | PUT | `/` |
| 删除 | DELETE | `/{ids}` |
| 导出 | POST | `/export` |
## 权限标识命名
- 格式:`{module}:{business}:{action}`
- action 取值:`list`、`query`、`add`、`edit`、`remove`、`export`、`import`
- 示例:
- `busi:OBJECT:list`
- `busi:OBJECT:add`
- `system:user:edit`
## 前端 API 文件命名
- 路径:`ruoyi-ui/src/api/{module}/{business}.js`
- 方法名:`listXxx`、`getXxx`、`addXxx`、`updateXxx`、`delXxx`、`exportXxx`
---
description: 操作日志(@Log)使用规范,编辑 Controller 时激活
globs: ["**/*Controller.java"]
alwaysApply: false
---
# 操作日志规范(@Log)
> 本项目使用 RuoYi 内置 `@Log` 注解,**未引入** `@ApiAccessLog`。
> 操作日志写入 `sys_oper_log` 表,由框架 AOP 自动记录。
## 哪些接口必须加 @Log
| 操作类型 | BusinessType | 是否必须 |
|---------|--------------|---------|
| 新增 | `BusinessType.INSERT` | ✅ |
| 修改 | `BusinessType.UPDATE` | ✅ |
| 删除 | `BusinessType.DELETE` | ✅ |
| 导出 | `BusinessType.EXPORT` | ✅ |
| 导入 | `BusinessType.IMPORT` | ✅ |
| 授权/强制退出等 | `BusinessType.GRANT` / `FORCE` 等 | 按场景 |
| 普通查询/分页 | — | ❌ 不需要 |
## 标准用法
```java
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
@Log(title = "社区矫正对象", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody JzObject jzObject) { ... }
@Log(title = "社区矫正对象", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody JzObject jzObject) { ... }
@Log(title = "社区矫正对象", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids) { ... }
@Log(title = "社区矫正对象", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, JzObject query) { ... }
```
## 参考:SysUserController
```java
@Log(title = "用户管理", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysUser user) { ... }
@Log(title = "用户管理", businessType = BusinessType.IMPORT)
@PostMapping("/importData")
public AjaxResult importData(MultipartFile file, boolean updateSupport) { ... }
```
## 关键约束
- ✅ `@Log` 只加在 **Controller 方法**上
- ✅ `title` 用中文模块名,与菜单/业务名称一致
- ✅ 增删改、导入、导出**必须**加
- ❌ 普通 GET 列表/详情**不需要**加
- ❌ **禁止**使用 `@ApiAccessLog`(项目未引入)
- ❌ **禁止**在 Service 层加操作日志注解
## 敏感字段
RuoYi `@Log` 不内置 `sanitizeKeys`。若请求体含密码等敏感字段:
- 在 VO/Domain 上用 `@JsonIgnore` 避免序列化到日志
- 或在 Service 层处理,不在日志中打印敏感值
---
description: Controller Service 层编写规范(RuoYi Cloud 标准模板)
globs: ["**/*Controller.java", "**/*Service.java", "**/*ServiceImpl.java"]
alwaysApply: false
---
# Controller & Service 规范(RuoYi Cloud
## Controller 标准模板
```java
package com.ruoyi.busi.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.common.security.annotation.RequiresPermissions;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.busi.domain.{Entity};
import com.ruoyi.busi.service.I{Entity}Service;
/**
* {中文业务名称}Controller
*
* @author ruoyi
*/
@RestController
@RequestMapping("/{path}")
public class {Entity}Controller extends BaseController
{
@Autowired
private I{Entity}Service {entity}Service;
/**
* 查询{中文名称}列表
*/
@RequiresPermissions("busi:{path}:list")
@GetMapping("/list")
public TableDataInfo list({Entity} query)
{
startPage();
List<{Entity}> list = {entity}Service.select{Entity}List(query);
return getDataTable(list);
}
/**
* 导出{中文名称}列表
*/
@RequiresPermissions("busi:{path}:export")
@Log(title = "{中文名称}", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, {Entity} query)
{
List<{Entity}> list = {entity}Service.select{Entity}List(query);
ExcelUtil<{Entity}> util = new ExcelUtil<{Entity}>({Entity}.class);
util.exportExcel(response, list, "{中文名称}数据");
}
/**
* 获取{中文名称}详细信息
*/
@RequiresPermissions("busi:{path}:query")
@GetMapping(value = "/{id}")
public AjaxResult getInfo(@PathVariable("{id}") String id)
{
return success({entity}Service.select{Entity}ById(id));
}
/**
* 新增{中文名称}
*/
@RequiresPermissions("busi:{path}:add")
@Log(title = "{中文名称}", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody {Entity} entity)
{
return toAjax({entity}Service.insert{Entity}(entity));
}
/**
* 修改{中文名称}
*/
@RequiresPermissions("busi:{path}:edit")
@Log(title = "{中文名称}", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody {Entity} entity)
{
return toAjax({entity}Service.update{Entity}(entity));
}
/**
* 删除{中文名称}
*/
@RequiresPermissions("busi:{path}:remove")
@Log(title = "{中文名称}", businessType = BusinessType.DELETE)
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable String[] ids)
{
return toAjax({entity}Service.delete{Entity}ByIds(ids));
}
}
```
### Controller 关键约束
- 继承 `BaseController`,使用 `success()` / `toAjax()` / `getDataTable()`
- 分页:`startPage()` 必须在 Service 查询前调用
- 权限:`@RequiresPermissions("模块:业务:操作")`,操作含 list/query/add/edit/remove/export
- 日志:增删改、导入、导出加 `@Log(title, businessType)`
- 注入:`@Autowired` 注入 Service**禁止**注入 Mapper
- **禁止** try-catch**禁止** 业务逻辑
> 操作日志详见 `java-operate-log.mdc`
---
## Service 接口标准模板
```java
/**
* {中文名称}Service接口
*
* @author ruoyi
*/
public interface I{Entity}Service
{
public {Entity} select{Entity}ById(String id);
public List<{Entity}> select{Entity}List({Entity} query);
public int insert{Entity}({Entity} entity);
public int update{Entity}({Entity} entity);
public int delete{Entity}ByIds(String[] ids);
}
```
---
## ServiceImpl 标准模板
```java
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.datascope.annotation.DataScope;
/**
* {中文名称}Service业务层处理
*
* @author ruoyi
*/
@Service
public class {Entity}ServiceImpl implements I{Entity}Service
{
@Autowired
private {Entity}Mapper {entity}Mapper;
@Override
public {Entity} select{Entity}ById(String id)
{
return {entity}Mapper.select{Entity}ById(id);
}
@Override
public List<{Entity}> select{Entity}List({Entity} query)
{
return {entity}Mapper.select{Entity}List(query);
}
// 若涉及部门/用户数据权限(参考 system 模块),在列表方法上加:
// @DataScope(deptAlias = "d", userAlias = "u")
@Override
public int insert{Entity}({Entity} entity)
{
entity.setCreateTime(DateUtils.getNowDate());
return {entity}Mapper.insert{Entity}(entity);
}
@Override
public int update{Entity}({Entity} entity)
{
entity.setUpdateTime(DateUtils.getNowDate());
return {entity}Mapper.update{Entity}(entity);
}
@Override
@Transactional(rollbackFor = Exception.class)
public int delete{Entity}ByIds(String[] ids)
{
// 删除前业务校验
for (String id : ids)
{
validateBeforeDelete(id);
}
return {entity}Mapper.delete{Entity}ByIds(ids);
}
/**
* 删除前校验
*/
private void validateBeforeDelete(String id)
{
{Entity} entity = {entity}Mapper.select{Entity}ById(id);
if (entity == null)
{
throw new ServiceException("{中文名称}不存在");
}
// 其他业务规则...
}
}
```
### ServiceImpl 关键约束
- 异常:`throw new ServiceException("用户可读的中文")`
- 事务:`@Transactional(rollbackFor = Exception.class)` 只加在 ServiceImpl
- 审计字段:`DateUtils.getNowDate()` 填充 createTime/updateTime
- 校验方法:`private`,以 `validate` 开头,放类末尾
- 注入:`@Autowired`,只注入本模块 Mapper
---
description: MCP 连接数据库后 AI 生成代码时的数据库字段调整规范
globs: ["**/*.sql", "**/*.java", "**/domain/**/*.java"]
alwaysApply: true
---
# MCP 数据库协作规范(达梦 DM8 + RuoYi)
## 核心原则:表结构即合同
- **Domain 字段** ↔ **数据库列**,必须严格一致(resultMap 映射)
- **前端 form 字段** ↔ **Domain 字段**,必须覆盖所有可编辑项
- AI 调整字段时,**SQL + Domain + Mapper XML + 前端** 必须同步修改
## 允许 AI 做的操作
- ✅ 新增业务字段(同步 Domain + XML + DDL + 前端表单)
- ✅ 调整字段长度
- ✅ 新增索引
- ✅ 增加列注释(达梦 `COMMENT ON COLUMN`)
## 禁止 AI 做的操作
- ❌ 删除已有列
- ❌ 修改列名(破坏历史映射)
- ❌ 修改主键类型
- ❌ 无 WHERE 条件的 UPDATE/DELETE
- ❌ MySQL 专属语法
## 调整字段时必须同时输出
```sql
-- 1. DDL(sql/ 目录,达梦语法)
ALTER TABLE jz_object ADD name VARCHAR(100);
COMMENT ON COLUMN jz_object.name IS '名称';
```
```java
// 2. Domain 字段
/** 名称 */
private String name;
```
```xml
<!-- 3. Mapper XML resultMap + SQL 片段 -->
<result property="name" column="name" />
```
```javascript
// 4. 前端表单字段
// form.name + el-form-item prop="name"
```
## RuoYi 业务表框架字段
通过 `BaseEntity` 映射(按需存在于数据库):
| 列名 | Java 字段 | 类型 |
|------|----------|------|
| create_by | createBy | VARCHAR |
| create_time | createTime | TIMESTAMP |
| update_by | updateBy | VARCHAR |
| update_time | updateTime | TIMESTAMP |
| remark | remark | VARCHAR |
逻辑删除(若启用):
| 列名 | 说明 |
|------|------|
| del_flag | CHAR(1),0=存在 2=删除 |
> 本项目 **无** `tenant_id` 多租户列(非 yudao TenantBaseDO 模式)。
## 字段类型映射
| Java 类型 | 达梦类型 | 说明 |
|----------|---------|------|
| String | VARCHAR(N) | 主键/文本 |
| String | CHAR(1) | 状态标志 |
| Integer | INT | 数值 |
| Date | TIMESTAMP | 时间 |
| Long | BIGINT | 大数值 |
## SQL 文件管理
- 路径:`platform/sql/`
- 命名:`{描述}.sql` 或 `V{yyyyMMdd}_{描述}.sql`
- 使用达梦语法,禁止 MySQL 函数
- 已执行脚本禁止修改,新需求新建文件
## 函数替换(MySQL → 达梦)
| MySQL | 达梦 |
|-------|------|
| IFNULL | NVL |
| DATE_FORMAT | TO_CHAR |
| NOW() | SYSDATE |
| LIMIT n,m | PageHelper 自动处理 / OFFSET FETCH |
| FIND_IN_SET | INSTR 或其他等价写法 |
---
description: 以前台页面为输入、逐步生成 RuoYi 后台代码的标准流程
globs: ["**/*.vue", "**/*.java", "**/*.js", "**/*.sql"]
alwaysApply: false
---
# 前台页面 → 后台代码生成流程
> 基于 RuoYi Cloud 3.6.8 + 代码生成器风格。
> **禁止**引入 yudao 的 SaveReqVO/PageReqVO/ErrorCodeConstants 作为默认产出。
## 核心原则
**禁止一次性生成所有文件**。按三阶段推进,每阶段等待用户确认。
```
阶段一:分析页面 → 输出功能描述(只文字,不写代码)
↓ 用户确认
阶段二:输出文件任务清单(只列清单,不写代码)
↓ 用户确认
阶段三:逐文件生成代码(每次一个文件,等待确认)
```
---
## 阶段一:分析页面,输出功能描述
```markdown
## 模块名称
{中文名称}
## 数据实体:{Entity}
| 字段名 | 中文含义 | 前台控件 | 是否必填 | 数据库列 | 备注 |
|-------|--------|--------|--------|---------|------|
| xxx | ... | el-input | ✅ | xxx | |
## 接口清单
| 序号 | 方法 | 路径 | 功能 | 入参 | 出参 |
|-----|------|------|------|------|------|
| 1 | GET | /list | 分页列表 | Domain 查询条件 | TableDataInfo |
| 2 | GET | /{id} | 详情 | id | AjaxResult |
| 3 | POST | / | 新增 | Domain | AjaxResult |
| 4 | PUT | / | 修改 | Domain | AjaxResult |
| 5 | DELETE | /{ids} | 删除 | ids[] | AjaxResult |
| 6 | POST | /export | 导出 | Domain 查询条件 | 文件流 |
## 业务规则
- {校验逻辑}
## 数据字典
- {状态字段对应的 dict_type}
```
---
## 阶段二:标准文件清单
```markdown
## 后台代码文件任务清单
### 数据库
- [ ] 1. `sql/{table}.sql`(建表/ALTER,达梦语法)
### 后端 Java(ruoyi-modules/ruoyi-busi)
- [ ] 2. `domain/{Entity}.java`
- [ ] 3. `mapper/{Entity}Mapper.java`
- [ ] 4. `resources/mapper/busi/{Entity}Mapper.xml`
- [ ] 5. `service/I{Entity}Service.java`
- [ ] 6. `service/impl/{Entity}ServiceImpl.java`
- [ ] 7. `controller/{Entity}Controller.java`
### 前端(ruoyi-ui)
- [ ] 8. `src/api/{module}/{business}.js`
- [ ] 9. `src/views/{module}/{business}/index.vue`
### 字典(如有状态字段)
- [ ] 10. `sql/dict_{type}.sql`
共 {N} 个文件待生成。
```
---
## 阶段三:生成顺序
```
1. sql DDL
2. Domain 实体
3. Mapper 接口
4. Mapper XML
5. IService 接口
6. ServiceImpl
7. Controller
8. api/*.js
9. views/*.vue
10. 字典 SQL(如有)
```
### 每个文件生成后
```
✅ 文件 {N}/{Total} 已生成:`{路径}`
请确认后回复「继续」。
```
### 生成规范
- ❌ 不得省略 import、方法体、注解
- ❌ 不得使用 BaseMapperX / CommonResult / @PreAuthorize
- ✅ 必须使用 AjaxResult / TableDataInfo / @RequiresPermissions / @Log
- ✅ Controller 继承 BaseController
---
## 快捷指令
| 用户输入 | AI 行为 |
|--------|--------|
| 「继续」 | 生成下一个文件 |
| 「全部继续」 | 依次生成剩余文件 |
| 「跳过」 | 跳过当前文件 |
| 「重新生成」 | 重做当前文件 |
| 「查看清单」 | 输出进度清单 |
---
## 最终完成 Checklist
- [ ] DDL 已在 `sql/` 目录,达梦语法
- [ ] Domain 继承 BaseEntity,字段与数据库一致
- [ ] Controller 权限标识与菜单配置一致
- [ ] 前端 api 路径与 Controller 一致
- [ ] 字典已初始化(如有状态字段)
- [ ] 增删改/export 已加 @Log
---
description: 测试规范(RuoYi Cloud 后端 + Vue2 前端)
globs: ["**/*Test.java", "**/*Tests.java"]
alwaysApply: false
---
# 测试规范(RuoYi Cloud)
## 后端单元测试
### 测试类命名与位置
- 命名:`{Entity}ServiceImplTest`
- 位置:`src/test/java/`,与被测类同包路径
### 标准模板
```java
@SpringBootTest
@Transactional
@Rollback
class JzObjectServiceImplTest
{
@Autowired
private IJzObjectService jzObjectService;
@Test
@DisplayName("新增社区矫正对象 - 正常流程")
void testInsert_success()
{
JzObject obj = new JzObject();
obj.setXM("测试姓名");
int rows = jzObjectService.insertJzObject(obj);
assertTrue(rows > 0);
}
@Test
@DisplayName("删除不存在记录 - 应抛出 ServiceException")
void testDelete_notExists()
{
ServiceException ex = assertThrows(ServiceException.class,
() -> jzObjectService.deleteJzObjectBySQJZDXBH("not-exist-id"));
assertNotNull(ex.getMessage());
}
}
```
### 关键约束
- ✅ `@DisplayName` 中文描述
- ✅ `@Transactional + @Rollback` 防止污染数据库
- ✅ 业务异常用 `assertThrows(ServiceException.class, ...)`
- ✅ 注入用 `@Autowired`(与项目一致)
- ❌ 禁止测试间执行顺序依赖
- ❌ 禁止 `Thread.sleep()` 处理异步
## 前端测试(可选)
本项目前端以手动测试为主。若需自动化:
- 工具:Jest + Vue Test Utils(Vue2 兼容版)
- 接口调用必须 mock,禁止真实请求
- 参考 `ruoyi-ui` 现有页面结构编写
## 接口联调 Checklist
- [ ] GET `/list` 返回 TableDataInfo(rows + total)
- [ ] GET `/{id}` 返回 AjaxResult
- [ ] POST/PUT 返回 toAjax 结果
- [ ] 无权限时返回 403
- [ ] 业务校验失败返回 ServiceException 消息
- [ ] 导出接口返回 Excel 文件流
## 测试覆盖率建议
| 层级 | 重点 |
|------|------|
| ServiceImpl | 业务校验、异常分支、事务 |
| Controller | 权限注解、参数绑定 |
| Mapper XML | 复杂动态 SQL(集成测试) |
---
description: ruoyi-ui 前端 Vue2 + Element UI 代码规范
globs: ["**/ruoyi-ui/**/*.vue", "**/ruoyi-ui/**/*.js"]
alwaysApply: false
---
# 前端代码规范(ruoyi-ui / Vue2 + Element UI)
## 技术栈
- Vue 2.6 + Vue Router 3 + Vuex
- Element UI 2.x
- axios(`@/utils/request` 封装)
- 图标:`el-icon-xxx`
## 页面目录结构
```
ruoyi-ui/src/
├── api/{module}/{business}.js # 接口请求
├── views/{module}/{business}/
│ └── index.vue # 列表 + 表单弹窗
└── components/ # 全局组件(Pagination、DictTag 等)
```
## API 文件标准模板
```javascript
import request from '@/utils/request'
// 查询列表
export function listObject(query) {
return request({
url: '/busi/OBJECT/list',
method: 'get',
params: query
})
}
// 查询详细
export function getObject(id) {
return request({
url: '/busi/OBJECT/' + id,
method: 'get'
})
}
// 新增
export function addObject(data) {
return request({
url: '/busi/OBJECT',
method: 'post',
data: data
})
}
// 修改
export function updateObject(data) {
return request({
url: '/busi/OBJECT',
method: 'put',
data: data
})
}
// 删除
export function delObject(id) {
return request({
url: '/busi/OBJECT/' + id,
method: 'delete'
})
}
```
## 列表页标准结构
```vue
<template>
<div class="app-container">
<!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter.native="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 操作按钮 -->
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['busi:OBJECT:add']">新增</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<!-- 表格 -->
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.busi_status" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['busi:OBJECT:edit']">修改</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['busi:OBJECT:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" />
<!-- 添加/修改对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<!-- 表单项 -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm">确 定</el-button>
<el-button @click="cancel">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
```
## 关键约束
| 约束 | 说明 |
|------|------|
| 请求封装 | 必须用 `@/utils/request`,禁止裸 axios |
| 权限指令 | `v-hasPermi="['模块:业务:操作']"` |
| 字典 | `dicts: ['xxx']` + `<dict-tag>` / `dict.type.xxx` |
| 分页 | `<pagination>` 组件,pageNum/pageSize |
| 删除确认 | `this.$modal.confirm(...)` |
| 消息提示 | `this.$modal.msgSuccess()` / `msgError()` |
| 主键类型 | **string**,禁止 number(防雪花 ID 精度丢失) |
| 表单校验 | `el-form` rules,必填项标红 |
| 提交防抖 | 按钮 loading + disabled |
## 禁止事项
- ❌ 使用 Vue3 / Element Plus / Pinia / Vite 语法(本项目是 Vue2)
- ❌ 使用 `SqSearchTableFrame` 等 yudao 自定义组件
- ❌ 页面硬编码字典状态文本
- ❌ 硬编码 API 地址,必须走 api/*.js
- ❌ 表单提交 catch 中重复弹错误(request 拦截器已处理)
## 参考页面
- 列表 CRUD:`ruoyi-ui/src/views/system/user/index.vue`
- 字典管理:`ruoyi-ui/src/views/system/dict/index.vue`
--- ---
description: 全项目代码通用强制自检清单,所有Java、Vue、UniApp、SQL文件全局生效 description: 全项目代码通用强制自检清单(与 .cursor/rules/ai-checklist.mdc 同步)
globs: ["**/*.java","**/*.vue","**/*.ts","**/*.sql","**/*.xml","**/*.vue"] globs: ["**/*.java","**/*.vue","**/*.js","**/*.sql","**/*.xml"]
alwaysApply: true alwaysApply: true
--- ---
# 冲突优先级声明
若本规则与其他专项规则冲突,专项业务规则优先级高于本文件;达梦数据库、Java编码禁令、信创约束拥有最高不可覆盖优先级。 > **框架基线**:RuoYi Cloud 3.6.8 + MyBatis + PageHelper + 达梦 DM8 + Vue2/Element UI。
> 与 `.cursor/rules/ai-checklist.mdc` 保持一致;若有冲突以 `.cursor/rules` 为准。
# 通用代码强制自检清单(若依微服务+达梦8+信创,无会议/BPM)
## 一、Java 通用红线 # AI 生成代码规范 — 核心约束
1. 依赖注入统一 @Resource,禁止 @Autowired;
2. 禁止连环set赋值,DO/VO全部使用@Builder链式构建; ## Java 强制规则摘要
3. 禁止手写getter/setter,统一Lombok @Data;
4. 非空判断统一Hutool工具类(StrUtil/CollUtil),禁止裸判空; - 异常:`throw new ServiceException("中文业务提示")`,禁止 RuntimeException
5. 禁止魔法数字/字符串,统一枚举、常量类; - 响应:`AjaxResult` / `TableDataInfo`,Controller 继承 `BaseController`
6. 多层if嵌套改用卫语句,禁止深度嵌套; - 时间:`java.util.Date` + `DateUtils.getNowDate()`,禁止强行改 LocalDateTime
7. 循环内禁止调用Mapper,统一批量操作; - 注入:`@Autowired`,Controller 禁止注入 Mapper
8. 时间统一 LocalDateTime,禁止 Date/Timestamp; - 权限:`@RequiresPermissions("模块:业务:操作")`,禁止 `@PreAuthorize`
9. 所有业务异常统一 ServiceExceptionUtil,禁止直接new RuntimeException; - 日志:增删改/导入/导出加 `@Log`,禁止 `@ApiAccessLog`
10. Service查询无数据必须抛异常,禁止return null; - Mapper:接口 + XML,禁止 MyBatis-Plus / BaseMapperX
11. Controller禁止try-catch,使用若依全局异常处理器; - 跨模块:`ruoyi-api` Feign,禁止 server 互依赖
12. Controller禁止直接注入Mapper,仅允许注入Service; - 数据权限:`@DataScope` 按需(system 模块常用,busi 模块不强制)
13. 微服务跨模块调用仅允许Feign DTO远程调用,禁止直接依赖对方server模块;
14. 所有新增表/字段必须适配达梦8语法,禁止MySQL专属函数; ## 前端强制规则摘要
15. 项目无BPM流程、会议预约相关业务,禁止新增Flowable依赖、审批监听、流程表单代码。
- Vue2 + Element UI + `@/utils/request`
## 二、SQL & 达梦8 强制红线 - 主键 ID 用 string
1. 主键统一String雪花ID,达梦8禁止自增ID,不使用序列作为业务主键; - 字典用 `dict-tag`,禁止硬编码状态
2. 时间字段使用达梦 TIMESTAMP,禁止 TIMESTAMPTZ; - 删除需二次确认,提交按钮 loading 防抖
3. 分页使用达梦分页语法,禁止MySQL LIMIT/OFFSET逗号写法;
4. 表名、字段名全部小写蛇形,规避达梦关键字; ## 禁止引入
5. 必须包含租户、软删除、创建人、创建时间等框架字段;
6. 字典初始化SQL适配达梦insert语法,兼容信创达梦驱动; yudao 框架类(CommonResult、TenantBaseDO、ServiceExceptionUtil、SaveReqVO 等)
7. 禁止使用MySQL专属函数:IFNULL、DATE_FORMAT等,替换达梦对应函数;
8. 不创建会议、审批流程相关数据表、索引、初始化数据。
## 三、前端双端通用红线(管理后台Vue3 + UniApp APP)
1. ID统一string类型,禁止number,避免雪花ID精度丢失;
2. 表单基础校验使用el-form/uni-form内置提示,业务逻辑弹窗提示;
3. 禁止页面硬编码魔法状态、文本,统一枚举/字典翻译;
4. API请求统一封装若依axios请求,禁止原生fetch/axios裸调用;
5. 所有删除、批量操作增加二次确认弹窗;
6. APP端适配国产安卓系统,避免闭源第三方SDK;
7. 页面类型区分:管理后台页面、APP表单页面,规范目录拆分;
8. 不开发流程审批、会议预约类页面、弹窗、表单组件。
## 四、信创强制约束(全代码通用)
1. 第三方依赖优先选用国产化开源包,剔除国外闭源组件;
2. SQL脚本、配置文件兼容国产服务器(鲲鹏、飞腾CPU);
3. JDK统一使用国产龙芯/鲲鹏适配OpenJDK,禁止Oracle JDK;
4. 中间件使用国产东方通、金蝶,不使用Tomcat商业版、WebLogic;
5. 打包产物支持信创容器镜像,无海外镜像依赖;
6. 所有功能无依赖境外API、境外存储服务。
## 五、微服务通用约束
1. 多模块拆分遵循若依微服务标准:gateway、system、business、api;
2. 远程调用统一Feign接口,DTO隔离,server模块不互相依赖;
3. 配置全部存入Nacos,禁止本地yml硬编码环境配置;
4. 接口路径统一 /api/{模块}/{功能},网关统一路由转发;
5. 权限标识遵循 模块:业务:操作 格式,适配若依Sa-Token鉴权;
6. 分布式防重复提交使用Redis幂等注解,适配微服务多实例。
--- ---
description: 达梦8 DM8数据库全局强制规范,信创数据库最高优先级规则 description: 达梦8 DM8数据库全局规范(与 .cursor/rules 同步)
globs: ["**/*.sql","**/*DO.java","**/*Mapper.xml"] globs: ["**/*.sql","**/*Mapper.xml","**/domain/**/*.java"]
alwaysApply: true alwaysApply: true
--- ---
# 达梦8(DM8)数据库规范 信创适配
## 一、达梦 8 字段类型强制约束 # 达梦 8(DM8)数据库规范
1. 雪花 ID 主键:Java String,达梦 `VARCHAR(20)`**禁止 BIGINT 自增、禁止序列做主键**
2. 状态、枚举值:Java Integer,达梦 `INT` ## 字段类型
3. 短文本名称:`VARCHAR(100)`,长描述 `VARCHAR(500)`
4. 时间统一 `TIMESTAMP`**禁止 TIMESTAMPTZ、DATE 单独存储时分秒** | Java | 达梦 | 说明 |
5. 布尔值使用 `BIT`,0/1; |------|------|------|
6. JSON 数组、复杂集合存储使用 `TEXT`,配合 MyBatis-Plus JacksonTypeHandler; | String | VARCHAR(N) | 主键/文本 |
7. 不使用达梦大字段 CLOB/BLOB,业务文本统一 VARCHAR/TEXT。 | Integer | INT | 状态枚举 |
| Date | TIMESTAMP | 时间(映射 BaseEntity) |
## 二、DDL 脚本达梦专属规范 | String | CHAR(1) | del_flag 逻辑删除 |
1. 表名、字段名全部小写蛇形命名,规避达梦系统关键字;
2. 注释使用 `COMMENT ON TABLE` / `COMMENT ON COLUMN` 达梦标准语法; ## DDL 规范
3. 新增字段使用 `ALTER TABLE 表名 ADD COLUMN xxx 类型 约束 COMMENT '注释'`
4. 建表语句包裹 `BEGIN;``COMMIT;`,事务执行; - 表名/字段名小写蛇形,规避关键字
5. 索引创建语法:`CREATE INDEX idx_xxx ON table_name(col);`;唯一索引 `CREATE UNIQUE INDEX` - 注释:`COMMENT ON TABLE/COLUMN`(达梦语法)
6. 达梦分页语法:`OFFSET x LIMIT y`,禁止 MySQL LIMIT 0,10 逗号写法; - 脚本放 `sql/` 目录,禁止 MySQL 专属语法
7. 达梦函数替换 MySQL 函数: - 逻辑删除:`del_flag CHAR(1) DEFAULT '0'`
- IFNULL → NVL
- DATE_FORMAT → TO_CHAR ## MyBatis(非 MyBatis-Plus)
- NOW() → SYSDATE
- SUBSTRING → SUBSTR - Mapper 为接口 + XML,**禁止** BaseMapperX / Wrapper
- 分页:Controller `startPage()` + PageHelper,XML **不写** LIMIT
## 三、MyBatis-Plus 适配达梦 8 - 模糊查询:沿用若依 `concat('%', #{field}, '%')`
1. Mapper 继承 `BaseMapperX`(项目封装适配达梦),禁止原生 BaseMapper; - 禁止 SELECT *,参数全部 `#{}`
2. 分页使用 `LambdaQueryWrapperX` 空值安全条件,达梦分页自动适配;
3. 禁止 MySQL 专属 XML SQL,所有原生 SQL 必须兼容达梦; ## 函数替换
4. 主键注解统一 `@TableId(type = IdType.ASSIGN_ID)`,达梦全局关闭自增;
5. 软删除使用 MyBatis-Plus 逻辑删除,达梦 BIT 字段自动适配。 | MySQL | 达梦 |
|-------|------|
## 四、达梦 8 信创部署约束 | IFNULL | NVL |
1. 驱动包使用达梦官方国产化驱动 DmJdbcDriver,不使用兼容 MySQL 驱动; | DATE_FORMAT | TO_CHAR |
2. 数据库字符集统一 GB18030,适配信创中文存储; | NOW() | SYSDATE |
3. 排序规则统一达梦中文排序,避免中文查询乱序; | FIND_IN_SET | INSTR 等等价写法 |
4. 生产环境达梦 8 部署在鲲鹏 / 飞腾国产服务器,禁止 x86 海外服务器;
5. 数据库备份脚本适配达梦 dexp/dimp 工具,不使用 mysqldump; ## 禁止
6. 账号权限最小化,业务账号仅拥有 DML 权限,DDL 仅 DBA 可执行,满足等保信创要求。
- MyBatis-Plus 注解(@TableName、@TableId 等)
## 五、数据库开发禁止事项 - MySQL LIMIT 逗号分页、IFNULL、DATE_FORMAT
❌ 禁止使用自增主键、序列作为业务主键; - 无 WHERE 的全表 UPDATE/DELETE
❌ 禁止 MySQL 专属函数、分页语法;
❌ 禁止字段名、表名使用达梦保留关键字不加转义;
❌ 禁止存储过程、触发器承载大量业务逻辑,业务全部下沉 Java 服务层;
❌ 禁止 TEXT/CLOB 存储超长业务文本,拆分字段;
❌ 禁止手动更新 deleted 软删除字段,使用框架内置逻辑删除方法;
❌ 禁止达梦数据库存储境外加密、境外第三方数据;
❌ 禁止创建会议、审批流程相关数据表、存储过程、触发器。
--- ---
description: 若依微服务前后端协作规范(Vue管理后台 + UniApp APP双端,无会议/BPM description: 全栈协作规范(与 .cursor/rules/fullstack-collaboration.mdc 同步
globs: ["**/*.java","**/*.vue","**/*.ts","**/*.sql","**/*.js"] globs: ["**/*.java","**/*.vue","**/*.js","**/*.sql"]
alwaysApply: true alwaysApply: true
--- ---
# 冲突优先级声明
达梦数据库、Java编码、信创部署规则优先级高于本文件;若依微服务专项架构规则冲突时以专项文件为准。 # 全栈协作规范(RuoYi Cloud)
# 若依微服务全栈协作规范 ## 技术栈
## 一、前后端字段映射标准(统一适配达梦8)
### TS类型 → Java类型 → 达梦8字段映射 - 后端:Spring Cloud + MyBatis + PageHelper + 达梦 DM8
| 前端TS类型 | Java实体类型 | 达梦8列类型 | 说明 | - 前端:Vue2 + Element UI + `@/utils/request`
| ---- | ---- | ---- | ---- |
| string(雪花ID) | String | VARCHAR(20) | 主键,防止精度丢失 | ## 接口对应
| number(状态枚举) | Integer | INT | 业务状态、字典值 |
| string(名称文本) | String | VARCHAR(100) | 名称、标题 | | 前端 | 后端 | 返回 |
| string(长描述) | String | VARCHAR(500) | 备注、描述 | |------|------|------|
| string(ISO时间) | LocalDateTime | TIMESTAMP | 统一时间类型 | | GET /list | list() | TableDataInfo |
| boolean | Boolean | BIT | 布尔标识 | | GET /{id} | getInfo() | AjaxResult |
| string[] | List<String> | TEXT | JSON数组存储,JacksonTypeHandler | | POST / | add() | AjaxResult |
| PUT / | edit() | AjaxResult |
## 二、前端页面推导后端代码流程 | DELETE /{ids} | remove() | AjaxResult |
1. 管理后台Vue页面、UniApp APP页面,先提取全部表单字段、列表查询条件、接口请求;
2. 区分双端接口隔离:管理后台接口、APP移动端独立接口,禁止复用同一套Controller; ## 生成顺序
3. 后端分层严格遵循:SQL DDL(达梦语法)→ DO → Mapper → VO → Controller → Service;
4. 跨模块查询使用Feign远程调用,不直接操作其他业务Mapper; sql → domain → mapper → xml → service → controller → api.js → index.vue
5. 字典、枚举前后端同步,后端存数字code,前端通过若依字典组件自动翻译中文;
6. 分页统一PageResult返回,前端PageReqVO继承若依PageParam。 ## 禁止
## 三、微服务接口路径规范 - yudao 路径(/create、CommonResult)
1. 管理后台接口前缀:`/api/admin/{module}/{business}` - Vue3 / Element Plus 语法
2. APP移动端接口前缀:`/api/app/{module}/{business}`
3. 公共基础模块接口:`/api/common/{function}`
4. CRUD固定后缀:/create /update /delete /get /page /export-excel
## 四、双端代码产出区分
1. Vue管理后台:基于Element Plus,SqSearchTableFrame标准列表框架;
2. UniApp APP端:uni-form、uni-data-select、uni-list等原生组件,适配移动端触控;
3. 公共类型统一抽离api/types.ts,后台与APP类型文件隔离,不共用;
4. APP端不展示复杂后台管理字段(租户ID、创建人、操作日志等)。
## 五、数据库字段对齐强制要求
1. DO驼峰字段 ↔ 达梦表下划线字段完全一一对应;
2. SaveReqVO覆盖前端所有可编辑字段,不含框架内置字段;
3. RespVO增加富化展示字段(关联名称、字典中文),DO不存储;
4. 新增字段必须同步:达梦ALTER脚本、DO实体、前后端VO类型。
## 六、信创前后端适配要求
1. 前端打包产物无海外CDN资源,静态资源本地化;
2. UniApp打包支持国产安卓系统、国产芯片设备;
3. 前端加密、工具类使用国产加密算法(SM2/SM3/SM4),禁用RSA国际算法;
4. 接口日志脱敏手机号、身份证等敏感信息,满足信创等保规范。
--- ---
description: Java编码八大强制红线禁令(最高优先级Java规则,达梦、信创规则除外,无BPM/会议 description: Java编码红线(与 .cursor/rules/java-coding-standards.mdc 同步
globs: ["**/*.java"] globs: ["**/*.java"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
本文件为Java代码最高强制约束,仅达梦数据库、信创部署规则优先级高于本文件,其余所有Java相关规则冲突时以本文件为准。
# Java编码强制八大禁令(若依微服务+达梦8+信创) # Java 编码红线(RuoYi Cloud)
## 禁令1:禁止连环set硬赋值,统一@Builder链式构建
❌ 错误:new DO() 后逐行setXxx
✅ 正确:DO实体添加@Builder、@NoArgsConstructor、@AllArgsConstructor,使用DO.builder().field(val).build()
## 禁令2:禁止手写getter/setter,统一Lombok @Data 1. **禁止**手动 new Service/Mapper,统一 `@Autowired` 注入
❌ 手动编写get/set方法 2. **禁止** Controller 直接注入 Mapper
✅ 所有DO、VO、DTO统一使用@Data,配合@EqualsAndHashCode(callSuper = true) 3. **禁止** `RuntimeException`,统一 `ServiceException("中文提示")`
4. **禁止** Controller try-catch 吞异常
5. **禁止**裸判空,使用 `StringUtils.isNotEmpty()`
6. **禁止**魔法数字/字符串,用常量或字典
7. **禁止**多层 if-else,用卫语句
8. **禁止**循环内单条 Mapper 调用,用 XML `<foreach>` 批量
9. 时间用 `java.util.Date`,写入用 `DateUtils.getNowDate()`
10. 事务 `@Transactional(rollbackFor = Exception.class)` 只加 ServiceImpl
## 禁令3:依赖注入统一@Resource,完全禁止@Autowired ## 禁止引入
❌ 混用@Autowired和@Resource
✅ Controller、ServiceImpl中所有Mapper、Service、Feign接口全部使用@Resource注入
## 禁令4:非空判断禁止裸判断,统一Hutool工具类 MyBatis-Plus、yudao(CommonResult、ServiceExceptionUtil 等)
❌ if(str != null && !str.equals("")) / if(list != null && list.size()>0)
✅ 字符串:StrUtil.isNotBlank();集合:CollUtil.isNotEmpty();对象:ObjectUtil.isNotNull()
## 禁令5:禁止魔法数字、魔法字符串,统一枚举/常量类
❌ 直接写if(status == 0)、return "goods_offline"
✅ 业务状态定义枚举,固定文本、阈值写入XXXConstants常量类
## 禁令6:禁止多层if-else嵌套,卫语句优先,复杂状态使用策略模式
❌ 超过2层if嵌套
✅ 所有边界、校验条件前置,提前return/抛异常,消除else分支;状态机多分支采用策略模式
## 禁令7:循环内部禁止调用Mapper单条操作,统一批量方法
❌ for循环中mapper.insert() / mapper.deleteById()
✅ 批量插入insertBatch、批量删除deleteBatchIds、条件批量更新wrapper更新,单次DB交互
## 禁令8:时间类型统一LocalDateTime,完全禁止Date、Timestamp
❌ java.util.Date、java.sql.Timestamp
✅ DO、VO、DTO时间字段全部使用LocalDateTime,达梦8 TIMESTAMP字段对应
# 补充强制编码约束
1. 业务异常统一 ServiceExceptionUtil.exception(ErrorCode),禁止直接new RuntimeException、IllegalArgumentException;
2. Service查询无数据必须抛不存在异常,禁止return null区分不存在;
3. Controller禁止编写try-catch捕获业务异常,使用若依全局异常处理器;
4. Controller禁止直接注入Mapper,仅允许注入对应Service;
5. 跨模块调用仅允许注入Feign API接口,禁止依赖对方ServiceImpl;
6. 所有类、Service接口方法、DO字段必须添加中文Javadoc注释;
7. 错误提示文案使用业务操作人员易懂中文,禁止技术术语、数据库字段名、英文编码;
8. 新增/修改/删除/导出接口必须添加@ApiAccessLog操作日志注解;
9. 创建、状态变更接口必须添加@Idempotent幂等注解防重复提交;
10. 所有DO主键统一String雪花ID,@TableId(type = IdType.ASSIGN_ID),适配达梦8;
11. 禁止引入Flowable、BPM流程审批相关类、注解、依赖。
--- ---
description: 对象转换Convert类规范,DO/VO/DTO分层隔离转换 description: 对象转换规范(与 .cursor/rules/java-convert.mdc 同步)
globs: ["**/*Convert.java"] globs: ["**/*ServiceImpl.java","**/*Controller.java"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
Java编码规范、达梦实体规则优先级高于本文件。
# 对象转换Convert类开发规范 # 对象转换规范
## 一、基础规范
1. 存放路径:convert包下,命名 XxxConvert;
2. 类添加 @Mapper(componentModel = "spring") 注解,使用MapStruct自动生成转换实现;
3. 所有转换方法为静态/实例抽象方法,禁止手动编写set赋值转换逻辑;
4. 转换类只做对象属性拷贝,不编写业务计算、数据查询逻辑。
## 二、标准转换方法定义 - **默认**:Controller/Service 直接使用 Domain 实体
### 1. DO ↔ RespVO - 字段不一致时:Service 层组装 Vo 或 `BeanUtils.copyProperties`
RespVO toRespVO(DO entity); - Feign 跨模块:独立 DTO,禁止传 Domain
List<RespVO> toRespVOList(List<DO> list);
### 2. SaveReqVO → DO ## 禁止
DO toDO(SaveReqVO reqVO);
### 3. DO ↔ Feign DTO(跨服务传输) - 强制要求 XxxConvert 类(yudao 模式)
DTO toDTO(DO entity); - Convert 中写业务校验
DO toDO(DTO dto);
List<DTO> toDTOList(List<DO> list);
## 三、特殊字段转换处理规则
1. 字典翻译、关联名称等富化字段:转换基础拷贝后,在Service层单独赋值,Convert不处理;
2. 时间字段 LocalDateTime 自动映射,无需额外转换配置;
3. 雪花ID String类型自动映射,无精度丢失问题;
4. 枚举字段:统一存储Integer编码,转换时直接拷贝数字,中文翻译在VO层处理;
5. 集合List<String> JSON字段:MyBatis类型处理器处理,转换层直接拷贝。
## 四、MapStruct 注解配置规范
1. 字段名称完全一致时,无需额外@Mapping;
2. 字段名称不一致时,添加映射注解:
@Mapping(source = "userId", target = "uid")
3. 忽略不需要拷贝的字段:
@Mapping(target = "richName", ignore = true)
4. 禁止使用复杂表达式在@Mapping中,复杂逻辑交给Service处理。
## 五、Convert通用禁止项
❌ 禁止手动new对象+连环set做转换,必须MapStruct自动生成;
❌ 禁止在转换方法中调用Mapper、Feign、Service查询数据;
❌ 禁止转换类添加业务工具方法、常量;
❌ 禁止跨模块直接转换VO与DO,跨服务只能通过DTO中转;
❌ 禁止转换方法返回null,空集合统一返回空列表Collections.emptyList()。
--- ---
description: 业务枚举、数据字典前后端同步规范,适配若依字典+达梦初始化SQL description: 枚举与字典同步(与 .cursor/rules/java-dict-enum-sync.mdc 同步)
globs: ["**/*Enum.java","**/*.sql"] globs: ["**/*Enum.java","**/*.sql"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
达梦数据库规范、Java编码规范优先级高于本文件。
# 枚举 & 数据字典同步开发规范 # 枚举与数据字典
## 一、业务枚举开发规范
1. 存放路径:enums包,命名 XxxEnum;
2. 枚举固定结构:code(Integer编码)、desc(中文描述);
3. 基础方法:getCode()、getDesc(),提供静态工具方法根据code获取枚举;
4. 所有业务状态、类型、标识全部使用枚举,禁止硬编码魔法数字;
5. 枚举添加中文类注释、每个实例添加单行注释说明业务含义;
6. 禁止枚举中编写数据库查询、远程调用、复杂业务逻辑。
示例标准枚举: - 字典表:`sys_dict_type` + `sys_dict_data`
public enum GoodsStatusEnum { - 后端存 value(字符串),前端 `dict-tag` 翻译
UP(1, "上架"), - 新增字典同步:`sql/` 达梦初始化脚本 + 前端 `dicts: ['xxx']`
DOWN(2, "下架");
private final Integer code; ## 禁止
private final String desc;
GoodsStatusEnum(Integer code, String desc) { - @DictFormat / DictTypeConstants(yudao 专属)
this.code = code; - 前端硬编码状态文本
this.desc = desc;
}
// getter、根据code查询工具方法
}
## 二、若依数据字典规范
1. 系统字典复用内置两张表:sys_dict_type(字典类型)、sys_dict_data(字典项);
2. 字典类型编码规则:`business_xxx`,区分系统字典与业务字典;
3. 达梦初始化SQL规范:
1. 先判断字典类型不存在再插入;
2. 批量插入字典项,适配达梦INSERT多行语法;
3. 所有字符串值使用单引号,注释符合达梦语法;
4. 前后端同步规则:
- 后端存储数字code;
- 管理后台Vue使用 <dict-tag /> 组件自动翻译中文;
- UniApp APP端封装全局字典翻译工具,根据code展示中文;
5. 区分使用场景:
- 固定不变、全项目通用状态:优先使用Java枚举;
- 支持后台动态新增修改的分类、标签:使用数据库数据字典。
## 三、枚举与字典同步约束
1. 若业务同时使用枚举+字典,必须保证code编码完全一致,避免前后端翻译错乱;
2. 新增业务状态时,同步更新枚举类、字典初始化SQL、前端字典选项;
3. 禁止枚举code与字典项value不一致,统一Integer数字编码;
4. 生产环境字典初始化脚本仅执行新增,不修改已有字典项,避免线上数据变更风险。
## 四、禁止事项
❌ 禁止业务状态硬编码数字,必须枚举/字典;
❌ 禁止字典初始化SQL使用MySQL专属语法,严格适配达梦;
❌ 禁止枚举存储字符串编码,统一Integer;
❌ 禁止前端硬编码状态文本,全部依赖枚举/字典翻译;
❌ 禁止动态可变业务分类使用Java枚举,必须数据库字典。
--- ---
description: DO/ReqVO/RespVO/DTO实体规范,适配达梦8雪花ID、字段类型映射 description: Domain/VO 规范(与 .cursor/rules/java-do-vo.mdc 同步)
globs: ["**/*DO.java","**/*VO.java","**/*DTO.java"] globs: ["**/domain/**/*.java"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
达梦数据库全局规则、Java编码禁令优先级高于本文件。
# DO、VO、DTO 实体开发规范(达梦8适配) # Domain 实体规范
## 一、DO 数据库实体规范
1. 存放路径:domain/dataobject,命名 Xxx;
2. 基础注解:
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("xxx")
3. 主键字段统一:
@TableId(type = IdType.ASSIGN_ID)
private String id;
4. 必须包含框架通用字段:creator、createTime、updater、updateTime、deleted;
5. 字段类型严格遵循达梦8映射规则,时间统一LocalDateTime,布尔使用Boolean;
6. 复杂数组/集合字段添加类型处理器注解:
@TableField(typeHandler = JacksonTypeHandler.class)
private List<String> tagList;
7. 禁止在DO中添加业务计算字段、字典翻译字段,翻译逻辑统一在RespVO处理;
8. 所有字段添加中文注释,说明业务含义。
## 二、ReqVO 请求VO规范 - 继承 `BaseEntity`(createBy/createTime/updateBy/updateTime/remark/params)
### 1. SaveReqVO(新增/编辑共用) - 时间字段:`java.util.Date`
1. 命名:XxxSaveReqVO; - 导出字段:`@Excel(name = "...")`
2. 仅包含前端可编辑业务字段,**不包含id、租户、创建人、创建时间、软删除**等框架字段; - 代码生成器产出传统 JavaBean(getter/setter)
3. 字段校验注解统一使用Hibernate Validator:@NotBlank、@NotNull、@Size、@Min、@Max; - 可选 VO:仅字段需隔离/脱敏时使用
4. 时间字段统一LocalDateTime;ID、编码类文本统一String;
### 2. PageReqVO(分页查询) ## 禁止
1. 命名:XxxPageReqVO,继承若依框架 PageParam;
2. 仅包含分页参数、业务模糊查询、状态筛选条件;
3. 禁止分页VO携带大文本、复杂数组参数;
4. 所有查询条件允许为空,不强制@NotNull。
## 三、RespVO 返回VO规范 - @TableName / @TableId(MyBatis-Plus)
1. 命名:XxxRespVO; - TenantBaseDO、LocalDateTime
2. 包含DO全部基础字段,额外增加富化展示字段(如分类名称、字典中文名称、关联业务名称); - Domain 中放无 DB 列的富化字段
3. 富化字段仅用于前端展示,不参与新增/编辑保存;
4. 时间统一LocalDateTime,序列化输出标准ISO格式;
5. 字典状态字段同时返回数字编码和中文翻译,方便前端展示。
## 四、Feign DTO 传输对象规范
1. 命名:XxxDTO,存放于ruoyi-business-api模块;
2. DTO仅存储跨服务传输必要字段,精简冗余字段;
3. 禁止将DO、VO直接作为Feign接口入参/返回值;
4. DTO不添加数据库相关注解(@TableName、@TableId等);
5. 基础注解仅保留@Data、@Builder,按需构造无参/全参构造。
## 五、实体通用禁止项
❌ 禁止DO直接返回前端,必须通过RespVO转换;
❌ 禁止SaveReqVO携带主键ID做新增操作;
❌ 禁止DTO中使用LocalDate、Date,统一LocalDateTime;
❌ 禁止实体字段使用基本类型(int、long、boolean),统一包装类型(Integer、Long、Boolean);
❌ 禁止在VO/DTO中编写业务逻辑方法,实体仅做数据载体。
--- ---
description: 全局错误码分段管理规范,微服务多模块隔离 description: 业务异常规范(与 .cursor/rules/java-error-code.mdc 同步)
globs: ["**/ErrorCodeConstants.java"] globs: ["**/*ServiceImpl.java"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
Java编码规范优先级高于本文件。
# 全局错误码常量规范 # 业务异常规范
## 一、错误码分段规则(无BPM分段)
采用三段式数字编码:`模块段_子模块_序号`
1. system系统模块:1_001_001 ~ 1_001_999
用户、部门、角色、菜单、字典、登录权限相关错误;
2. business业务模块:1_100_001 ~ 1_999_999
所有自定义业务模块错误码,每个业务子模块分配100个序号区间;
3. 通用框架错误:1_000_001 ~ 1_000_999
参数校验、幂等、文件上传、导出、远程调用通用异常。
## 二、常量定义规范 - 使用 `throw new ServiceException("用户可读的中文")`
1. 统一存放于 `ErrorCodeConstants.java` 常量类; - 复杂模块可建 `BusiErrorMessages` 常量类复用文案
2. 常量命名:全大写,下划线分隔,业务含义清晰;
3. 常量值严格遵循分段编码,注释写明异常提示文案;
4. 示例:
// 商品模块-商品不存在
public static final Integer GOODS_NOT_EXIST = 1_100_001;
5. 同一业务模块错误码按业务流程顺序递增,预留间隔序号便于后续扩展;
6. 禁止重复错误码,新增错误码前检查已存在常量。
## 三、异常文案规范 ## 禁止
1. 错误提示面向业务操作人员,使用通俗中文;
2. 禁止文案包含数据库字段名、技术术语、英文编码;
3. 参数校验类文案清晰指明错误字段,例:"商品名称不能为空";
4. 远程调用、服务异常文案屏蔽底层技术细节,统一友好提示。
## 四、使用规范 - ErrorCodeConstants / ServiceExceptionUtil(yudao 专属)
1. 业务抛出异常统一使用工具类: - 技术术语、英文字段名作错误提示
ServiceExceptionUtil.exception(ErrorCodeConstants.GOODS_NOT_EXIST);
2. 禁止直接在代码中写数字错误码,全部引用常量;
3. 捕获Feign远程调用异常时,透传远端错误码与提示文案;
4. 前端接收错误码,可根据特定错误码做页面特殊处理(如跳转登录、弹窗提示)。
## 五、禁止事项
❌ 禁止使用重复错误码;
❌ 禁止硬编码数字错误码,必须引用常量;
❌ 禁止文案暴露底层技术、数据库、服务名称;
❌ 禁止跨模块混用错误码分段,严格按区间分配;
❌ 禁止新增BPM流程相关错误码分段。
--- ---
description: 分布式幂等注解 @Idempotent 使用规范,基于Redis实现微服务防重复提交 description: 防重复提交规范(与 .cursor/rules/java-idempotent.mdc 同步)
globs: ["**/controller/**/*.java"] globs: ["**/*Controller.java","**/*.vue"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
Controller三层规范、Java编码规范优先级高于本文件。 # 防重复提交规范
# 分布式幂等防重复提交规范 > 项目**未引入** `@Idempotent`。依赖前端按钮 loading/disabled + 后端唯一性校验。
## 一、注解基础说明
使用项目自定义 `@Idempotent` 注解,基于Redis实现分布式幂等控制,防止用户快速重复点击、网络重试造成重复新增、重复扣款、重复生成数据问题,适配微服务多实例集群环境。 ## 前端(必须)
## 二、注解属性配置规范 - 提交按钮 `:loading` + `:disabled`
1. expireTime:幂等key过期时间,单位秒; - 删除用 `this.$modal.confirm()`
- 新增、编辑表单:默认5秒;
- 提交复杂业务、导出任务:设置30~60秒; ## 后端(兜底)
2. message:重复提交时返回的提示文案,示例:"请勿重复提交表单";
3. keyType:幂等key生成策略: - 创建前唯一性校验,重复时 `throw new ServiceException("...")`
- TOKEN:基于用户登录Token + 接口路径(表单页面通用); - 可选:Redis 锁、数据库唯一索引
- PARAM:基于指定请求参数(唯一编码、订单号等唯一性字段)。
## 禁止
## 三、强制添加幂等注解的接口
1. POST /create 新增业务数据接口; - 使用 @Idempotent / @RepeatSubmit(未引入)
2. PUT /update 修改核心业务数据接口; - GET 接口做幂等拦截
3. 状态变更、数据生成、批量处理接口;
4. APP端表单提交、订单创建类接口;
## 四、使用约束
1. 注解仅添加在Controller接口方法上;
2. 所有面向用户提交、可重复点击的写接口,必须配置@Idempotent;
3. 读接口(分页查询、详情查询、导出)无需添加幂等注解;
4. Redis统一使用国产化分布式缓存,不依赖境外Redis商业版本;
5. 幂等key自动绑定当前登录用户,用户之间互不干扰。
## 五、禁止事项
❌ 新增、编辑、业务提交接口不添加幂等注解,存在重复提交风险;
❌ 自定义本地内存锁替代分布式Redis幂等,集群多实例失效;
❌ 幂等提示文案使用技术术语,必须使用通俗易懂业务提示;
❌ 导出、单纯查询接口滥用@Idempotent注解,浪费Redis资源。
--- ---
description: Mapper接口与XML规范,适配达梦8分页、函数、语法 description: Mapper 与 XML 规范(与 .cursor/rules/java-mapper.mdc 同步)
globs: ["**/*Mapper.java","**/*Mapper.xml"] globs: ["**/*Mapper.java","**/*Mapper.xml"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
达梦数据库全局规则优先级最高,其次为Java编码规范。
# Mapper层开发规范(达梦8专属适配) # Mapper 层规范(MyBatis + 达梦 8)
## 一、Mapper接口规范
1. 存放路径:mapper,命名 XxxMapper;
2. 自定义查询方法命名规范:
- selectXxxByXxx:单条件查询列表
- countXxxByXxx:统计数量
- deleteXxxBatch:批量删除
- updateXxxBatch:批量更新
4. 方法入参:单参数直接传;多参数使用@Param("xxx")注解;
5. 禁止在Mapper接口编写业务逻辑,仅做数据库CRUD操作。
## 二、Mapper XML 文件规范 ## 接口
1. XML与Mapper接口同目录,文件名与接口名完全一致 XxxMapper.xml;
2. namespace 严格对应Mapper接口全类名;
3. 通用字段复用sql片段,抽取公共查询列、通用条件:
<sql id="common_column">
id, creator, create_time, updater, update_time, deleted
</sql>
4. 分页查询统一使用达梦分页语法 OFFSET #{offset} LIMIT #{pageSize},禁止MySQL逗号分页;
5. 函数统一使用达梦内置函数 NVL、TO_CHAR、SYSDATE,禁止IFNULL、DATE_FORMAT、NOW();
6. 所有SQL关键字大写(SELECT、FROM、WHERE、LEFT JOIN、ORDER BY),字段、表名下划线小写;
7. 禁止写SELECT *,必须明确查询需要的字段,减少IO开销。
## 三、MyBatis-Plus Wrapper 查询规范 - 路径:`com.ruoyi.{module}.mapper`
1. 业务查询统一使用 LambdaQueryWrapperX、LambdaUpdateWrapperX,项目封装适配达梦; - 命名:`selectXxxById``selectXxxList``insertXxx``updateXxx``deleteXxxByIds`
2. 等值查询:eq;模糊查询:like;范围查询:ge、le; - 禁止继承 BaseMapper / BaseMapperX
3. 多条件拼接使用链式调用,禁止硬编码SQL字符串;
4. 分页查询调用 mapper.selectPage(page, wrapper),分页参数由上层PageParam转换;
5. 批量操作优先使用BaseMapperX提供的批量方法:insertBatch、updateBatchById。
## 四、达梦适配强制约束 ## XML
1. 不使用自增主键、序列,主键由框架雪花ID生成;
2. 关联查询多表时,表别名简洁(t1、t2),避免关键字冲突;
3. 文本模糊查询长度适配达梦VARCHAR,超长文本使用TEXT字段查询;
4. 批量操作单次数据量控制在500条以内,防止达梦事务压力过大;
5. 禁止在XML中使用MySQL专属注释、引擎、字符集配置。
## 五、Mapper开发禁止项 - 路径:`resources/mapper/{module}/XxxMapper.xml`
❌ 禁止继承原生BaseMapper,必须BaseMapperX; - namespace 与接口全类名一致
❌ 禁止SELECT * 查询所有字段; - 动态条件:`<if test="...">`
❌ 禁止MySQL分页、MySQL专属函数; - 数据权限:`${params.dataScope}`(配合 @DataScope)
❌ 禁止循环调用Mapper单条操作,统一批量方法; - 模糊查询:`concat('%', #{name}, '%')`(若依现有写法)
❌ 禁止在XML中硬编码租户ID、软删除条件,统一框架自动填充; - 分页:不在 XML 写 LIMIT,由 PageHelper 拦截
❌ 禁止存储过程、复杂函数在XML中调用,业务逻辑下沉Service层。
## 禁止
- MyBatis-Plus Wrapper(LambdaQueryWrapperX 等)
- SELECT *、MySQL 专属函数
- Mapper 上加 @Transactional 或业务逻辑
--- ---
description: Java类、方法、数据库表、接口路径、权限标识全量命名规范(若依微服务+达梦8,无会议/BPM description: 命名规范(与 .cursor/rules/java-naming.mdc 同步
globs: ["**/*.java","**/*.sql","**/*.yml"] globs: ["**/*.java","**/*.sql"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
达梦数据库规范、Java编码禁令优先级高于本文件。
# 全项目统一命名规范 # 命名规范
## 一、Java类命名
| 类类型 | 命名格式 | 示例 |
| ---- | ---- | ---- |
| 数据库DO实体 | {业务}DO | GoodsDO |
| 创建更新请求VO | {业务}SaveReqVO | GoodsSaveReqVO |
| 分页查询请求VO | {业务}PageReqVO | GoodsPageReqVO |
| 响应VO | {业务}RespVO | GoodsRespVO |
| Feign远程DTO | {业务}DTO | GoodsDTO |
| Service接口 | {业务}Service | GoodsService |
| Service实现 | {业务}ServiceImpl | GoodsServiceImpl |
| Mapper接口 | {业务}Mapper | GoodsMapper |
| 转换类Convert | {业务}Convert | GoodsConvert |
| 枚举类 | {业务}Enum | GoodsStatusEnum |
| 错误码常量 | ErrorCodeConstants | 统一文件追加 |
| Controller后台 | {业务}AdminController | GoodsAdminController |
| Controller移动端APP | {业务}AppController | GoodsAppController |
## 二、Service方法命名统一标准 | 类型 | 规范 | 示例 |
| 功能 | 方法名 | 返回值 | |------|------|------|
| ---- | ---- | ---- | | 实体 | `{Entity}` | `JzObject` |
| 新增创建 | create{Entity} | String(雪花ID) | | Service | `I{Entity}Service` / `{Entity}ServiceImpl` | `IJzObjectService` |
| 更新 | update{Entity} | void | | Mapper | `{Entity}Mapper` | `JzObjectMapper` |
| 删除单条 | delete{Entity} | void | | Controller | `{Entity}Controller` | `JzObjectController` |
| 批量删除 | delete{Entity}ListByIds | void |
| 根据ID查询(不存在抛异常) | get{Entity} | DO实体 |
| 根据ID查询(允许空) | get{Entity}IfExists | DO实体 |
| 分页查询 | get{Entity}Page | PageResult<DO> |
## 三、达梦8数据库命名规范 ## HTTP 路径
1. 业务表前缀 `business_`,格式 `business_{模块}_{业务}`,全小写蛇形;
示例:`business_goods_info``business_user_address`
2. 字段全小写蛇形,与DO驼峰字段一一映射;
3. 索引命名:普通索引 `idx_字段名`;唯一索引 `uk_字段名`
4. 字典系统表复用若依自带 `sys_dict_type``sys_dict_data`,不新建字典表。
## 四、微服务接口路径命名 - GET `/list`、GET `/{id}`、POST `/`、PUT `/`、DELETE `/{ids}`、POST `/export`
1. 管理后台接口:`/api/admin/{模块}/{业务}`
示例:`/api/admin/business/goods`
2. APP移动端接口:`/api/app/{模块}/{业务}`
示例:`/api/app/business/goods`
3. CRUD固定后缀:
创建 POST `/create`;更新 PUT `/update`;删除 DELETE `/delete`
查询单条 GET `/get`;分页 GET `/page`;导出 GET `/export-excel`
## 五、权限标识命名(Sa-Token) ## 权限
格式:`{模块}:{业务}:{操作}`
操作固定枚举:create / update / delete / query / export
示例:`business:goods:create``business:goods:query`
## 六、常量&魔法值命名 - `busi:OBJECT:list` / `add` / `edit` / `remove` / `export` / `query`
1. 业务状态全部枚举类,禁止硬编码数字;
2. 全局固定阈值、模板ID、字典Key统一放入XXXConstants常量类;
3. 错误码分段规范:
- system系统模块:1_001_xxx_xxx
- business业务模块:1_100_xxx_xxx
## 七、前端文件命名 ## 前端 API
1. Vue后台列表页面:index.vue;表单抽屉:XxxFormDrawer.vue;详情抽屉:XxxDetailDrawer.vue;
2. UniApp APP页面:短横线kebab-case命名; - `ruoyi-ui/src/api/{module}/{business}.js`
3. API类型文件:types.ts;接口请求文件:index.ts。 - 方法:`listXxx``getXxx``addXxx``updateXxx``delXxx`
--- ---
description: 若依框架操作日志注解 @ApiAccessLog 使用规范 description: 操作日志 @Log 规范(与 .cursor/rules/java-operate-log.mdc 同步)
globs: ["**/controller/**/*.java"] globs: ["**/*Controller.java"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
Controller三层规范、Java编码规范优先级高于本文件。 # 操作日志规范(@Log)
# 操作日志 @ApiAccessLog 使用规范 > 使用 RuoYi `@Log` + `BusinessType`,**禁止** `@ApiAccessLog`。
## 一、注解基础说明
使用若依内置注解 `@ApiAccessLog`,自动记录操作人、操作时间、接口地址、请求参数、操作类型、耗时,满足信创等保审计日志要求。 ## 必须加 @Log 的接口
## 二、注解必填属性规范 - INSERT / UPDATE / DELETE / EXPORT / IMPORT
1. title:必填,模块业务中文名称,例:"商品管理";
2. operateType:操作类型枚举,可选值: ## 示例
- CREATE:新增
- UPDATE:编辑修改 ```java
- DELETE:删除 @Log(title = "社区矫正对象", businessType = BusinessType.INSERT)
- EXPORT:导出Excel @PostMapping
- QUERY:查询(分页/详情) public AjaxResult add(@RequestBody JzObject jzObject) { ... }
3. saveRequestData:布尔值,默认true,记录请求参数;敏感接口(含身份证、手机号)设置为false,防止日志泄露隐私。 ```
## 三、接口注解使用强制规则 ## 禁止
1. 以下接口**必须添加@ApiAccessLog**
- POST /create 新增 - 普通 GET 列表/详情加 @Log
- PUT /update 编辑 - Service/Mapper 层加日志注解
- DELETE /delete 删除 - 使用 @ApiAccessLog
- GET /export-excel 导出
2. 查询接口(分页、详情)按需添加,内部管理系统建议全部记录;APP端普通查询可省略日志注解;
3. 注解仅允许添加在Controller接口方法上,禁止在Service、Mapper层使用。
## 四、日志脱敏规范
1. 接口参数包含手机号、身份证、银行卡、家庭地址等敏感字段时:
1. @ApiAccessLog(saveRequestData = false) 关闭参数记录;
2. 或全局配置日志脱敏规则,自动隐藏敏感信息中间字符;
2. 生产环境日志持久化存储,保留至少6个月审计日志,符合信创等保三级要求。
## 五、禁止事项
❌ 新增/修改/删除/导出接口不添加操作日志注解;
❌ 在Service、Mapper、Convert等非Controller层使用日志注解;
❌ 敏感隐私接口完整记录明文身份证、手机号;
❌ 自定义日志打印替代框架统一@ApiAccessLog日志,分散审计日志。
## 4、01_java_ruoyi_cloud_architecture.mdc
```mdc
--- ---
description: 若依RuoYi-Vue-Cloud微服务工程分层、模块分包、Nacos/Feign/Gateway规范(无BPM模块 description: RuoYi Cloud 工程架构(与 .cursor/rules/java-architecture.mdc 同步
globs: ["**/*.java","**/pom.xml","**/application.yml","**/bootstrap.yml"] globs: ["**/*.java","**/pom.xml"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
达梦数据库、Java编码禁令优先级高于本文件;本文件规范优先级高于通用全栈协作规则。
# 若依微服务工程架构规范(RuoYi-Vue-Cloud) # RuoYi Cloud 3.6.8 架构
## 一、标准模块拆分(移除ruoyi-bpm流程模块)
1. `ruoyi-gateway` 网关模块:路由转发、鉴权、跨域、限流、请求日志; ## 模块
2. `ruoyi-system` 系统基础模块:用户、部门、角色、菜单、字典、操作日志;
3. `ruoyi-business-api` 业务公共API模块:Feign远程调用DTO、接口定义(仅接口、DTO,无业务实现);
4. `ruoyi-business-server` 业务实现服务模块:所有业务CRUD、ServiceImpl、Mapper、DO;
5. `ruoyi-common` 通用工具模块:常量、工具类、异常、枚举、全局返回体;
6. `ruoyi-admin` 管理后台前端;`ruoyi-app` UniApp移动端前端。
## 二、包结构标准(business-server业务模块) - ruoyi-gateway / ruoyi-auth / ruoyi-api / ruoyi-common
com.ruoyi.business.{业务模块名} - ruoyi-modules(system、gen、job、file、**busi**
├── controller 业务控制器(统一继承 BaseController,区分后台 / APP 接口) - ruoyi-ui(Vue2 前端)
├── domain 数据库实体 DO(达梦表映射实体,替换旧 dal/dataobject)
├── domain/vo 各类vo
├── mapper Mapper 接口(MyBatis-Plus 接口)
├── service
│ ├── impl ServiceImpl 业务实现类
│ └── 业务 Service 接口
├── convert 对象转换 Convert 类
├── enums 业务枚举、错误码常量
├── util 业务工具类
ruoyi-modules/ruoyi-busi/src/main/resources
├── mapper/busi Mapper.xml SQL 映射文件
├── application-dev.yml 开发环境配置
├── bootstrap.yml 启动配置
## 三、微服务核心组件规范 ## 包结构(busi 示例)
### 1. Nacos配置中心
1. 所有环境配置(数据库连接、Redis、Feign超时、线程池)存入Nacos;
2. bootstrap.yml仅配置Nacos地址、命名空间、集群;application.yml仅少量本地默认值;
3. 区分开发、测试、生产Nacos命名空间,生产配置加密存储(国产加密算法);
4. 达梦数据库连接池配置统一在Nacos,适配达梦驱动参数。
### 2. Feign远程调用(跨模块) ```
1. 跨服务调用仅允许通过 \`ruoyi-business-api\` 定义Feign接口; com.ruoyi.busi/
2. API模块仅存放接口、DTO数据传输对象,无任何业务实现代码; ├── controller/
3. Server模块之间禁止直接依赖,只能依赖对应API模块; ├── domain/ # 继承 BaseEntity
4. Feign调用异常统一捕获,使用若依全局异常处理,返回标准化CommonResult; ├── mapper/
5. Feign超时、重试策略在Nacos统一配置,适配微服务分布式场景。 ├── service/ + impl/
└── resources/mapper/busi/*.xml
```
### 3. Gateway网关 ## 框架能力
1. 所有接口请求统一经过网关,不允许服务直连访问;
2. 网关统一处理Sa-Token鉴权、跨域、接口限流、请求参数脱敏;
3. 路由规则区分admin后台、app移动端、内部服务接口;
4. 网关日志记录请求来源、耗时、操作人,满足信创等保审计要求。
### 4. Sa-Token 微服务鉴权 | 能力 | 类 |
1. 管理后台、APP端使用两套独立Token体系,权限隔离; |------|-----|
2. 接口必须添加 \`@PreAuthorize("@ss.hasPermission('模块:业务:操作')")\` 权限校验; | 响应 | AjaxResult / TableDataInfo |
3. APP移动端仅开放查询、提交保存等基础权限,禁止后台管理类权限; | 分页 | PageHelper + startPage() |
4. 分布式会话存储Redis,适配多实例微服务集群。 | 权限 | @RequiresPermissions |
| 认证 | TokenService + JWT/Redis |
| 日志 | @Log |
| 异常 | ServiceException |
| 跨模块 | @FeignClient(ruoyi-api) |
| 内部调用 | @InnerAuth + R<T> |
## 四、微服务部署&信创适配 ## 禁止
1. 所有服务打包为jar镜像,支持鲲鹏/飞腾国产CPU容器化部署;
2. 中间件国产化:Nacos国产适配版、东方通/TongWeb替代Tomcat;
3. Redis使用国产分布式缓存,禁用海外Redis企业版;
4. 服务日志输出适配国产日志采集工具,日志脱敏敏感信息;
5. 容器镜像不依赖海外Docker镜像源,全部本地化信创镜像。
## 五、模块依赖禁止事项 - MyBatis-Plus、yudao、Sa-Token、@PreAuthorize
❌ 禁止server模块互相直接依赖;跨模块仅依赖xxx-api;
❌ 禁止将业务实现代码写入api模块;
❌ 禁止硬编码环境地址、数据库连接,全部Nacos配置;
❌ 禁止Feign接口传DO数据库实体,统一使用隔离DTO;
❌ 禁止APP端Controller开放后台管理权限接口;
❌ 禁止微服务多实例本地缓存存储状态,分布式状态统一Redis;
❌ 禁止引入Flowable、BPM流程相关依赖包。
\ No newline at end of file
--- ---
description: Controller、Service、ServiceImpl三层代码模板规范,微服务鉴权、多租户适配 description: Controller/Service 规范(与 .cursor/rules/java-service-controller.mdc 同步)
globs: ["**/controller/**/*.java","**/service/**/*.java"] globs: ["**/controller/**/*.java","**/service/**/*.java"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
Java编码、达梦实体规范优先级高于本文件。
# Controller & Service & ServiceImpl 三层开发规范 # Controller & Service 规范(RuoYi Cloud)
## 一、Controller 分层规范
### 1. 基础约束
1. 存放路径:controller/;
2. AdminController:@RestController + @RequestMapping("/api/admin/business/xxx");
3. AppController:@RestController + @RequestMapping("/api/app/business/xxx");
4. 统一添加 @Tag 接口文档注解,标注模块名称;
5. 依赖注入仅注入对应Service,禁止直接注入Mapper、Feign(Feign在Service层注入);
6. 接口权限校验:@PreAuthorize("@ss.hasPermission('business:goods:query')");
7. APP端接口不添加后台管理类权限标识,仅做登录Token校验。
### 2. 标准CRUD接口模板 ## Controller
1. 新增 POST /create:入参SaveReqVO,返回雪花ID;添加@Idempotent、@ApiAccessLog;
2. 更新 PUT /update:入参SaveReqVO(携带id);添加@Idempotent、@ApiAccessLog;
3. 删除 DELETE /delete/{id}:路径ID,添加@ApiAccessLog;
4. 分页查询 GET /page:入参PageReqVO,返回PageResult<XxxRespVO>
5. 单条详情 GET /get/{id}:返回XxxRespVO;
6. 导出 GET /export-excel:分页查询数据,导出Excel,添加导出权限校验。
### 3. Controller禁止项 - 继承 `BaseController`
❌ 禁止Controller编写业务逻辑、数据库查询; - 返回 `AjaxResult` / `TableDataInfo`
❌ 禁止Controller捕获业务异常,全局统一异常处理器处理; - 分页:`startPage()` → Service 查询 → `getDataTable(list)`
❌ 禁止Controller直接注入Mapper、Feign接口; - 权限:`@RequiresPermissions("busi:OBJECT:list")`
❌ 禁止Admin与APP接口写在同一个Controller; - 日志:增删改/导出 `@Log(title, businessType)`
❌ 禁止接口路径、权限标识混用后台与移动端。 -`@Autowired` Service,禁止注入 Mapper
## 二、Service 接口规范 ## Service
1. 存放路径:service包,命名 XxxService;
2. 仅定义业务抽象方法,不编写实现逻辑;
3. 方法返回值规范:
- 新增:String(雪花ID)
- 更新/删除:void
- 单条查询:XxxDO(不存在抛异常)
- 分页查询:PageResult<XxxDO>
4. 所有方法添加中文Javadoc注释,写明入参、返回值、异常场景;
5. 跨服务远程调用方法,在Service接口定义对应方法。
## 三、ServiceImpl 实现类规范 - 接口:`I{Entity}Service`,实现:`{Entity}ServiceImpl`
1. 存放路径:service/impl,命名 XxxServiceImpl,实现XxxService; - 异常:`throw new ServiceException("...")`
2. 添加 @Service 注解; - 审计:`entity.setCreateTime(DateUtils.getNowDate())`
3. 依赖注入:@Resource 注入Mapper、Feign接口、其他Service; - `@DataScope` 按需(system 模块列表常用)
4. 业务分层逻辑:
1. 参数校验(非空、长度、状态合法性);
2. 数据库CRUD操作,批量数据处理;
3. 跨服务Feign远程调用;
4. 数据转换DO ↔ VO/DTO;
5. 组装分页、返回结果;
5. 多租户自动过滤:使用MyBatis-Plus租户插件,无需手动拼接租户条件;
6. 不存在数据统一抛出业务异常,禁止返回null。
## 四、通用三层统一约束 ## 禁止
1. 入参校验统一使用Hibernate Validator注解,Controller层自动校验;
2. 所有分页返回统一包装 PageResult,包含总条数、当前页、数据列表; - CommonResult、@PreAuthorize、@ApiAccessLog、@Idempotent
3. 时间、创建人等公共字段由MyBatis-Plus自动填充,无需手动set; - SaveReqVO 作为默认入参(直接用 Domain,除非字段需隔离)
4. 软删除统一框架逻辑删除,ServiceImpl不手动修改deleted字段。
--- ---
description: 若依Vue3管理后台前端规范(Element Plus description: ruoyi-ui 前端规范(与 .cursor/rules/vue-frontend.mdc 同步
globs: ["**/ruoyi-admin/**/*.vue","**/ruoyi-admin/**/*.ts"] globs: ["**/ruoyi-ui/**/*.vue","**/ruoyi-ui/**/*.js"]
alwaysApply: false alwaysApply: false
--- ---
# 冲突优先级声明
全局前后端协作规范优先级高于本文件。 # 前端规范(Vue2 + Element UI)
# 若依Vue3后台前端开发规范 ## 目录
## 一、页面目录结构规范
页面存放路径 `views/{业务模块}/`,目录拆分: - API:`ruoyi-ui/src/api/{module}/{business}.js`
1. index.vue:列表主页面(搜索栏、表格、新增/编辑弹窗入口); - 页面:`ruoyi-ui/src/views/{module}/{business}/index.vue`
2. XxxFormDrawer.vue:新增、编辑抽屉表单;
3. XxxDetailDrawer.vue:详情查看抽屉; ## 关键约束
4. components/:页面内部复用小型组件,不全局公用;
5. api/:当前模块接口请求文件; - 请求:`@/utils/request`
6. types.ts:当前模块TS类型定义。 - 权限:`v-hasPermi="['busi:OBJECT:add']"`
- 字典:`dicts: ['xxx']` + `<dict-tag>`
## 二、页面基础框架规范 - 分页:`<pagination>` + pageNum/pageSize
统一使用项目封装通用列表组件 `SqSearchTableFrame`,内置搜索区、表格、分页、新增/删除按钮插槽; - 删除:`this.$modal.confirm()`
1. 搜索表单使用el-form-item,搜索项控制在6个以内,多余折叠; - 主键 ID:**string** 类型
2. 表格列使用el-table-column,字典状态列使用 <dict-tag /> 自动翻译;
3. 表格操作列统一封装操作按钮组件,区分查看、编辑、删除; ## 参考
4. 删除、批量删除按钮绑定二次确认弹窗,提示用户确认操作;
5. 分页统一使用框架封装分页组件,参数pageNum、pageSize与后端PageReqVO对齐。 - `ruoyi-ui/src/views/system/user/index.vue`
## 三、表单抽屉规范 ## 禁止
1. 新增/编辑共用一套FormDrawer组件,通过入参id区分新增/编辑;
2. 表单校验使用el-form内置rules校验,必填项标红* - Vue3 / Element Plus / Pinia / Vite
3. 下拉选择、状态选择统一使用字典接口回显,禁止硬编码选项; - SqSearchTableFrame 等 yudao 组件
4. 表单提交统一调用封装api,成功后关闭抽屉并刷新表格列表; - 裸 axios/fetch
5. 复杂多行数据使用el-table内嵌表单行,支持新增、删除子行。
## 四、TS类型规范
1. types.ts 统一定义PageReq、SaveReq、Resp类型,与后端VO字段完全一致;
2. 所有ID字段定义为string,避免雪花ID数字精度丢失;
3. 状态枚举直接复用后端字典编码,前端不单独维护状态数字;
4. 接口请求统一封装axios工具,请求参数、返回值绑定TS类型。
## 五、前端通用禁止项
❌ 禁止页面硬编码字典状态、业务枚举数字;
❌ 禁止手动拼接接口地址,统一api文件导出请求方法;
❌ 禁止表单不做前端必填校验,仅依赖后端校验;
❌ 禁止表格操作无二次确认弹窗(删除、批量删除);
❌ 禁止TS类型中ID使用number类型,防止雪花ID精度丢失。
# 项目强制约束:RuoYi-Vue + SpringBoot + MyBatis-Plus + 达梦DM8数据库 # 智慧矫正项目强制约束(RuoYi Cloud 3.6.8)
# 项目强制约束:RuoYi-Vue + SpringBoot + MyBatis-Plus + 达梦DM8数据库 # 智慧矫正项目强制约束(RuoYi Cloud 3.6.8)
## 1. 框架架构约束(若依标准)
1. 严格遵循RuoYi-Vue前后端分层:controller/service/mapper/entity/dto > 详细规则见 `.cursor/rules/`,本文件为摘要。
2. 实体必须继承 BaseEntity,自带del_flag、create_by、create_time、update_by、update_time、dept_id
3. 列表查询方法必须加 @DataScope 数据权限注解,deptAlias、userAlias必填 ## 1. 框架架构
4. Controller统一继承 BaseController,返回 AjaxResult,禁止直接返回实体
5. 分页统一使用 PageUtils.startPage() + getDataTable,分页插件DbType固定DM 1. RuoYi Cloud 微服务:gateway / auth / api / common / modules / ui
6. 新增/修改统一使用 @Valid 入参校验,自定义校验注解实现业务规则 2. 业务模块:`ruoyi-modules/ruoyi-busi`,包路径 `com.ruoyi.busi.*`
7. 异常统一抛 RuoYiException,禁止裸try-catch只打印日志不抛出 3. 分层:controller → service(I*Service) → mapper → domain(BaseEntity)
4. Controller 继承 BaseController,返回 AjaxResult / TableDataInfo
## 2. 达梦DM8数据库SQL强制约束(最关键) 5. 分页:Controller `startPage()` + PageHelper
1. 禁用MySQL专属函数:FIND_IN_SET、REPLACE INTO、LIMIT、IFNULL、DATE_FORMAT 6. 异常:`ServiceException`(中文业务语言)
- FIND_IN_SET → INSTR(?, 字段) > 0 7. 权限:`@RequiresPermissions`,认证 TokenService + Redis
- REPLACE INTO → MERGE INTO 达梦语法
- LIMIT → OFFSET ... FETCH NEXT ... ROWS ONLY ## 2. 达梦 DM8
- IFNULL → NVL,DATE_FORMAT → TO_CHAR
2. 主键策略:禁用MySQL自增auto_increment,全部使用达梦SEQUENCE序列生成ID 1. 禁止 MySQL 专属函数(IFNULL、DATE_FORMAT、LIMIT 逗号分页等)
3. 建表DDL规范: 2. 主键按业务约定(标准表可用司法部字段名)
- 字段名统一小写,达梦表字段不加反引号`,不使用``包裹字段 3. 逻辑删除:`del_flag CHAR(1)`
- 字符串类型统一 VARCHAR2,日期 DATE/DATETIME,大文本 CLOB 4. MyBatis 接口 + XML,**非** MyBatis-Plus
- 必加逻辑删除字段 del_flag CHAR(1) DEFAULT '0' 5. 模糊查询沿用若依 `concat('%', #{field}, '%')`
- 权限字段 dept_id BIGINT、create_by BIGINT 必须存在业务表
4. MyBatis-Plus配置强制:分页插件 DbType.DM,禁止默认MYSQL ## 3. 前端
5. 禁止写SELECT *,必须显式列出查询字段
6. 批量操作禁止无条件UPDATE/DELETE,开启BlockAttackInnerInterceptor防全表更新 1. ruoyi-ui:Vue2 + Element UI
2. API 走 `@/utils/request`
## 3. 数据源与驱动约束 3. 字典:`sys_dict_type/data` + dict-tag
1. pom必须引入达梦驱动 com.dameng:Dm7JdbcDriver18,移除mysql-connector
2. druid数据源配置:driverClassName=dm.jdbc.driver.DmDriver ## 4. 禁止行为
url=jdbc:dm://127.0.0.1:5236/库名?schema=SYSDBA
3. 不使用MySQL专属配置,时区、zeroDateTimeBehavior等参数删除 - MyBatis-Plus、yudao(CommonResult、BaseMapperX 等)
- @PreAuthorize、@ApiAccessLog、@Idempotent
## 4. 代码生成器约束(Trae生成CRUD时强制) - LocalDateTime 替代 BaseEntity 的 Date
1. 生成mapper.xml自动适配达梦分页、序列主键 - Controller 直接注入 Mapper
2. 生成SQL脚本输出达梦DDL,不输出MySQL建表语句
3. 生成的Mapper接口禁止MySQL特有分页语法
4. 新增实体类自动添加序列注解 @KeySequence(value="SEQ_表名")
## 5. 安全与编码约束
1. SQL全部参数化查询,禁止字符串拼接SQL防注入
2. 日志使用 org.slf4j.Logger,禁止System.out/System.err
3. 公共方法必须写JavaDoc,controller接口加@ApiOperation
4. 禁止字段注入@Autowired,统一构造器注入
5. 敏感数据(手机号、身份证)入库前脱敏,查询返回脱敏
## 6. 禁止行为(AI生成代码绝对不能出现)
- 任何MySQL专属SQL语法、函数、关键字
- 自增主键auto_increment、`反引号包裹字段
- 硬编码数据库连接、账号密码
- 无@DataScope的业务列表查询接口
- 裸SELECT *、无WHERE的update/delete
- 不用达梦序列,使用mysql自增逻辑
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论