# 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 请求、参数校验(`@Valid`)、调用 Service、组装响应;不写业务逻辑 | | `service/` | 业务编排、事务边界、跨 Mapper 调用;接口 + `impl/` 实现 | | `mapper/` | MyBatis-Plus 数据访问(Java 接口 + XML),仅做单表 CRUD 与简单关联查询 | | `entity/` | 与数据库表 1:1 的实体类,字段名/类型严格对齐 docs/03 | | `dto/` | 入参对象(前端 → 后端),含 `@NotNull` / `@Pattern` 等校验注解 | | `vo/` | 出参对象(后端 → 前端),由 MapStruct 从 Entity 转换 | | `config/` | Spring 配置类(Security / Redis / MyBatis-Plus / Swagger / Activiti) | | `common/` | 全局响应包装、统一异常处理器、拦截器、工具类 | | `security/` | JWT 生成 / 验证、`UserDetailsService` 实现、权限注解 | ### 1.2 命名约定 - **包名**:全小写,单数。根包 `com.example.erp`。业务模块包 `.module.<模块代码小写>`(示例:`com.example.erp.module.usr`)。 - **类名**:大驼峰;按层级加后缀(`UserController` / `UserServiceImpl` / `UserMapper` / `UserCreateDTO` / `UserListVO`)。 - **方法名**:小驼峰;动词开头(`createUser` / `listUsers` / `disableUser`),与 REST 动作语义对齐。 - **常量**:全大写下划线(`MAX_LOGIN_FAILS = 5`),放对应业务模块的 `constant/` 子包或公共 `common/constant/`。 - **示例 1**:`com.example.erp.module.usr.controller.UserController#listUsers(UserQueryDTO)` 返回 `PageVO`。 - **示例 2**:`com.example.erp.module.usr.service.impl.UserServiceImpl#disableUser(Long id)` 写入 `t_user_audit_log` 审计。 ### 1.3 统一响应格式 后端所有 HTTP 接口返回 `Result` 包装: ```json // 成功 { "code": 0, "message": "ok", "data": { ... } } // 失败 { "code": 40001, "message": "用户名已存在", "data": null } ``` 错误码段位: | 段位 | 含义 | |---|---| | `0` | 成功 | | `1xxxx` | 系统级(参数校验、未授权、未登录) | | `2xxxx` | 通用业务错误(资源不存在、状态非法) | | `4xxxx` | 模块业务错误(按模块再分子段:USR=`40xxx`,PUR=`41xxx`...) | | `5xxxx` | 第三方 / 基础设施错误(DB / Redis / 外部服务) | ### 1.4 异常处理 - **全局异常处理器**:`@RestControllerAdvice` 统一捕获,转换为 `Result` 失败结构。 - **必须 catch**:`MethodArgumentNotValidException`(参数校验)/ `BindException` / 业务自定义 `BizException` / `AccessDeniedException`。 - **禁止 catch**:泛 `Exception` 在业务代码中吞掉;必须让全局处理器接管。 - **接口响应禁止回显后端异常堆栈**:返回用户友好错误码 + 文案;堆栈仅写入 logback。 ### 1.5 事务 - **事务边界**:放在 Service 层方法上(`@Transactional`),Controller / Mapper 禁止开事务。 - **传播策略**:默认 `REQUIRED`;只读查询用 `@Transactional(readOnly = true)`。 - **跨服务调用禁止开新事务嵌套**:跨进程 / 跨服务的一致性走「最终一致 + 补偿」或 Activiti 工作流,不要用分布式事务。 ### 1.6 认证 - **协议**:JWT(HS256),头 `Authorization: Bearer `。 - **生命周期**:access token 8 小时,refresh token 7 天;登录返回两枚 token;access 过期前端凭 refresh 刷新一次。 - **刷新机制**:refresh token 只能用于换 access,不能直接调业务接口;服务端可吊销(Redis 存吊销名单)。 - **密钥管理**:JWT 签名密钥放 `.env.local` 的 `JWT_SECRET`,至少 32 字节;生产环境必须更换默认值。 - **登录失败锁定**:连续 5 次失败锁账户 30 分钟,Redis 计数器 key `login:fail:`。 ## 二、前端规范 ### 2.1 目录约定 | 目录 | 职责 | |---|---| | `src/api/` | Axios 实例 + 每模块一个 API 文件;**所有 HTTP 调用唯一入口** | | `src/components/` | 跨页面通用组件(`AuthButton` / `AppTable` / `PageHeader`) | | `src/pages/` | 业务页面,按模块组织子目录 | | `src/store/` | Redux Toolkit slice,仅放真正的全局状态 | | `src/hooks/` | 自定义 hook(`useAuth` / `usePagination` / `useDebounce`) | | `src/utils/` | 纯函数工具(格式化、校验、正则) | | `src/styles/` | `tokens.css` + 全局样式 | | `src/router/` | 路由表 + 路由守卫 | > **前端禁止直接写 SQL / 操作 DB**,所有数据访问走 `api/` 层统一封装。 ### 2.2 状态管理 - **Redux 存什么**:全局共享 + 跨页面持久(当前用户信息、权限码列表、菜单树、字典)。 - **Redux 不存什么**:单个页面的表单值、Modal 开关、表格分页参数 → 放组件 `useState` / `useReducer`。 - **服务端数据**:业务数据(列表、明细)不要塞 Redux,每次进入页面走 `api/` 取最新;只有字典 / 全局枚举做内存缓存(`store/slices/dictSlice`)。 ### 2.3 请求封装 - **Axios 实例**:`src/api/http.ts` 统一创建,`baseURL` 取 `import.meta.env.VITE_API_BASE`。 - **请求拦截器**:自动注入 `Authorization: Bearer `;token 临期则先刷新再发起原请求。 - **响应拦截器**:剥 `Result.data` 给业务;`code !== 0` 时 `message.error(message)` 并 reject。 - **超时**:默认 15s;上传 / 导出接口单独 60s。 - **错误重试**:仅对幂等 GET 重试 1 次,POST / PUT / DELETE 禁止重试。 ### 2.4 错误处理 - **网络错误**:Axios `error.code === 'ERR_NETWORK'` → 全局 `message.error('网络异常,请检查连接')`。 - **业务错误**:`code !== 0` 在响应拦截器统一弹 message;页面只需处理 `try/catch` 中的 reject。 - **页面级错误**:路由级 `ErrorBoundary` 包顶层,组件 throw 时显示统一错误页(docs/06 § 1.2)。 ### 2.5 样式与主题 - **CSS 变量命名**:`--color---` - `scope` = `form` / `table-row` / `btn` / `link` / ... - `role` = `bg` / `fg` / `border` - `state` = `edit` / `readonly` / `hover` / `selected` - **文件位置**:`src/styles/tokens.css`,由 skeleton-gen 生成空骨架,色值由 docs/06 § 二锁定后填入。 - **组件样式**:只用 `var(--color-xxx)`,禁止硬编码 hex / rgba。 - **Ant Design 主题对接**:`` 把 tokens 注入 antd 主题。 具体 token 表见 docs/06 § 二。 ## 三、共同约定 ### 3.1 Git 提交 `(): REQ-XXX-NNN` - `type` ∈ `feat` / `fix` / `refactor` / `test` / `docs` / `chore` / `style` - `scope` 为模块代码小写(`usr` / `pur` / `sal`)或 `infra` - `subject` 50 字以内动词开头 - 末尾必须挂 `REQ-XXX-NNN`(如 `REQ-USR-001`),CI 用此挂关联 ### 3.2 分页查询 - **后端入参**:`PageQuery { pageNum: int = 1, pageSize: int = 20 }`(`pageSize` 上限 100)+ 业务过滤字段;继承基类避免重复声明。 - **后端出参**:`PageVO { records: List, total: long, pageNum: int, pageSize: int }`。 - **前端组件**:统一封装 `` 内置 antd `Table` + `Pagination`,受控 `current` / `pageSize` / `total`。 - **默认排序**:按创建时间倒序;可按列点击切换。 ### 3.3 日期与金额 - **后端类型**:日期 `LocalDate`,时间 `LocalDateTime`,金额 `BigDecimal`(scale=2,HALF_UP)。 - **序列化**:Jackson 全局配置 `LocalDateTime` ↔ `yyyy-MM-dd HH:mm:ss`;`BigDecimal` 序列化为字符串避免精度丢失。 - **前端展示**:`utils/format.ts` 提供 `formatDate(d)` / `formatMoney(n)`;金额展示固定 2 位小数 + 千分位(`¥1,234.56`)。 ### 3.4 数据访问规约 - **SELECT 字段显式列举**,禁止 `SELECT *`;Mapper XML 用 `` 集中维护。 - **禁止 N+1**:循环中不得执行 DB 查询;改用批量查(`IN (?,?,?)`)/ JOIN / ``。 - **表名 / 字段名**:Mapper XML 中通过 `` 片段或常量引用,禁止字符串拼接(防 SQL 注入 + 利于改名)。 - **分页**:统一用 MyBatis-Plus `Page` + `selectPage(...)`,禁止 LIMIT 字符串拼接。 ### 3.5 配置与安全 - **配置**:DB 连接 / 端口 / 密钥 / 第三方 URL 等一律放 `application.yml` + `.env.local`,代码里**禁止硬编码**;`application.yml` 用 `${VAR_NAME:default}` 引用环境变量。 - **前端安全**: - `localStorage` **不存敏感信息**(token / 身份 / 个人数据);推荐 HttpOnly Cookie 或 「内存 access token + HttpOnly refresh cookie」组合。 - 接口响应禁止回显后端异常堆栈(与 § 1.4 一致)。 - XSS:所有用户输入展示走 React JSX 自动转义;`dangerouslySetInnerHTML` 禁用,除非内容来源已白名单化。