# 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 分层结构 按 Spring Boot 3 + MyBatis-Plus 惯例分四层,每层职责单一: | 层 | 职责 | |---|---| | `controller` | HTTP 入口;参数校验(`@Valid`);调用 service;返回统一响应;**不写业务逻辑** | | `service` + `service/impl` | 业务编排;事务边界;调用一个或多个 mapper;DTO ↔ Entity 转换走 converter | | `mapper` + `resources/mapper/*.xml` | 单表 CRUD 走 MyBatis-Plus;复杂 SQL 写 XML;**不写业务逻辑** | | `entity` / `dto` / `vo` / `converter` | 数据传输层;converter 用 MapStruct 自动生成实现 | ### 1.2 命名约定 - **Java 包**:全小写。根包:`com.xly.erp`。业务模块:`module.`(与 docs/01 模块代码对齐)。 - **类名**:大驼峰;后缀清晰标识层(`UserController` / `UserServiceImpl` / `UserMapper` / `UserEntity` / `CreateUserReq` / `UserVo` / `UserConverter`)。 - **方法 / 字段**:小驼峰(`createUser` / `userName`)。 - **常量**:全大写下划线(`MAX_LOGIN_ATTEMPTS`)。 - **数据库表名**:小写下划线(`sys_user`);字段名同样小写下划线(`created_at`)。 **示例**: ```java package com.xly.erp.module.usr.controller; @RestController @RequestMapping("/api/v1/users") public class UserController { public Result createUser(@RequestBody @Valid CreateUserReq req) { ... } } ``` ### 1.3 统一响应格式 所有 HTTP 接口返回 `Result` / `PageResult`: ```json // 成功 { "code": 0, "message": "ok", "data": { ... } } // 失败 { "code": 40001, "message": "用户名已存在", "data": null } ``` 错误码段位: - `0`:成功 - `10xxx`:参数 / 校验类错误 - `20xxx`:业务规则错误 - `30xxx`:权限类错误 - `40xxx`:资源类错误(找不到、冲突) - `50xxx`:服务器内部错误 - `60xxx`:第三方依赖错误 ### 1.4 异常处理 - 全局异常处理器 `GlobalExceptionHandler`(`@RestControllerAdvice`)统一捕获并转 `Result.fail(...)`。 - 业务异常用 `BizException(int code, String message)`,service 层抛出,全局处理器捕获后转响应。 - **禁止**在 controller / service 里 `catch (Exception e) { e.printStackTrace(); }` 后吞掉。 - **接口响应禁止回显后端异常堆栈**:仅返回 `code` + 用户友好 `message`;堆栈写日志(含 traceId)。 ### 1.5 事务 - 事务边界统一在 **service 实现层**,使用 `@Transactional(rollbackFor = Exception.class)`。 - controller / mapper 层**禁止**写 `@Transactional`。 - 跨服务(跨进程)调用**禁止**使用本地事务跨边界;改用最终一致性(消息队列 / 补偿任务),本项目当前无跨服务场景。 ### 1.6 认证 - 使用 Spring Security + JWT。 - **Access Token**:HS256,TTL 2 小时;签发后写 Redis(key=`auth:token::`,value=用户摘要)。 - **Refresh Token**:TTL 7 天,单独签发;刷新时旋转 token 并使旧 token 失效。 - 密钥(HMAC secret)放 `.env.local` 的 `JWT_SECRET`,**禁止**写入 application.yml 或代码。 - 登出 / 改密 / 停用:把对应 `jti` 加入 Redis 黑名单直至原 TTL 过期。 ## 二、前端规范 ### 2.1 目录约定 按 Vite + React 18 + Redux Toolkit 惯例分层(详见 docs/09 § 三): | 目录 | 职责 | |---|---| | `src/api/` | Axios 实例 + 各模块接口调用函数;**所有数据访问唯一入口** | | `src/store/` | Redux Toolkit slices;全局态(认证 / 用户信息 / 字典) | | `src/router/` | React Router 配置 + 路由守卫 | | `src/pages//` | 业务页面(按模块分目录) | | `src/components/` | 跨页面通用组件(含 `Permission` 等) | | `src/layouts/` | 框架布局 | | `src/hooks/` | 自定义 hook | | `src/utils/` | 工具方法(日期 / 金额 / 校验等) | | `src/styles/` | 全局样式 + Design Tokens | | `src/types/` | 全局 TypeScript 类型 | **前端禁止直接写 SQL / 操作 DB**;所有数据访问走 `api/` 层封装的 HTTP 调用。 ### 2.2 状态管理 - **全局态**(用户身份 / 权限 / 全局字典 / 主题):Redux Toolkit。 - **页面级态**(表单值 / 列表参数):组件本地 `useState` / `useReducer`。 - **服务端数据**(列表 / 详情):直接调 `api/` 函数,配合 `useEffect` + 本地 state;**不放**全局 store,避免缓存一致性问题。 - 跨页面共享但**非全局**的态用 React Context(如 Modal Provider)。 ### 2.3 请求封装 `src/api/client.ts` 统一 Axios 实例: - baseURL 从 `import.meta.env.VITE_API_BASE_URL` 读取。 - **请求拦截**:自动注入 `Authorization: Bearer `;附带 `X-Request-Id` 用于链路追踪。 - **响应拦截**: - HTTP 200 + `code === 0` → 返回 `data`。 - HTTP 200 + `code !== 0` → 抛业务错误(含 message 和 code)。 - HTTP 401 → 触发 refresh token;refresh 失败 → 清登录态 + 跳登录页。 - HTTP 5xx → 抛网络错误。 - 超时:默认 10s;上传 / 导出接口 60s。 - 不做自动重试(重试由业务调用处显式控制)。 ### 2.4 错误处理 | 错误类型 | 处理方式 | |---|---| | 网络错误(断网 / 5xx) | 顶层 `message.error('网络异常,请重试')`,业务调用处可自定义重试按钮 | | 业务错误(code !== 0) | 默认 `message.error(err.message)`,业务调用处可拦截做特殊提示 | | 表单校验失败 | 字段下方红字(Ant Design `Form` 自带) | | 路由级未授权 | `RequireAuth` 守卫重定向到 `/login` | | 页面级崩溃 | 顶层 `ErrorBoundary` 显示 `Result status="500"` + 重新加载按钮 | ### 2.5 样式与主题 - **CSS 变量命名**:`--color---` - `scope`:`form` / `table-row` / `tag` / `btn` 等;通用全局色无 scope(如 `--color-primary`) - `role`:`bg` / `fg` / `border` - `state`:`edit` / `readonly` / `hover` / `selected` / `disabled`;常态省略 - **文件位置**:`frontend/src/styles/tokens.css`(由 skeleton-gen 生成骨架,色值由 docs/06 § 二锁定)。 - **组件样式中只用 `var(--color-xxx)`**,禁止硬编码 hex / rgba。 - **与 Ant Design 主题对接**:`App.tsx` 顶层包 ``;Ant Design 5 接受 token 对象映射,确保组件库色值与 tokens.css 单一来源。 - 具体 token 表见 `docs/06 § 二`。 ## 三、共同约定 ### 3.1 Git 提交 `(): REQ-XXX-NNN` - type:见 CLAUDE.md § 🗂️ Git 提交规范。 - scope:模块代码小写(`usr` / `pur` / `sal`)或 `infra` / `docs`。 - subject:祈使句,中文,<= 50 字。 - REQ tag:业务类提交(feat / fix / test)必带。 **示例**:`feat(usr): 实现用户登录接口 REQ-USR-001` ### 3.2 分页查询 - **后端**:请求入参 `PageReq { page=1, size=20 }`(兜底默认值;size 上限 100);返回 `PageResult { records: List, total: long, page: int, size: int }`。 - **前端**:使用 Ant Design `Table` + `Pagination`;统一组件包装在 `components/PagedTable`,对接 `PageResult`。 - 排序参数走 `sortField` / `sortOrder`,白名单字段,禁止任意字段排序。 ### 3.3 日期与金额 - **后端类型**:日期用 `LocalDateTime` / `LocalDate`;金额用 `BigDecimal`(精度 2 位)。 - **后端 → 前端**:日期统一序列化为 `YYYY-MM-DD HH:mm:ss` 字符串;金额序列化为 `string`(避免精度丢失)。 - **前端展示**:日期使用 `dayjs` 格式化(`YYYY-MM-DD HH:mm`);金额使用 `utils/money.ts` 格式化为千分位。 - **金额精度**:内部全部 `BigDecimal`,4 舍 6 入 5 成双(`HALF_EVEN`);展示截断到 2 位。 ### 3.4 数据访问规约 - **SELECT 字段显式列举**:禁止 `SELECT *`;MyBatis-Plus 用 `select(User::getId, User::getUsername)` 或 XML 显式列名。 - **禁止 N+1 反模式**:循环中不得执行 DB 查询;改用 `selectBatchIds` / `IN` 子句 / `JOIN`。 - **Mapper XML**:表名 / 字段名用常量或引用,禁止字符串拼接 SQL(防注入)。 - **复杂查询走 XML**,简单 CRUD 走 LambdaQueryWrapper。 - **写操作**:单表批量写用 `saveBatch` / `updateBatchById`;超大批量(>1000)分批 commit。 ### 3.5 配置与安全 - **后端配置**:DB 连接 / 端口 / 密钥 / 第三方 URL 等一律放 `application.yml` + `.env.local`。代码中**禁止硬编码**(用 `@Value` / `@ConfigurationProperties` 注入)。 - **多环境**:`application-dev.yml` / `application-test.yml` / `application-prod.yml`,通过 `SPRING_PROFILES_ACTIVE` 切换。 - **前端安全**: - `localStorage` **禁止**存敏感信息(token / 身份 / 个人数据)。 - Token 推荐**内存 + HttpOnly Cookie**(refresh)或纯内存(access),Redux store 持有 access;刷新页面通过 refresh cookie 重新换取。 - **接口响应禁止回显后端异常堆栈**(与 § 1.4 一致)。 - **密钥来源**:所有密钥(JWT / DB 密码 / 第三方 API key)从 `.env.local` 加载;`.env.local` 在 `.gitignore`,永不入库。