# 04-技术规范 ## 零、技术栈总览 | 分层模块 | 技术 | 版本要求 | 说明 | |---|---|---|---| | 前端基础框架 | React | 18.x | 构建前端应用 | | 前端 UI 组件 | Ant Design | 5.x | 页面组件与交互控件 | | 前端状态管理 | Redux Toolkit | 最新稳定版 | 管理全局状态 | | 前端路由管理 | React Router | v6 | 页面路由与导航 | | 前端工程化构建 | Vite | 最新稳定版 | 前端开发与打包构建 | | 前端接口通信 | Axios | 最新稳定版 | 调用后端 API | | 后端基础框架 | Spring Boot | 3.x | 构建后端服务 | | 后端数据访问 | MyBatis-Plus | 最新稳定版 | 数据库访问与 ORM 增强 | | 工作流引擎 | Activiti | 6.x | 审批流、流程流转 | | 缓存服务 | Redis | 最新稳定版 | 缓存、会话、分布式能力 | | 报表打印 | JXLS | 2.8.1 | 基于 Excel 模板生成报表 | | Excel 导入导出 | EasyExcel | 4.0.3 | Excel 数据导入导出 | | 关系型数据库 | MySQL | 8.x | 核心业务数据存储 | | 数据库 schema 迁移 | Flyway (`flyway-core` + `flyway-mysql`) | 10.x / 最新稳定版 | `sql/migrations/V_n__*.sql` 顺序 apply;Spring Boot 启动时自动应用 | | 接口风格 | RESTful API | 统一规范 | 前后端接口设计规范 | | 权限认证 | Spring Security / JWT | 最新稳定版 | 登录认证、权限控制 | | API 文档 | OpenAPI / Swagger | 最新稳定版 | 接口文档与调试 | | 项目构建管理 | Maven | 3.9.x | Java 项目依赖与构建 | | JDK 运行环境 | Java | 17 / 21 | Spring Boot 3 推荐版本 | | 部署容器 | Docker | 最新稳定版 | 容器化部署 | | Web 服务器 / 反向代理 | Nginx | 最新稳定版 | 前端托管、反向代理、负载分发 | | 日志管理 | Logback | 默认集成 / 最新稳定版 | 应用日志输出 | | 对象映射工具 | MapStruct | 最新稳定版 | DTO / VO / Entity 转换 | | 工具类库 | Hutool / Apache Commons | 最新稳定版 | 常用工具方法支持 | > 本表由 scope-lock 锁定。后续所有规范基于此表推导。 ## 一、后端规范 ### 1.1 分层结构 | 层 | 职责 | |---|---| | controller | 解析 HTTP 入参 / 校验请求体格式 / 返回 `Result`;不写业务逻辑 | | service | 业务流程编排、事务边界、跨 Mapper 组合;接口 + impl 拆开 | | mapper | 数据访问,对应一张表;XML 写 SQL,禁止跨表 JOIN 之外的业务判断 | | entity | 与数据库表一一映射的 PO;不带业务方法 | | dto / vo | 入参(DTO) / 出参(VO)专用结构;通过 MapStruct 与 entity 转换 | | common | 跨模块基础设施(异常 / 响应 / 配置 / 工具 / 安全) | 调用方向严格自上而下,禁止反向依赖(Controller 不能被 Service import)。 ### 1.2 命名约定 - **包名**:根包`com.xly.test4`,全小写点分隔;模块代码小写作为子包(`USR` → `usr`)。 - **类名**:大驼峰,按职责加后缀:`UserController` / `UserService` / `UserServiceImpl` / `UserMapper` / `UserCreateDTO` / `UserVO`。 - **方法名 / 变量**:小驼峰;布尔以 `is` / `has` / `can` 开头。 - **常量**:`UPPER_SNAKE_CASE`,定义在 `common.constant.Constants`。 示例: ```java // 示例 1:Controller @RestController @RequestMapping("/api/usr/user") public class UserController { public Result createUser(@Valid @RequestBody UserCreateDTO dto) { ... } } // 示例 2:常量 public final class UserConstants { public static final int MAX_LOGIN_FAIL_TIMES = 5; } ``` ### 1.3 统一响应格式 所有 Controller 返回 `Result`,结构: ```json // 成功 { "code": "0", "msg": "ok", "data": { ... }, "traceId": "..." } // 失败 { "code": "USR-001", "msg": "用户名已存在", "data": null, "traceId": "..." } ``` 错误码段位: | 段位 | 含义 | |---|---| | `0` | 成功 | | `1xxx` | 通用框架错误(参数校验失败、权限不足、未登录) | | `-` | 业务错误,MOD 与模块代码一致(如 `USR-001`) | | `5xxx` | 系统内部错误(DB 异常、第三方调用失败) | ### 1.4 异常处理 - 使用 `@RestControllerAdvice` 全局异常处理器,统一捕获并转 `Result.fail(...)`。 - 业务异常用自定义 `BusinessException(code, msg)` 抛出,不要 catch 后吞掉。 - 参数校验异常(`MethodArgumentNotValidException`)→ `1001` + 首个字段错误信息。 - 未预期异常 → `5000` + 通用文案"系统繁忙,请稍后重试";**接口响应禁止回显堆栈**,堆栈只进 Logback。 - traceId 在 Filter 层注入 MDC,错误响应中回填便于排查。 ### 1.5 事务 - `@Transactional` 仅打在 Service 实现类方法上,默认 `rollbackFor = Exception.class`。 - Controller 层禁止打事务注解。 - 一个 Service 方法只能跨当前模块的 Mapper;调用另一模块必须走对方 Service 的公共方法。 - 跨服务(跨进程)调用 **禁止**包在事务里;如有最终一致性需求走异步 + 补偿。 ### 1.6 认证 - 使用 Spring Security + JWT;登录接口签发 `accessToken`(24h)+ `refreshToken`(7 天)。 - token 放 Authorization header,格式 `Bearer `。 - 密钥从 `.env.local` → `JWT_SECRET` 注入到 `application.yml`,**代码里禁止硬编码**。 - 刷新机制:accessToken 过期前 30 分钟前端用 refreshToken 换新;refreshToken 一次性使用,签发新 access 时同时滚动新 refresh。 ## 二、前端规范 ### 2.1 目录约定 | 目录 | 职责 | |---|---| | `api/` | 后端接口封装;每模块一文件;导出函数对应 REQ 接口 | | `components/` | 跨页面通用组件;无业务耦合 | | `pages/` | 业务页面;按模块代码分子目录 | | `store/` | Redux Toolkit slice;按模块拆分 | | `hooks/` | 自定义 hooks | | `utils/` | 纯函数工具(日期、金额、字符串等) | | `styles/` | 全局样式 + Design Tokens | **前端禁止直接写 SQL / 操作 DB / 直连数据库连接**;所有数据访问走 `api/` 层 axios 封装。 ### 2.2 状态管理 - **服务端数据**:默认不存 Redux;通过 `useQuery` 风格 hook 或就近 `useState + useEffect` 拉取;如确实需跨页面共享(如当前用户信息),存 `store/` 对应 slice。 - **全局状态**:登录态、当前用户、权限列表、菜单 → Redux。 - **页面级状态**:表单字段、过滤条件、分页 → `useState` 或 `useReducer`,不进 Redux。 ### 2.3 请求封装 - 单例 `axios` 实例,`baseURL` 由环境变量注入。 - 请求拦截器:从 Redux 取 accessToken 注入 Authorization header。 - 响应拦截器: - `code === '0'` → resolve `data` - 401 → 自动调 refresh 接口尝试续期;失败则清空登录态跳 `/login` - 其他失败 → reject `Result`,由调用方决定弹窗 - 默认超时 15s;GET 类请求允许业务侧覆盖至 60s(如导出大数据量列表)。 - 重试:默认不重试;幂等查询接口(GET)业务侧可显式配置 1 次重试。 ### 2.4 错误处理 - **网络错误**(无 response):响应拦截器统一 `notification.error`「网络异常,请检查连接」。 - **业务错误**(`code !== '0'`):reject 给调用方;调用方根据场景决定 `message.error`(inline)或 `notification.error`(异步任务)。 - **页面级错误**(路由懒加载失败 / 组件渲染异常):用 React `ErrorBoundary` 兜底,展示 `Result` 错误页 + "重试"按钮。 ### 2.5 样式与主题 - CSS 变量命名格式:`--color---` - ``:`form` / `table-row` / `button` / 其他组件域名 - ``:`bg` / `fg` / `border` - ``:`edit` / `readonly` / `hover` / `selected` / `disabled` - 文件位置:`src/styles/tokens.css`,由 skeleton-gen 生成空骨架,色值由 docs/06 § 二锁定后填入。 - 组件样式中只允许 `var(--color-xxx)`,**禁止硬编码 hex / rgba**。 - 与 Ant Design 5 对接:在 App 根层用 `ConfigProvider`,将 token 值绑定到 `theme.token.colorPrimary` 等。 - 具体 token 表见 docs/06 § 二。 ## 三、共同约定 ### 3.1 Git 提交 `(): REQ-XXX-NNN` 具体规则见 `CLAUDE.md § 🗂️ Git 提交规范`。 ### 3.2 分页查询 - **后端入参**:`PageQuery { pageNum: int=1, pageSize: int=20, ... }`,pageSize 上限 100。 - **后端出参**:`PageResult { records: List, total: long, pageNum: int, pageSize: int }`。 - **前端**:Ant Design `Table` + `pagination` 双向绑定 `pageNum` / `pageSize`;切换时清空选中行。 - 排序与过滤条件并入 PageQuery 子类(如 `UserPageQuery`),避免接口爆炸。 ### 3.3 日期与金额 - **后端类型**:日期一律 `LocalDateTime`(含时分秒)或 `LocalDate`(仅日期);JSON 序列化用 ISO-8601 字符串(`yyyy-MM-dd'T'HH:mm:ss`)。 - **金额类型**:`BigDecimal`,标度(scale)= 2(保留 2 位小数),所有运算用 `BigDecimal.divide(..., RoundingMode.HALF_UP)` 避免 `double` 精度丢失。 - **前端展示**: - 日期用 `dayjs` 统一格式化,列表 `YYYY-MM-DD HH:mm`,详情 `YYYY-MM-DD HH:mm:ss`。 - 金额展示用千分位 + 2 位小数;展示前必须 `Number.toFixed(2)`。 ### 3.4 数据访问规约 - **SELECT 字段必须显式列举**,禁止 `SELECT *`;新增字段时同步更新 Mapper XML 与 entity。 - **禁止循环中执行 DB 查询**(N+1 反模式);改用: - 批量查询:`Mapper.selectBatchIds(ids)` - IN 子句:`Mapper.selectByIds(ids)` 一次拉取 - JOIN:在 XML 内 JOIN 子表 - Mapper XML 内字段与表名建议用 `` 复用片段或常量;禁止字符串拼接 SQL 片段。 - MyBatis-Plus 的 `LambdaQueryWrapper` 优先于硬编码字符串列名。 ### 3.5 配置与安全 - **配置外置**:DB 连接 / 端口 / 密钥 / 第三方 URL 等一律放 `application.yml` + `.env.local`; - `application.yml` 写占位 `${JWT_SECRET}` - 真实值放 `.env.local`(不入 git) - 代码里**禁止硬编码**任何凭据。 - **前端安全**: - `localStorage` 不存敏感信息(token / 身份 / 个人数据)。 - 推荐 HttpOnly Cookie 存 refreshToken;accessToken 放内存(Redux)+ 刷新机制兜底。 - 接口响应**禁止回显后端异常堆栈**(与 § 1.4 一致),错误码 + 文案足够。