# 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 请求，参数校验，调用 service，返回统一响应 |
| `service` | 业务逻辑编排，事务边界；接口与实现分离 |
| `mapper` | 数据访问层（MyBatis-Plus），单表 CRUD + 自定义 SQL |
| `entity` | 与表 1:1 映射的 PO |
| `dto` | 入参对象（接口入参） |
| `vo` | 出参对象（接口响应） |

### 1.2 命名约定

- **包名**：全小写，根包 `com.xly.erp`，子包按业务模块代码小写（如 `module.usr`）
- **类名**：UpperCamelCase；Controller 后缀 `Controller`，Service 接口无后缀、实现类后缀 `Impl`，Mapper 后缀 `Mapper`，实体后缀 `Entity` 可省略
- **方法名**：lowerCamelCase；CRUD 动词：`create / update / removeById / getById / page / list`
- **常量**：全大写下划线，如 `MAX_LOGIN_ATTEMPTS`

示例 1：`com.example.erp.module.usr.controller.UserController`
示例 2：`com.example.erp.module.mod.service.impl.ModuleServiceImpl`

### 1.3 统一响应格式

所有接口返回 `Result<T>`：

```json
// 成功
{ "code": 0, "msg": "ok", "data": { /* 业务数据 */ } }
// 失败
{ "code": 40001, "msg": "用户名或密码错误", "data": null }
```

错误码段位划分：
- `0`：成功
- `1xxxx`：参数校验失败
- `2xxxx`：认证 / 鉴权失败
- `3xxxx`：业务规则失败
- `5xxxx`：系统内部错误

### 1.4 异常处理

- 全局 `@RestControllerAdvice` 拦截所有 Controller 抛出的异常
- 业务异常用自定义 `BizException(code, msg)`，由全局处理器转为标准 `Result`
- 参数校验异常（`MethodArgumentNotValidException`）统一返回 `1xxxx` 错误码
- **接口响应禁止回显后端异常堆栈**——返回用户友好错误码 + 文案，堆栈只记日志
- 不要在 controller / service 里 catch 后吞异常，必须向上抛或显式转 `BizException`

### 1.5 事务

- 事务边界统一在 `service` 实现类，使用 `@Transactional(rollbackFor = Exception.class)`
- controller / mapper 层禁止开事务
- 跨服务调用（远程 RPC / HTTP）禁止包在事务里；如需保证最终一致性走消息或补偿，不依赖数据库事务

### 1.6 认证

- 登录使用用户名 + 密码，后端签发 JWT（HS256），写入响应 body
- Token 生命周期：access token 8 小时；引入 refresh token（30 天）支持刷新
- 密钥放 `.env.local` 的 `JWT_SECRET`，禁止入仓
- 受保护接口由 Spring Security `JwtAuthenticationFilter` 校验；未携带或过期返回 `2xxxx`

## 二、前端规范

### 2.1 目录约定

| 目录 | 职责 |
|---|---|
| `api/` | HTTP 请求封装；每模块一文件；**前端禁止直接写 SQL / 操作 DB**，所有数据访问走此层 |
| `components/` | 通用展示组件（无业务语义） |
| `pages/` | 按模块分子目录，每 REQ 一页面 |
| `store/` | Redux Toolkit slices；只放跨页面共享状态 |
| `hooks/` | 自定义 hooks，如 `useUser` / `usePagination` |
| `utils/` | 工具函数（日期、金额、权限） |
| `router/` | 路由配置 |

### 2.2 状态管理

- **服务端数据**：每个页面独立请求 + 局部 `useState`，不进 Redux
- **跨页面共享**：登录用户、权限、模块树 等放 Redux Toolkit
- **表单状态**：使用 Ant Design `Form.useForm`，不进 Redux

### 2.3 请求封装

- 统一 axios 实例，配置：`baseURL=/api`、超时 15s、自动注入 `Authorization: Bearer <token>`
- 响应拦截器：`code !== 0` 触发统一错误处理（`message.error(msg)` + 抛错），`401` 跳登录
- 不在业务代码里手动设置请求头

### 2.4 错误处理

- 网络错误：拦截器统一 `message.error('网络异常')`
- 业务错误（`code !== 0`）：拦截器读 `msg` 字段提示，业务代码可 catch 自定义补充
- 页面级错误（路由错误 / 渲染异常）：`ErrorBoundary` 包裹，展示 `Result` 组件

## 三、共同约定

### 3.1 Git 提交

`<type>(<scope>): <subject> REQ-XXX-NNN`

业务类（feat / fix / test）必须带 `REQ-XXX-NNN` 后缀。

### 3.2 分页查询

- **后端**：使用 MyBatis-Plus `Page<T>`，请求入参 `pageNum`（1 起）+ `pageSize`（默认 20，上限 100）；响应 `{ records, total, pageNum, pageSize }`
- **前端**：`Table` 配 `pagination` 配置，与后端字段一一对应

### 3.3 日期与金额

- **后端**：日期统一 `LocalDateTime`（无时区业务）/ `OffsetDateTime`（有时区）；金额一律 `BigDecimal`，小数位精度由业务规则决定
- **前端**：日期展示用 `dayjs`，统一格式 `YYYY-MM-DD HH:mm:ss`；金额展示保留 2 位小数 + 千分位

### 3.4 数据访问规约

- **SELECT 字段必须显式列举**，禁止 `SELECT *`
- 循环中**禁止**执行 DB 查询（N+1 反模式），改用批量 IN / JOIN / 一次查 Map 建索引
- Mapper XML 字段名 / 表名通过 `<sql>` 片段或常量引用，避免散落字符串
- 复杂查询用 MyBatis-Plus `LambdaQueryWrapper`；动态 SQL 用 XML

### 3.5 配置与安全

- DB 连接 / Redis 地址 / JWT 密钥 / 第三方 URL 一律放 `application.yml` + `.env.local`，**代码里禁止硬编码**
- 前端 `localStorage` **禁止**存敏感信息（token / 身份证 / 个人数据），token 存内存 + refresh token 走 HttpOnly Cookie
- 接口响应禁止回显异常堆栈（与 § 1.4 一致）
