You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
RuoYi-Vue/docs/architecture/optimization-suggestions.md

501 lines
29 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# RuoYi-Vue 优化建议清单
> 文档版本v1.0 | 生成日期2026-06-28
> 数据来源:前端架构分析、后端架构分析、前后端交互规范、数据库结构分析
> 问题总数36 条(前端 8 条、后端 8 条、交互 10 条、数据库 10 条)
---
## P0 - 高优先级(立即实施)
> 影响安全、稳定性、核心功能,建议在 1-2 周内完成。
### 1. fastjson 版本存在已知安全漏洞
- **问题描述**: 项目使用 fastjson 1.2.79,该版本存在多个已知 CVE 漏洞(如 CVE-2022-25845攻击者可利用反序列化漏洞执行远程代码。
- **影响范围**: 全系统所有使用 JSON 序列化/反序列化的接口包括登录、CRUD 操作、文件上传等。
- **推荐方案**: 升级至 fastjson22.x 系列)或替换为 Jackson/Gson。fastjson2 API 兼容性好,迁移成本较低。
- **实施优先级**: P0
- **实施步骤**:
1. 在根 `pom.xml` 中将 fastjson 版本改为 fastjson2 依赖
2. 全局搜索 `com.alibaba.fastjson` 导入,替换为 `com.alibaba.fastjson2`
3. 重点检查 `AjaxResult`、`TokenService`、`LogAspect` 中的 JSON 操作
4. 运行全量回归测试,确保序列化行为一致
5. 安全扫描验证漏洞已修复
### 2. 业务表主键使用 double 类型
- **问题描述**: 所有业务表stocks、account、operations、statistics 等)的主键使用 `double` 类型,浮点数作为主键可能导致精度丢失、索引效率低下、比较运算异常。
- **影响范围**: 股票业务表8 万+ 记录)、账户记账表等所有业务模块的数据查询和关联操作。
- **推荐方案**: 将所有业务表主键改为 `bigint(20) NOT NULL AUTO_INCREMENT`
- **实施优先级**: P0
- **实施步骤**:
1. 备份 `nstocks``ry` 数据库中涉及的业务表
2. 按依赖顺序执行 `ALTER TABLE` 语句修改主键类型(先子表后父表)
3. 更新对应的 Domain 实体类,将 `id` 字段类型从 `Double` 改为 `Long`
4. 更新 Mapper XML 中的主键引用
5. 验证数据完整性,运行全量测试
### 3. trade_dates 表无主键
- **问题描述**: `trade_dates` 表(交易日历)没有任何主键或唯一索引,无法保证数据唯一性,数据库复制和备份可能出错。
- **影响范围**: 所有依赖交易日历的业务查询,包括股票行情、涨跌停板等模块。
- **推荐方案**: 将日期字段设为主键。
- **实施优先级**: P0
- **实施步骤**:
1. 检查 `trade_dates` 表结构,确认日期字段名称
2. 清理可能存在的重复日期记录
3. 执行 `ALTER TABLE trade_dates ADD PRIMARY KEY (date);`
4. 验证查询功能正常
### 4. 核心业务表缺少必要索引
- **问题描述**: `stocks`8 万+ 记录)、`stock_index`、`stock_financial`、`operations` 等大表仅有主键索引高频查询字段code、trade_day、user_id完全无索引导致全表扫描。
- **影响范围**: 所有股票行情查询、操作记录查询、持仓统计查询,数据量增长后性能急剧下降。
- **推荐方案**: 为高频查询字段添加复合索引和单列索引。
- **实施优先级**: P0
- **实施步骤**:
1. 分析慢查询日志,确认高频查询模式
2.`stocks` 表添加 `idx_code_trade(code, trade_day)``idx_trade_day(trade_day)`
3.`stock_index` 表添加 `idx_code_trade(code, trade_day)`
4.`operations` 表添加 `idx_code_trade(code, trade_day)``idx_user_id(user_id)`
5.`statistics_remain` 表添加 `idx_code_trade(code, trade_day)``idx_user_id(user_id)`
6. 使用 `EXPLAIN` 验证索引生效
### 5. 排序字段存在 SQL 注入风险
- **问题描述**: 分页排序参数直接从请求参数读取并拼接到 SQL ORDER BY 子句中,虽使用 `SqlUtil.escapeOrderBySql()` 正则过滤,但正则表达式级别的防护存在被绕过的可能。
- **影响范围**: 所有使用分页排序的列表接口(约 50+ 个),攻击者可能通过精心构造的排序参数执行 SQL 注入。
- **推荐方案**: 使用白名单机制替代正则过滤,仅允许传入已知的合法字段名。
- **实施优先级**: P0
- **实施步骤**:
1.`TableSupport``SqlUtil` 中实现排序字段白名单校验
2. 为每个实体定义允许排序的字段列表
3.`startPage()` 方法中增加白名单校验逻辑
4. 非法排序参数直接拒绝并记录安全日志
5. 使用 SQL 注入扫描工具验证修复效果
### 6. 响应格式不统一
- **问题描述**: `AjaxResult`(普通 CRUD 接口)使用 `data` 字段返回数据,而 `TableDataInfo`(分页列表接口)使用 `rows` + `total` 字段,前端需要分别处理两种完全不同的响应结构。
- **影响范围**: 前端所有 API 调用180+ 个接口涉及两种响应格式处理,增加认知负担和维护成本。
- **推荐方案**: 统一响应结构,推荐在 `TableDataInfo` 中也使用 `data` 字段包裹分页数据,或引入统一的 `ApiResponse<T>` 泛型响应体。
- **实施优先级**: P0
- **实施步骤**:
1. 定义统一响应基类 `ApiResponse<T>`,包含 `code`、`msg`、`data`
2. 分页响应改为 `data: { list: [], total: 0 }` 结构
3. 前端 `request.js` 响应拦截器统一处理单一结构
4. 逐步迁移现有接口(可先从新接口开始)
5. 更新前端所有列表页面的数据提取逻辑
### 7. ${params.dataScope} SQL 拼接注入风险
- **问题描述**: MyBatis XML 中使用 `${params.dataScope}` 直接拼接 SQL 片段,虽然 `DataScopeAspect` 在执行前会清空参数,但若切面执行顺序被改变或绕过,将直接导致 SQL 注入。
- **影响范围**: 所有使用 `@DataScope` 注解的 Service 方法,涉及用户、角色、部门等核心数据查询。
- **推荐方案**: 使用参数化方案替代直接 SQL 拼接,或在切面层进行严格的 SQL 片段校验。
- **实施优先级**: P0
- **实施步骤**:
1.`DataScopeAspect` 中增加 SQL 片段合法性校验(仅允许特定模式)
2. 考虑将数据权限过滤改为 MyBatis 插件方式,在 SQL 解析阶段注入
3. 为关键查询添加安全审计日志
4. 进行安全渗透测试验证
---
## P1 - 中优先级(近期实施)
> 影响开发效率、可维护性,建议在 1-2 个月内完成。
### 8. 使用已废弃的 WebSecurityConfigurerAdapter
- **问题描述**: Spring Security 5.7+ 已废弃 `WebSecurityConfigurerAdapter`,项目当前继承该类进行安全配置,未来升级 Spring Boot 时将无法兼容。
- **影响范围**: `SecurityConfig.java` 安全配置模块,影响所有认证和授权流程。
- **推荐方案**: 改用 `SecurityFilterChain` Bean 配置方式。
- **实施优先级**: P1
- **实施步骤**:
1. 移除 `WebSecurityConfigurerAdapter` 继承
2.`configure(HttpSecurity http)` 方法改为 `@Bean SecurityFilterChain` 方法
3.`configure(WebSecurity web)` 方法改为 `WebSecurityCustomizer` Bean
4. 使用 `Lambda DSL` 风格编写安全规则(`.authorizeHttpRequests()` 替代 `.authorizeRequests()`
5. 验证登录、权限校验、匿名访问等功能正常
### 9. Token 解析异常被静默吞没
- **问题描述**: `TokenService.getLoginUser()` 方法中(第 72-74 行catch 块为空JWT Token 解析异常被完全忽略,导致问题难以排查。
- **影响范围**: 认证模块,所有 Token 验证失败的场景(过期、篡改、格式错误等)均无日志记录。
- **推荐方案**: 至少记录 WARN 级别日志,包含异常信息和请求上下文。
- **实施优先级**: P1
- **实施步骤**:
1.`TokenService` 中注入 Logger
2. 在 catch 块中添加 `log.warn("Token 解析失败: {}", e.getMessage())`
3. 可选:记录请求 IP 和 User-Agent 便于安全审计
4. 验证日志输出正常
### 10. 缺少统一 DTO/VO 分层
- **问题描述**: Domain 实体直接暴露给 Controller 层(如 `SysUser` 同时用于数据库映射和接口响应),密码等敏感字段需额外处理,字段暴露风险高。
- **影响范围**: 全系统所有 Controller 接口,特别是用户管理、角色管理等敏感模块。
- **推荐方案**: 引入独立的 DTO数据传输对象和 VO视图对象使用 MapStruct 或手动转换器进行映射。
- **实施优先级**: P1
- **实施步骤**:
1.`ruoyi-common` 中创建 `dto/``vo/`
2. 为敏感实体SysUser、SysRole 等)创建对应的 DTO/VO
3. Controller 层使用 DTO 接收请求、VO 返回响应
4. 使用 `@JsonIgnore` 或字段排除确保敏感字段不暴露
5. 逐步迁移现有接口
### 11. Vue 2 + Vue CLI 技术栈老化
- **问题描述**: Vue 2 已于 2023 年底停止官方维护Vue Router 3、Vuex 3、Vue CLI 4 均为旧版本,存在安全风险且无法使用 Composition API、`<script setup>` 等现代特性。
- **影响范围**: 前端全量代码40+ 页面、22 个组件组),长期维护成本高,第三方库兼容性逐步下降。
- **推荐方案**: 规划升级至 Vue 3 + Vite + Pinia可采用渐进式迁移策略。
- **实施优先级**: P1
- **实施步骤**:
1. 使用 `@vue/compat` 兼容性构建进行渐进式迁移
2. 先将构建工具从 Vue CLI 迁移至 Vite可独立进行
3. 将 Vuex 3 迁移至 PiniaAPI 相似,迁移成本低)
4. 逐个组件迁移至 Composition API
5. 最终移除 `@vue/compat`,完成纯 Vue 3 升级
### 12. 权限逻辑重复实现
- **问题描述**: 权限校验在 4 个位置分别实现(`plugins/auth.js`、`utils/permission.js`、`directive/permission/hasPermi.js`、`directive/permission/hasRole.js`),逻辑高度重复但存在细微差异,超级权限标识 `*:*:*` 散落在各处。
- **影响范围**: 前端所有权限校验场景,修改权限规则需同时修改多处,易遗漏导致权限漏洞。
- **推荐方案**: 抽取统一的权限校验核心模块,其他模块基于该核心实现。
- **实施优先级**: P1
- **实施步骤**:
1. 创建 `src/utils/permission-core.js` 作为唯一权限判断入口
2. 将超级权限标识、角色标识等常量集中管理
3. `plugins/auth.js`、`directive/permission/` 均调用核心模块
4. 编写单元测试覆盖所有权限判断场景
5. 移除重复代码
### 13. 状态持久化分散且不统一
- **问题描述**: Token 存 Cookie、sidebar 状态存 Cookie、布局设置存 localStorage手动读写无统一管理无持久化插件刷新后部分状态可能不一致。
- **影响范围**: 前端全局状态管理涉及登录态、UI 设置、侧边栏状态等。
- **推荐方案**: 引入 `vuex-persistedstate` 或自定义统一持久化层。
- **实施优先级**: P1
- **实施步骤**:
1. 安装 `vuex-persistedstate``js-cookie`
2. 在 Vuex Store 中配置统一持久化策略
3. 按模块配置不同的存储介质Token → CookieUI → localStorage
4. 移除手动读写 Cookie/LocalStorage 的散点代码
5. 验证刷新后状态恢复正常
### 14. 前后端 API 路径不一致
- **问题描述**: 部分接口前端调用路径与后端映射不一致(如 `/querylist` vs `/list``StocksController` 中存在被注释的权限控制(`@PreAuthorize` 被注释),存在安全漏洞风险。
- **影响范围**: 股票系统模块为主,涉及约 63 个接口。
- **推荐方案**: 清理未使用的接口,补全权限控制,统一前后端路径命名规范。
- **实施优先级**: P1
- **实施步骤**:
1. 逐个比对前端 API 文件与后端 Controller 路径映射
2. 恢复被注释的 `@PreAuthorize` 注解
3. 清理前端未使用的 API 调用
4. 建立前后端路径一致性检查机制(可写脚本自动化)
5. 制定 API 命名规范文档
### 15. 分页参数隐式依赖
- **问题描述**: 分页参数通过 `ServletUtils.getParameter()` 从 HttpServletRequest 中隐式读取,而非通过 `@RequestParam` 显式声明,导致 API 文档Swagger无法自动生成分页参数说明。
- **影响范围**: 所有使用 `BaseController.startPage()` 的分页接口(约 50+ 个)。
- **推荐方案**: 使用 `@RequestParam` 显式声明分页参数,或引入 `PageRequest` 对象作为 Controller 方法参数。
- **实施优先级**: P1
- **实施步骤**:
1. 创建 `PageRequest` 对象(包含 pageNum、pageSize、orderByColumn、isAsc
2. 修改 `BaseController.startPage()` 支持显式参数
3. 为 Controller 分页接口添加 `@RequestParam``PageRequest` 参数
4. 补充 Swagger 注解生成分页参数文档
5. 验证分页功能正常
### 16. 接口文档缺失
- **问题描述**: 项目虽引入 Swagger 依赖,但所有业务 Controller 均未添加 Swagger 注解(`@Api`、`@ApiOperation`、`@ApiParam`),无法自动生成 API 文档,前后端协作效率低。
- **影响范围**: 全部 180+ 个 API 端点,影响前后端协作、测试、接口维护。
- **推荐方案**: 补充 Swagger/OpenAPI 注解,或接入 SpringDoc + Knife4j 增强文档体验。
- **实施优先级**: P1
- **实施步骤**:
1. 升级 Swagger 至 SpringDocOpenAPI 3.0
2. 接入 Knife4j 增强 UI
3. 为每个 Controller 添加 `@Tag`/`@Operation` 注解
4. 为关键参数添加 `@Parameter`/`@Schema` 注解
5. 配置文档访问路径和权限控制
### 17. 无逻辑外键导致数据一致性风险
- **问题描述**: 系统管理表和业务表之间没有物理外键约束,全部采用逻辑关联,删除用户/角色时关联表sys_user_role、sys_role_menu 等)数据可能残留。
- **影响范围**: 用户管理、角色管理、菜单管理等核心模块,长期运行后可能产生脏数据。
- **推荐方案**: 在 Service 层确保级联删除逻辑完整,或引入数据库层面的逻辑外键校验。
- **实施优先级**: P1
- **实施步骤**:
1. 审查所有删除操作(用户、角色、部门、菜单)的级联清理逻辑
2. 补充缺失的关联表清理代码
3. 在事务中确保原子性
4. 添加定期数据一致性校验脚本
5. 可选:在数据库层面添加外键约束(需评估性能影响)
### 18. find_in_set 查询无法利用索引
- **问题描述**: 部门树查询使用 `find_in_set(#{deptId}, ancestors)` 进行字符串匹配,无法使用任何索引,数据量增长后性能线性下降。
- **影响范围**: 所有涉及部门层级查询的场景(用户列表按部门过滤、数据权限范围计算等)。
- **推荐方案**: 使用闭包表Closure Table或物化路径的整数数组类型替代字符串匹配。
- **实施优先级**: P1
- **实施步骤**:
1. 评估闭包表方案:新增 `sys_dept_closure` 表存储祖先后代关系
2. 或使用 MySQL 8.0+ 的 JSON 数组 + JSON 函数替代 `find_in_set`
3. 更新 `DataScopeAspect` 中的 SQL 生成逻辑
4. 在部门增删改时同步维护闭包表/路径
5. 使用 `EXPLAIN` 验证查询使用索引
---
## P2 - 低优先级(长期规划)
> 优化类建议,可在 3-6 个月内逐步实施。
### 19. 业务 Controller 缺少 @Log 注解
- **问题描述**: `book-system` 下的 Controller`AccountController`)部分接口缺少 `@Log` 操作日志注解,审计不完整。
- **影响范围**: 账务系统模块的操作审计,安全合规场景下无法追溯操作记录。
- **推荐方案**: 为所有业务 Controller 的增删改接口补充 `@Log` 注解。
- **实施优先级**: P2
- **实施步骤**:
1. 梳理 `book-system``stock-system` 下所有 Controller
2. 为每个增删改方法添加 `@Log(title = "模块名", businessType = BusinessType.XXX)`
3. 验证操作日志正常写入
4. 建立代码审查规则,新接口必须包含 `@Log`
### 20. Service 层直接注入 Mapper 实现类
- **问题描述**: `SysUserServiceImpl` 中使用 `@Autowired private SysUserMapper userMapper` 直接注入实现类,不符合面向接口编程原则。
- **影响范围**: 全系统所有 Service 实现类,影响代码规范和可测试性。
- **推荐方案**: 改为注入 Mapper 接口类型。
- **实施优先级**: P2
- **实施步骤**:
1. 全局搜索 `@Autowired` 注入 Mapper 的代码
2. 将注入类型从实现类改为接口MyBatis 代理本身实现接口)
3. 使用 `@Resource` 或构造函数注入替代字段注入(可选)
### 21. 缺少接口版本控制
- **问题描述**: 所有 API 路径无版本号(如 `/api/v1/system/user`),未来接口升级时无法平滑过渡,可能导致前端兼容问题。
- **影响范围**: 全系统 API 设计,影响未来接口迭代和客户端兼容。
- **推荐方案**: 引入 URL 路径版本控制(`/api/v1/`)或 Header 版本控制。
- **实施优先级**: P2
- **实施步骤**:
1. 制定 API 版本管理策略(推荐 URL 路径方式)
2. 为所有现有接口添加 `/api/v1/` 前缀
3. 前端 `request.js``baseURL` 中添加版本前缀
4. 建立接口版本废弃机制
5. 文档中注明版本策略
### 22. 生产/开发环境使用不同的懒加载方式
- **问题描述**: 开发环境使用 `require()` 加载组件,生产环境使用 `import()`,两份逻辑增加维护复杂度,且开发环境无法享受代码分割优化。
- **影响范围**: 前端路由懒加载模块,影响开发构建产物大小和热更新速度。
- **推荐方案**: 统一开发/生产环境的组件加载方式,均使用动态 `import()`
- **实施优先级**: P2
- **实施步骤**:
1. 移除 `process.env.NODE_ENV` 条件分支
2. 统一使用 `() => import('@/views/${view}')` 方式
3. 验证开发环境热更新正常
4. 对比构建产物大小变化
### 23. 响应拦截器 401 处理使用 location.href 硬跳转
- **问题描述**: 401 未授权时使用 `location.href = '/index'` 硬跳转,绕过 Vue Router 导航守卫和状态清理流程,可能导致 Vuex 状态未完全清理、标签页数据残留。
- **影响范围**: 用户登录态过期后的退出流程,影响状态清理完整性。
- **推荐方案**: 改用 `router.replace()` 跳转,确保走完整的导航守卫流程。
- **实施优先级**: P2
- **实施步骤**:
1.`request.js` 中导入 router 实例
2.`location.href = '/index'` 改为 `router.replace('/login')`
3. 确保 `LogOut` action 在跳转前被正确调用
4. 验证状态清理完整Token、tagsView、缓存等
### 24. 缺少统一请求重试机制
- **问题描述**: 网络波动或后端短暂不可用时,所有请求直接失败,无自动重试策略,用户体验下降。
- **影响范围**: 所有 API 请求,特别是网络不稳定场景。
- **推荐方案**: 在 `request.js` 中添加可配置的重试机制(如 `axios-retry`)。
- **实施优先级**: P2
- **实施步骤**:
1. 安装 `axios-retry` 或自行实现重试拦截器
2. 配置重试条件(仅网络错误和超时,不重试 4xx/5xx
3. 设置重试次数(建议 2-3 次)和退避策略
4. 为特定请求提供 `maxRetries` 配置覆盖
5. 验证重试行为符合预期
### 25. GET 请求参数转换方式不标准
- **问题描述**: 前端 GET 请求的 `params` 通过 `tansParams` 函数手动拼接为 URL 字符串,而非使用 axios 原生的 `paramsSerializer`,可能导致特殊字符编码问题。
- **影响范围**: 所有 GET 请求,涉及中文、特殊字符的查询参数。
- **推荐方案**: 使用 axios 的 `paramsSerializer` 配置进行参数序列化。
- **实施优先级**: P2
- **实施步骤**:
1. 在 axios 实例配置中添加 `paramsSerializer`
2. 使用 `qs.stringify()``URLSearchParams` 替代手动拼接
3. 移除请求拦截器中的 `tansParams` 逻辑
4. 验证中文、特殊字符参数正常传递
### 26. 批量删除路径参数格式不一致
- **问题描述**: 部分 Controller 使用 `@DeleteMapping("/{ids}")` 接收 `Long[]`URL 中数组传递格式(逗号分隔 vs 多次参数)缺乏统一规范,前端需手动拼接字符串。
- **影响范围**: 所有支持批量删除的接口,前端需要适配不同格式。
- **推荐方案**: 统一使用 `@DeleteMapping` + `@RequestParam List<Long> ids``@RequestBody` 传递数组。
- **实施优先级**: P2
- **实施步骤**:
1. 统一所有批量删除接口为 `DELETE /{module}/{ids}``DELETE /{module}` + RequestBody
2. 前端封装统一的 `delByIds(url, ids)` 方法
3. 更新所有页面的批量删除调用
4. 补充接口文档说明
### 27. 大量调试代码未清理
- **问题描述**: `StocksController` 中存在大量 `System.out.println()` 调试输出(超过 50 处以及大段被注释的代码1000+ 行),污染日志且增加维护成本。
- **影响范围**: `stock-system` 模块,影响生产环境日志质量和代码可读性。
- **推荐方案**: 统一替换为 `logger.info/debug`,清理历史注释代码。
- **实施优先级**: P2
- **实施步骤**:
1.`StocksController` 中创建 Logger 实例
2.`System.out.println()` 替换为 `log.debug()` 或删除
3. 清理大段注释代码1000+ 行)
4. 同样检查 `stock-system` 下其他 Controller
5. 建立代码审查规则,禁止 `System.out.println`
### 28. 缺少审计字段
- **问题描述**: 大部分业务表stocks、operations、statistics 等)缺少 `create_by`、`create_time`、`update_by`、`update_time` 审计字段,无法追溯数据变更历史。
- **影响范围**: 所有业务表的数据审计和问题排查。
- **推荐方案**: 为业务表添加标准审计字段,继承 `BaseEntity`
- **实施优先级**: P2
- **实施步骤**:
1. 为业务表 DDL 添加审计字段
2. 实体类继承 `BaseEntity` 或手动添加审计字段
3. 利用 MyBatis 拦截器或 AOP 自动填充审计字段
4. 历史数据补充默认值
### 29. 缺少软删除机制
- **问题描述**: 业务表stocks、operations 等)数据删除后直接物理删除,无法恢复,不符合审计要求。
- **影响范围**: 所有业务模块的数据管理,特别是财务和统计相关数据。
- **推荐方案**: 为业务表添加 `del_flag` 字段,实现软删除。
- **实施优先级**: P2
- **实施步骤**:
1. 为业务表添加 `del_flag char(1) default '0'` 字段
2. 实体类添加 `delFlag` 属性
3. Mapper XML 中所有查询添加 `del_flag = '0'` 条件
4. 删除操作改为更新 `del_flag = '2'`
5. 管理后台提供回收站/恢复功能(可选)
### 30. 大字段 TEXT/BLOB 无分离
- **问题描述**: `sys_notice.content`longblob、`operations.deal_logic`TEXT、`statistics.bz`TEXT等大文本字段与主表混合存储查询时即使不需要这些字段也会被加载影响性能。
- **影响范围**: 公告管理、操作记录、统计备注等模块的查询性能。
- **推荐方案**: 将大字段移至扩展表,主表仅保留轻量字段。
- **实施优先级**: P2
- **实施步骤**:
1. 为包含大字段的表创建 `_detail` 扩展表
2. 将 TEXT/BLOB 字段迁移至扩展表
3. 主表保留外键关联
4. 仅在需要详情时 JOIN 扩展表
5. 验证查询性能提升
### 31. HTTP 状态码与业务状态码混用
- **问题描述**: 后端 HTTP Response 的 Status Code 始终为 200真正的业务状态码在响应体 `code` 字段中,前端无法利用 HTTP 状态码进行路由/拦截逻辑,也与 RESTful 最佳实践不符。
- **影响范围**: 全局 API 设计,影响前端错误处理逻辑。
- **推荐方案**: 保持当前模式(业界常见做法)但在文档中明确说明;或逐步将 HTTP Status Code 与业务 code 对齐。
- **实施优先级**: P2
- **实施步骤**:
1. 在 API 文档中明确说明当前状态码策略
2. 评估 HTTP 状态码对齐的改造成本
3. 如选择对齐,修改 `GlobalExceptionHandler` 返回对应 HTTP 状态码
4. 前端响应拦截器适配新的状态码策略
### 32. 错误码体系不完整
- **问题描述**: 前端 `errorCode.js` 仅映射了 401/403/404 三个错误码400/409/415 等 HTTP 标准错误码未做前端映射,全部 fallback 到 `default` 或后端 `msg`。后端虽定义了 16 个状态码,但实际使用集中在 200 和 500。
- **影响范围**: 全局错误提示,用户体验不够精准。
- **推荐方案**: 完善前端错误码映射表,后端减少 500 的滥用。
- **实施优先级**: P2
- **实施步骤**:
1.`errorCode.js` 中补充 400/409/415/501 等错误码映射
2. 后端对参数错误返回 400业务冲突返回 409
3. 更新 `GlobalExceptionHandler` 返回更精确的状态码
4. 前端展示更友好的错误提示
### 33. 业务组件与通用组件混放
- **问题描述**: `Kdialog`、`TrendStocksDialog`、`NegativeDialog` 等强业务耦合组件放在 `src/components/` 通用组件目录,通过全局注册加载,增加首屏包体积。
- **影响范围**: 前端首屏加载性能,通用组件库纯净度。
- **推荐方案**: 将业务组件移至对应业务模块目录,或采用按需异步加载。
- **实施优先级**: P2
- **实施步骤**:
1. 将业务组件从 `src/components/` 移至对应业务模块(如 `src/views/stocksystem/components/`
2. 取消全局注册,改为局部注册或异步加载
3. 重新评估首屏包体积变化
4. 制定组件目录规范
### 34. 视图页面高度模板化
- **问题描述**: `system/`、`booksystem/`、`stocksystem/` 下的 CRUD 页面结构高度相似(搜索表单 + 表格 + 分页 + 弹窗),但未抽取为可配置的高阶组件或 Schema 驱动表单。
- **影响范围**: 前端开发效率,新增 CRUD 页面工作量大,修改通用逻辑需改多个文件。
- **推荐方案**: 抽取 CRUD 页面为 Schema 驱动的高阶组件或低代码配置方案。
- **实施优先级**: P2
- **实施步骤**:
1. 分析现有 CRUD 页面的共同模式
2. 设计 Schema 配置格式(字段定义、搜索条件、操作按钮)
3. 实现 `ProTable``ProForm` 高阶组件
4. 在新页面试点使用 Schema 驱动方式
5. 逐步迁移现有页面
### 35. 缺少接口版本控制
- **问题描述**: (与第 21 条重复,此处补充前端视角)前端 API 模块文件中没有版本管理概念,接口变更时需要手动修改 URL。
- **影响范围**: 前端 API 维护,接口升级时容易遗漏。
- **推荐方案**: 前端 API 基础路径集中管理,支持版本切换。
- **实施优先级**: P2
- **实施步骤**:
1.`.env` 文件中定义 `VUE_APP_API_VERSION=v1`
2. `request.js``baseURL` 中动态拼接版本前缀
3. 新接口版本在对应模块文件中并行维护
4. 旧版本接口标记废弃注释
### 36. 日期格式化查询导致索引失效
- **问题描述**: 时间范围查询使用 `date_format(u.create_time, '%y%m%d')` 包装列,导致即使 `create_time` 有索引也无法使用,必须全表扫描。
- **影响范围**: 用户列表、操作日志、登录日志等时间范围查询。
- **推荐方案**: 将函数包裹改为范围查询。
- **实施优先级**: P2
- **实施步骤**:
1.`date_format(u.create_time, '%y%m%d') >= ?` 改为 `u.create_time >= #{beginTime}`
2.`date_format(u.create_time, '%y%m%d') <= ?` 改为 `u.create_time < DATE_ADD(#{endTime}, INTERVAL 1 DAY)`
3. 更新 Mapper XML 中的时间查询条件
4. 前端传入完整的日期时间格式参数
5. 使用 `EXPLAIN` 验证索引生效
---
## 总结
| 优先级 | 数量 | 建议实施周期 | 涵盖领域 |
|--------|------|-------------|----------|
| **P0** | 7 | 1-2 周 | 安全漏洞、主键类型、索引缺失、SQL 注入、响应格式 |
| **P1** | 11 | 1-2 月 | 技术栈升级、安全配置、架构分层、API 规范、文档 |
| **P2** | 18 | 3-6 月 | 代码规范、审计追踪、性能优化、组件重构、开发体验 |
| **合计** | **36** | — | 前端 8、后端 8、交互 10、数据库 10 |
### 实施路线图建议
```
第 1-2 周P0 紧急修复)
├── 升级 fastjson → fastjson2
├── 修复业务表主键 double → bigint
├── trade_dates 添加主键
├── 核心表添加索引
├── 排序字段白名单改造
├── 统一响应格式设计
└── dataScope SQL 拼接加固
第 3-6 周P1 架构优化)
├── Spring Security 配置升级
├── Token 异常日志补充
├── DTO/VO 分层设计
├── Vue 3 迁移评估与 POC
├── 权限核心模块抽取
├── 状态持久化统一
├── API 路径一致性修复
├── 分页参数显式化
├── API 文档接入
├── 级联删除逻辑完善
└── 部门树查询优化
第 7-16 周P2 持续改进)
├── @Log 注解补充
├── Mapper 注入规范化
├── API 版本控制
├── 组件加载方式统一
├── 401 处理优化
├── 请求重试机制
├── 参数序列化标准化
├── 批量删除规范统一
├── 调试代码清理
├── 审计字段添加
├── 软删除机制
├── 大字段分离
├── HTTP 状态码策略
├── 错误码体系完善
├── 组件目录规范
└── CRUD Schema 驱动
```
---
*文档结束*