feat: 优化

This commit is contained in:
2025-12-27 18:17:10 +08:00
parent ad36382f60
commit effbbc694c
282 changed files with 66909 additions and 1131 deletions

View File

@@ -1,468 +0,0 @@
---
description: RuoYi Spring Boot 后端开发最佳实践与规范
globs: **/*.java, **/*.xml, **/*.yaml, **/*.yml
---
# RuoYi Spring Boot 后端开发规范
## 项目架构
## 代码规划
- 代码简洁易于人类阅读
### 模块结构
- `yudao-dependencies`: Maven 依赖版本统一管理
- `yudao-framework`: 框架拓展组件(技术组件)
- `yudao-server`: 服务启动模块
- `yudao-module-*`: 业务模块(如 system、member、ai 等)
### 分层架构
- **Controller 层**: 接收请求,参数校验,调用 Service
- **Service 层**: 业务逻辑处理,事务管理
- **Mapper 层**: 数据访问,使用 MyBatis Plus
- **VO 层**: 视图对象,用于前后端交互
- **DO 层**: 数据对象,对应数据库表
## 目录结构规范
### 模块目录结构
业务模块的标准目录结构如下:
```
yudao-module-{模块名}/
└── src/main/java/cn/iocoder/yudao/module/{模块名}/
├── controller/ # Controller 层
│ └── {Xxx}Controller.java
├── service/ # Service 层
│ ├── {Xxx}Service.java # Service 接口
│ ├── {Xxx}ServiceImpl.java # Service 实现类
│ └── {Xxx}Util.java # Service 工具类(可选)
├── mapper/ # Mapper 层
│ └── {Xxx}Mapper.java
├── dataobject/ # DO 对象(可选)
│ └── {Xxx}DO.java
├── vo/ # VO 对象
│ ├── {Xxx}SaveReqVO.java
│ ├── {Xxx}PageReqVO.java
│ ├── {Xxx}UpdateReqVO.java
│ └── {Xxx}RespVO.java
├── enums/ # 枚举类(可选)
│ └── {Xxx}Enum.java
└── mq/ # 消息队列(可选)
└── consumer/
└── {Xxx}Consumer.java
```
### 目录结构说明
- **mapper/**: Mapper 接口,继承 `BaseMapperX<T>`
- **dataobject/**: DO 对象(可选),继承 `BaseDO` 或 `TenantBaseDO`
- 如果模块没有 DO 对象,可以省略 `dataobject/` 包
### 包命名规范
#### Controller 包
- Controller 类名:`{Xxx}Controller` 或 `App{Xxx}Controller`
- 直接放在 `controller/` 包下
#### Service 包
- Service 接口:`{Xxx}Service.java`
- Service 实现:`{Xxx}ServiceImpl.java`
- Service 工具类:`{Xxx}Util.java` 或 `{Xxx}Helper.java`
#### Mapper 包
- Mapper 接口:`mapper/{Xxx}Mapper.java`
- Mapper 接口继承 `BaseMapperX<T>`
#### DO 包
- DO 对象:`dataobject/{Xxx}DO.java`(可选)
- DO 类名:`{Xxx}DO.java`
- 继承 `BaseDO` 或 `TenantBaseDO`
#### VO 包
- Request VO: `{Xxx}SaveReqVO`、`{Xxx}PageReqVO`、`{Xxx}UpdateReqVO`
- Response VO: `{Xxx}RespVO`
- App VO: `App{Xxx}ReqVO`、`App{Xxx}RespVO`
- 直接放在 `vo/` 包下
### 目录结构示例
#### 示例 2模块
```
file/
├── controller/
│ ├── AppTikUserFileController.java
│ ├── AppTikFileGroupController.java
│ └── AppTikTestController.java
├── service/
│ ├── TikUserFileService.java
│ ├── TikUserFileServiceImpl.java
│ ├── TikFileGroupService.java
│ └── TikFileGroupServiceImpl.java
├── mapper/
│ ├── TikUserFileMapper.java
│ └── TikFileGroupMapper.java
├── vo/
│ ├── AppTikUserFilePageReqVO.java
│ ├── AppTikUserFileRespVO.java
│ └── AppTikFileGroupCreateReqVO.java
└── enums/
└── TikFileCategoryEnum.java
```
### 目录结构原则
1. **统一性**:同一模块内保持结构一致
2. **简洁性**:使用 `mapper/`,结构清晰
3. **可选性**:省略 `dataobject/` 包
4. **可扩展性**:预留扩展空间,便于后续功能扩展
## Controller 层规范
### 注解使用
- 使用 `@RestController` 而非 `@Controller`
- 使用 `@RequestMapping` 定义基础路径
- 使用 `@Tag` 定义 Swagger 文档标签
- 使用 `@Operation` 定义接口说明
- 使用 `@Parameter` 定义参数说明
- 使用 `@Valid` 或 `@Validated` 进行参数校验
### 权限控制
- 管理后台接口使用 `@PreAuthorize("@ss.hasPermission('module:resource:action')")`
- 用户端接口通过 `getLoginUserId()` 获取当前用户,确保数据隔离
- 使用 `@PermitAll` 标记允许匿名访问的接口
### 返回值规范
- 统一使用 `CommonResult<T>` 包装返回值
- 使用 `success()` 静态方法返回成功结果
- 异常由全局异常处理器统一处理
### 代码示例
```java
@Tag(name = "管理后台 - 用户提示词")
@RestController
@RequestMapping("/ai/user-prompt")
@Validated
public class UserPromptController {
@Resource
private UserPromptService userPromptService;
@PostMapping("/create")
@Operation(summary = "创建用户提示词")
@PreAuthorize("@ss.hasPermission('ai:user-prompt:create')")
public CommonResult<Long> createUserPrompt(@Valid @RequestBody UserPromptSaveReqVO createReqVO) {
return success(userPromptService.createUserPrompt(createReqVO));
}
}
```
## Service 层规范
### 接口与实现
- Service 接口定义在 `service` 包下
- Service 实现类使用 `ServiceImpl` 后缀,实现对应接口
- 使用 `@Service` 注解标记
- 使用 `@Validated` 启用参数校验
### 事务管理
- 涉及数据库写操作的方法使用 `@Transactional(rollbackFor = Exception.class)`
- 查询方法不需要事务注解
- 避免在 Service 方法中捕获异常后不抛出,导致事务无法回滚
### 业务逻辑
- Service 层处理核心业务逻辑
- 使用 `BeanUtils.toBean()` 进行对象转换
- 使用 `validateXxxExists()` 方法校验数据存在性
- 使用 `ServiceExceptionUtil.exception()` 抛出业务异常
### 代码示例
```java
@Service
@Validated
public class UserPromptServiceImpl implements UserPromptService {
@Resource
private UserPromptMapper userPromptMapper;
@Override
@Transactional(rollbackFor = Exception.class)
public Long createUserPrompt(UserPromptSaveReqVO createReqVO) {
// 1. 校验
// 2. 转换
UserPromptDO userPrompt = BeanUtils.toBean(createReqVO, UserPromptDO.class);
// 3. 插入
userPromptMapper.insert(userPrompt);
// 4. 返回
return userPrompt.getId();
}
}
```
## Mapper 层规范
### 继承规范
- Mapper 接口继承 `BaseMapperX<T>`,而非 `BaseMapper<T>`
- `BaseMapperX` 提供了更强大的查询能力
### 方法命名
- 查询方法使用 `select` 前缀
- 插入方法使用 `insert` 前缀
- 更新方法使用 `update` 前缀
- 删除方法使用 `delete` 前缀
### 分页查询
- 使用 `selectPage(PageReqVO pageReqVO)` 进行分页查询
- 使用 `LambdaQueryWrapperX` 构建查询条件
### 代码示例
```java
@Mapper
public interface UserPromptMapper extends BaseMapperX<UserPromptDO> {
default PageResult<UserPromptDO> selectPage(UserPromptPageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<UserPromptDO>()
.likeIfPresent(UserPromptDO::getName, reqVO.getName())
.eqIfPresent(UserPromptDO::getCategory, reqVO.getCategory())
.betweenIfPresent(UserPromptDO::getCreateTime, reqVO.getCreateTime())
.orderByDesc(UserPromptDO::getId));
}
}
```
## VO 对象规范
### 命名规范
- Request VO: `XxxSaveReqVO`、`XxxPageReqVO`、`XxxUpdateReqVO`
- Response VO: `XxxRespVO`
- App VO: `AppXxxReqVO`、`AppXxxRespVO`
### 字段注解
- 使用 `@Schema` 定义字段说明和示例
- 使用 `@NotNull`、`@NotEmpty`、`@NotBlank` 等校验注解
- 使用 `requiredMode = Schema.RequiredMode.REQUIRED` 标记必填字段
### 对象转换
- Controller 层使用 `BeanUtils.toBean()` 进行 DO 到 VO 的转换
- Service 层使用 `BeanUtils.toBean()` 进行 VO 到 DO 的转换
- 复杂转换使用 MapStruct 或手动转换
### 代码示例
```java
@Schema(description = "管理后台 - 用户提示词创建 Request VO")
@Data
public class UserPromptSaveReqVO {
@Schema(description = "提示词名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "Java 开发助手")
@NotBlank(message = "提示词名称不能为空")
private String name;
@Schema(description = "提示词内容", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "提示词内容不能为空")
private String content;
}
```
## DO 对象规范
### 继承规范
- 普通 DO 继承 `BaseDO`,包含 `id`、`createTime`、`updateTime`、`creator`、`updater`、`deleted`
- 需要多租户的 DO 继承 `TenantBaseDO`,额外包含 `tenantId`
- 使用 `@TableName` 指定表名
### 字段规范
- 使用 `@TableId(type = IdType.AUTO)` 指定主键策略
- 使用 `@TableLogic` 标记逻辑删除字段
- 字段名使用驼峰命名,对应数据库下划线命名
### 代码示例
```java
@TableName("ai_user_prompt")
@Data
@EqualsAndHashCode(callSuper = true)
public class UserPromptDO extends TenantBaseDO {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private String content;
private String category;
}
```
## 异常处理规范
### 异常定义
- 业务异常使用 `ServiceException`,通过 `ServiceExceptionUtil.exception()` 创建
- 异常码定义在 `ErrorCodeConstants` 中
- 使用全局异常处理器统一处理
### 异常码规范
- 格式:`MODULE_RESOURCE_ACTION_ERROR`
- 例如:`USER_PROMPT_NOT_EXISTS`、`USER_PROMPT_NAME_DUPLICATE`
### 代码示例
```java
// 定义异常码
public interface ErrorCodeConstants {
ErrorCode USER_PROMPT_NOT_EXISTS = new ErrorCode(1_010_000_001, "用户提示词不存在");
}
// 使用异常
if (userPrompt == null) {
throw exception(USER_PROMPT_NOT_EXISTS);
}
```
## 多租户规范
### DO 继承
- 需要多租户的数据表DO 继承 `TenantBaseDO`
- 框架自动注入 `tenantId`,无需手动设置
### 数据隔离
- Mapper 查询时,框架自动添加租户条件
- 跨租户操作需要特殊处理
### 代码示例
```java
// DO 继承 TenantBaseDO
public class UserPromptDO extends TenantBaseDO {
// tenantId 自动注入,无需手动定义
}
// Service 中无需关心租户,框架自动处理
public UserPromptDO getUserPrompt(Long id) {
return userPromptMapper.selectById(id); // 自动添加租户条件
}
```
## 权限控制规范
### 权限标识
- 格式:`模块:资源:操作`
- 例如:`ai:user-prompt:create`、`ai:user-prompt:query`、`ai:user-prompt:update`、`ai:user-prompt:delete`
### 权限注解
- 使用 `@PreAuthorize("@ss.hasPermission('module:resource:action')")`
- 查询操作使用 `query`,创建使用 `create`,更新使用 `update`,删除使用 `delete`
## API 路径规范
### 路径前缀
- 管理后台:`/admin-api`
- 用户端:`/api`
- Controller 路径:`/模块/资源`,如 `/ai/user-prompt`
### HTTP 方法
- GET: 查询操作
- POST: 创建操作
- PUT: 更新操作
- DELETE: 删除操作
### 接口路径
- 创建:`POST /模块/资源/create`
- 更新:`PUT /模块/资源/update`
- 删除:`DELETE /模块/资源/delete`
- 查询单个:`GET /模块/资源/get?id=xxx`
- 分页查询:`GET /模块/资源/page`
- 导出:`GET /模块/资源/export-excel`
## 代码质量规范
### 命名规范
- 类名使用大驼峰PascalCase
- 方法名和变量名使用小驼峰camelCase
- 常量使用大写下划线UPPER_SNAKE_CASE
- 包名全小写,使用点分隔
### 注释规范
- 类和方法必须有 JavaDoc 注释
- 复杂业务逻辑添加行内注释
- 使用 `@author` 标记作者
### 代码格式
- 使用 4 个空格缩进
- 每行代码不超过 120 个字符
- 方法参数过多时换行对齐
- 使用 IDE 格式化快捷键统一格式
### 导入规范
- 使用静态导入简化代码:`import static ...`
- 避免使用 `.*` 通配符导入
- 导入顺序Java 标准库 → 第三方库 → 项目内部
## 性能优化规范
### 数据库查询
- 避免 N+1 查询问题,使用批量查询
- 合理使用索引,避免全表扫描
- 分页查询必须限制每页数量
### 缓存使用
- 热点数据使用 Redis 缓存
- 缓存 key 使用统一前缀:`模块:资源:id`
- 注意缓存更新和失效策略
### 事务优化
- 查询方法不使用事务
- 事务范围尽可能小
- 避免在事务中进行远程调用
## 安全规范
### 参数校验
- 所有用户输入必须校验
- 使用 `@Valid` 和 JSR-303 注解
- 敏感操作进行二次校验
### SQL 注入防护
- 使用 MyBatis Plus 的参数化查询
- 禁止拼接 SQL 语句
- 使用 `LambdaQueryWrapperX` 构建查询条件
### 权限校验
- 所有接口必须进行权限校验
- 数据操作前校验数据归属
- 敏感操作记录操作日志
## 测试规范
### 单元测试
- Service 层方法编写单元测试
- 使用 Mockito 模拟依赖
- 测试覆盖率不低于 70%
### 集成测试
- 关键业务流程编写集成测试
- 使用 `@SpringBootTest` 进行集成测试
- 测试数据使用独立的测试数据库
## 日志规范
### 日志级别
- ERROR: 系统错误,需要立即处理
- WARN: 警告信息,需要关注
- INFO: 关键业务流程日志
- DEBUG: 调试信息,生产环境关闭
### 日志格式
- 使用 SLF4J + Logback
- 日志包含:时间、级别、线程、类名、消息
- 关键操作记录操作日志(使用 `@ApiAccessLog`
## 配置管理
### 配置文件
- 使用 `application.yaml` 作为主配置
- 使用 `application-{profile}.yaml` 作为环境配置
- 敏感信息使用环境变量或配置中心
### 配置类
- 使用 `@ConfigurationProperties` 绑定配置
- 配置类使用 `@Validated` 进行校验
- 提供默认值和说明文档

116
.cursor/rules/project.mdc Normal file
View File

@@ -0,0 +1,116 @@
<!-- OPENSPEC:START -->
# OpenSpec Instructions
These instructions are for AI assistants working in this project.
Always open `@/openspec/AGENTS.md` when the request:
- Mentions planning or proposals (words like proposal, spec, change, plan)
- Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
- Sounds ambiguous and you need the authoritative spec before coding
Use `@/openspec/AGENTS.md` to learn:
- How to create and apply change proposals
- Spec format and conventions
- Project structure and guidelines
Keep this managed block so 'openspec update' can refresh the instructions.
<!-- OPENSPEC:END -->
## 项目简介
**Yudao芋道** - Spring Boot快速开发平台AI/媒体功能增强版
### 核心技术栈
- **后端**: Java 17 + Spring Boot 3.5.5 + MyBatis Plus + Redis
- **前端**: Vue.js 3 + TypeScript + Ant Design Vue + TailwindCSS
- **数据库**: MySQL 8.0+,支持多种数据库
- **AI服务**: 语音克隆、图像生成、音乐生成、向量搜索
## 代码规范要点
### Vue.js 最佳实践
- 优先使用组合式API`<script setup>`
- 状态管理使用Pinia保持仓库模块化
- TypeScript类型定义规范
- 组件保持小巧专注,逻辑清晰
### Java开发规范
- 分层架构Controller → Service → Mapper → VO/DO
- Mapper继承 `BaseMapperX<T>`
- DO继承 `BaseDO` 或 `TenantBaseDO`
- API响应统一使用 `CommonResult<T>`
- 权限注解:`@PreAuthorize("hasPermission(...)")`
## 项目结构
```
/d/projects/sionrui/
├── yudao-server/ # 主应用端口9900
├── yudao-module-tik/ # 媒体模块(语音克隆、视频)
├── yudao-module-ai/ # AI模块聊天、知识库
├── yudao-module-system/ # 系统管理
└── frontend/app/web-gold/ # Vue前端
```
## 模块标准结构
```
module/
├── controller/ # REST控制器
├── service/ # 业务逻辑(接口+实现)
├── mapper/ # 数据访问层
└── vo/ # 值对象SaveReq/PageReq/Resp
```
## 关键配置
- **后端配置**: `yudao-server/src/main/resources/application-local.yaml`
- **数据库**: `jdbc:mysql://8.155.172.147:3306/sion_rui_dev`
- **Redis**: `8.155.172.147:6379`
- **前端代理**: `/admin-api` 和 `/api` 代理到 `http://localhost:9900`
## API约定
- 管理API: `/admin-api/{module}/{resource}`
- 应用API: `/api/{module}/{resource}`
- CRUD端点: create/update/delete/get/page
## 常见易错点
### 1. 权限控制
❌ `Long userId = 1L`
✅ `SecurityFrameworkUtils.getLoginUserId()`
### 2. 分页查询
❌ 自定义pageNo/pageSize
✅ VO继承 `SortablePageParam` + `selectPage(reqVO, wrapper)`
### 3. Mapper查询
❌ `QueryWrapper` + 字符串字段
✅ `LambdaQueryWrapperX` + 方法引用
### 4. JSON字段处理
❌ `private List<String> urls`
✅ `private String urls` + `getUrlList()/setUrlList()` 转换方法
### 5. Bean转换
❌ `org.springframework.beans.BeanUtils`
✅ `framework.common.util.object.BeanUtils`
### 6. 多租户
- DO类必须继承 `TenantBaseDO`
- 框架自动注入 `tenantId`
## 开发命令
```bash
# 前端开发
cd frontend/app/web-gold
pnpm install
pnpm run dev # 启动开发服务器
# 后端开发
mvn clean install
mvn spring-boot:run
```
## 重要提醒
1. **OSS配额检查**: 文件上传前必须检查用户/系统配额
2. **多租户**: 默认启用DO类需继承 `TenantBaseDO`
3. **异常处理**: 使用 `ErrorCodeConstants` 中的错误码
4. **事务管理**: Service写操作使用 `@Transactional`

View File

@@ -1,92 +0,0 @@
---
description: 现代 Web 应用中的 Vue.js 最佳实践与模式
globs: **/*.vue, **/*.ts, components/**/*
---
# Vue.js 最佳实践
## 代码规划
- 代码简洁易于人类阅读
## 组件结构
- 优先使用组合式 API 而非选项式 API
- 保持组件小巧且功能专注
- 采用恰当的 TypeScript 集成方案
- 实现规范的 props 验证
- 使用标准的 emit 声明
- 保持模板逻辑简洁
- 优先使用template 语法,而不是函数组件
- 优先使用函数或者hook而不是类
## 组合式 API
- 正确使用 ref 与 reactive
- 合理实现生命周期钩子
- 通过组合式函数封装可复用逻辑
- 保持 setup 函数整洁
- 规范使用计算属性
- 合理实现侦听器
## 状态管理
- 使用 Pinia 进行状态管理
- 保持仓库模块化
- 采用合理的状态组织方式
- 规范实现操作逻辑
- 正确使用获取器
- 妥善处理异步状态
## 性能优化
- 实现组件懒加载
- 配置恰当的缓存策略
- 高效使用计算属性
- 避免不必要的侦听器
- 区分使用 v-show 与 v-if
- 实现科学的 key 管理
## 路由管理
- 规范使用 Vue Router
- 实现完整的导航守卫
- 合理配置路由元字段
- 正确处理路由参数
- 实现路由懒加载
- 使用标准的导航方法
## 表单处理
- 正确使用 v-model
- 实现完善的验证机制
- 规范处理表单提交
- 展示合理的加载状态
- 配置完整的错误处理
- 实现表单重置功能
## TypeScript 集成
- 使用规范的组件类型定义
- 实现完整的 props 类型声明
- 规范 emit 类型声明
- 处理类型推断
- 使用标准的组合函数类型
- 实现完整的仓库类型定义
## 测试策略
- 编写规范的单元测试
- 实现完整的组件测试
- 正确使用 Vue Test Utils
- 全面测试组合式函数
- 实现科学的模拟机制
- 测试异步操作流程
## 开发规范
- 遵循 Vue 样式指南
- 使用统一的命名约定
- 保持组件结构清晰
- 实现完整的错误处理
- 规范事件处理机制
- 为复杂逻辑添加文档注释
- 文件名使用mutiword 示例 'ExamplePage'
## 构建与工具链
- 使用 Vite 进行开发
- 配置完整的构建方案
- 规范使用环境变量
- 实现代码分割方案
- 正确处理静态资源
- 配置完整的优化策略