# 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 锁定。后续所有规范基于此表推导。 ### 命令清单 > 由 scope-lock(A1) 锁定。Coding 阶段 `coding.mjs` 的 tdd / test-gate 按 stack 读取以下命令。`无` 表示该栈不提供此类命令。 **后端(Spring Boot 3 / Maven / Java 17)** | 类别 | 命令 | |---|---| | build | `mvn -q -B -DskipTests package` | | lint | `mvn -q -B checkstyle:check` | | unit | `mvn -q -B test` | | e2e | 无 | **前端(React / Vite / npm)** | 类别 | 命令 | |---|---| | build | `npm run build` | | lint | `npm run lint` | | unit | `npm run test:unit` | | e2e | `npm run test:e2e` | --- ## 一、后端规范 > 技术栈:Spring Boot 3 + MyBatis-Plus + MySQL 8 + Flyway + Spring Security/JWT,根包 `com.xly.erp`,构建工具 Maven。 ### 1.1 规则 - 所有后端代码位于仓库根 `backend/` 子项目;根包统一为 `com.xly.erp`,禁止散落到其他包名。 - 业务代码按模块组织在 `com.xly.erp.modules.<模块小写代码>` 下(如 `modules.usr`),通用能力在 `com.xly.erp.common` 下,不得跨模块直接引用对方的 `mapper`/`entity`。 - 每个对外接口必须先在 `docs/05-API接口契约.md` 定义,再编码实现;Controller 只做参数校验 + 调 Service,不写业务逻辑。 - 业务 schema 变更一律走 `sql/migrations/V_n__*.sql`(Flyway),禁止在代码或会话里手跑业务 DDL。 - 密码等敏感值只从 `config-vars.yaml` / 环境读取,禁止硬编码进源码或日志。 ### 1.2 分层结构 后端为仓库根下的 `backend/` Maven 子项目,目录布局: ``` backend/ ├── pom.xml # 声明 spring-boot / mybatis-plus / flyway-core / flyway-mysql / spring-security / jjwt / mapstruct / hutool 等依赖 ├── src/main/java/com/xly/erp/ │ ├── ErpApplication.java # Spring Boot 启动类 │ ├── common/ # 跨模块通用能力(不属于任何业务模块) │ │ ├── response/ # Result 统一响应体、ResultCode 枚举、PageResult │ │ ├── exception/ # BusinessException、GlobalExceptionHandler(@RestControllerAdvice) │ │ ├── config/ # MybatisPlusConfig / SecurityConfig / SwaggerConfig / CorsConfig │ │ ├── security/ # JWT 工具、JwtAuthenticationFilter、UserDetails 适配 │ │ └── base/ # BaseEntity(id/创建时间/制单人/逻辑删除等公共字段) │ └── modules/ │ └── usr/ # USR 用户管理(每个业务模块一个子包) │ ├── controller/ # UsrUserController —— 仅校验 + 委派 │ ├── service/ # UsrUserService 接口 │ │ └── impl/ # UsrUserServiceImpl 业务实现 │ ├── mapper/ # UsrUserMapper(继承 MyBatis-Plus BaseMapper) │ ├── entity/ # UsrUser 实体(映射数据库表) │ ├── dto/ # 入参对象(CreateUserDTO / UpdateUserDTO / UserQueryDTO / LoginDTO) │ └── vo/ # 出参对象(UserVO / LoginVO) ├── src/main/resources/ │ ├── application.yml # 端口、数据源、MyBatis-Plus、Flyway locations、JWT 等配置 │ └── mapper/ # 复杂 SQL 的 MyBatis XML(简单 CRUD 用注解/MP 内置) └── src/test/java/com/xly/erp/ # 单元测试 + 集成测试,包结构镜像主代码 ``` - **跨模块判定**:路径 `backend/src/main/java/com/xly/erp/modules//**` 归属模块 ``;`common/**` 为公共区,改动需在《模块完成报告》留痕。 - **Flyway**:迁移脚本在仓库根 `sql/migrations/`,`application.yml` 配置 `spring.flyway.locations=filesystem:../sql/migrations`(相对 `backend/` 工作目录),Spring Boot 启动时自动 apply。 ### 1.3 命名约定 - 类:大驼峰,模块前缀 + 业务名 + 层后缀,如 `UsrUserController` / `UsrUserServiceImpl` / `UsrUserMapper`。 - 方法:小驼峰动词起头,如 `createUser` / `updateUser` / `pageUsers` / `login`。 - 表名:`snake_case` 单数或业务习惯命名(详见 docs/03);实体类名大驼峰对应表名。 - 常量:全大写下划线;DTO/VO 字段小驼峰。 - REST 路径:`/api/<模块>/<资源>`,小写中划线,如 `/api/usr/users`。 ### 1.4 统一响应格式 所有接口返回统一包装 `Result`: ```json { "code": 0, "message": "success", "data": { } } ``` - `code`:0 成功;非 0 为业务/系统错误码(由 `ResultCode` 枚举集中定义)。 - 分页返回 `Result>`,`PageResult` 含 `records` / `total` / `pageNum` / `pageSize`。 - 失败响应不抛栈到前端,`message` 给可读提示。 ### 1.5 异常处理 - 业务错误统一抛 `BusinessException(ResultCode, msg)`,由 `GlobalExceptionHandler` 捕获转 `Result`。 - 参数校验用 `jakarta.validation`(`@Valid` + 注解),校验失败由全局处理器转统一错误。 - 系统异常(未捕获)记录 ERROR 日志并返回通用错误码,不泄露内部细节。 ### 1.6 事务 - 写操作(增/改/删,含多表)在 Service 实现方法上加 `@Transactional(rollbackFor = Exception.class)`。 - 只读查询不开事务;避免在事务方法内做远程调用 / 长耗时操作。 ### 1.7 认证 - 采用 Spring Security + JWT 无状态认证。登录成功签发 JWT(密钥取自 `config-vars.yaml` `secrets.jwt_secret`,有过期时间)。 - 受保护接口经 `JwtAuthenticationFilter` 校验 `Authorization: Bearer `;登录接口 `/api/usr/login` 放行。 - 密码用 `BCryptPasswordEncoder` 哈希存储与比对,禁止明文。 ## 二、前端规范 > 技术栈:React 18 + Ant Design 5 + Redux Toolkit + React Router v6 + Vite + Axios,包名 `xly-erp-web`。 ### 2.1 目录约定 前端为仓库根下的 `frontend/` 子项目,目录布局: ``` frontend/ ├── package.json # name=xly-erp-web;scripts: dev/build/lint/test:unit/test:e2e ├── vite.config.ts ├── index.html ├── src/ │ ├── main.tsx # 入口:挂载 App + Redux Provider + Router + AntD ConfigProvider │ ├── App.tsx │ ├── router/ # React Router v6 路由表 + 路由守卫(未登录跳登录页) │ ├── store/ # Redux Toolkit:store.ts + slices/(authSlice 等) │ ├── api/ # Axios 实例封装(request.ts)+ 各模块 api(usrApi.ts) │ ├── pages/ │ │ └── usr/ # 用户管理页面(用户列表 / 新增 / 编辑 / 登录) │ ├── components/ # 跨页面通用组件 │ ├── styles/ # 引用 Design Tokens(见下) │ └── utils/ # 通用工具 └── tests/ # 单元测试(Vitest)+ e2e(Playwright) ``` - **Design Tokens SSoT**:色值单一来源在仓库根 `src/styles/tokens.css`(由 skeleton-gen 生成),前端在 `main.tsx` / 全局样式中引入;组件只用 `var(--color-xxx)`,禁止硬编码 hex/rgba。**色值冲突时 `tokens.css` 优先于 `prototype/`**。 - **UI/交互/布局权威**:项目根 `prototype/`(完整 demo)为前端页面布局与交互的权威参照,A5 据其推导 FE 清单。 ### 2.2 状态管理 - 全局状态(登录态、当前用户、token)用 Redux Toolkit `createSlice` 管理;按域拆 slice。 - 服务端数据优先就近在页面用 hooks 拉取,跨页面共享的才进 store;避免把所有响应塞进全局。 ### 2.3 请求封装 - 统一 Axios 实例(`api/request.ts`):baseURL 指向后端 `/api`,请求拦截器注入 `Authorization` 头,响应拦截器拆 `Result`、对非 0 `code` 统一提示。 - 各模块 API 集中在 `api/<模块>Api.ts`,页面只调封装后的方法,不直接散用 axios。 ### 2.4 错误处理 - 响应拦截器统一处理:401 跳登录、业务错误码弹 `message.error`、网络异常兜底提示。 - 表单提交错误就近在表单展示;列表加载失败展示空态/重试。 ## 三、共同约定 ### 3.1 Git 提交 `(): REQ-XXX-NNN`(详见 `CLAUDE.md § 🗂️ Git 提交规范`)。 ### 3.2 分页查询 - 入参统一 `pageNum`(从 1 起)+ `pageSize`(有上限,默认 10/20,最大 100)+ 业务过滤条件。 - 返回 `PageResult`:`records` / `total` / `pageNum` / `pageSize`。 - 文本条件模糊匹配,枚举/外键条件精确匹配;空条件返回全量分页。 ### 3.3 日期与金额 - 日期时间统一 ISO-8601 字符串传输(`yyyy-MM-dd'T'HH:mm:ss`),后端用 `LocalDateTime`。 - 金额用整数分或 `BigDecimal`,禁止用 `float/double` 表示金额。 ### 3.4 数据访问规约 - 数据访问只走 Mapper(MyBatis-Plus);简单 CRUD 用 MP 内置/`LambdaQueryWrapper`,复杂 SQL 写 XML。 - 禁止在 Controller 直接操作 Mapper;逻辑删除/审计字段(创建时间、制单人)由 `BaseEntity` + MP 自动填充统一处理。 - 业务 schema 变更走 Flyway migration,并反向同步更新 `docs/03-数据库设计文档.md` 对应表小节(SSoT 一致)。