You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
houqin-java/docs/04-开发与测试规范.md

364 lines
13 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 医院物业SaaS管理后台 — 开发与测试规范
> 版本v1.0
> 定位:开发团队统一规范,所有开发人员必须严格遵守
> 日期2026-04-16
---
## 一、后端开发规范
### 1.1 代码分层规范
```
Controller层接收请求、参数校验、调用Service、返回响应
Service层业务逻辑编排、事务管理、权限校验
Repository层数据访问MyBatis-Plus Mapper
```
**严格分离原则**
| 类型 | 用途 | 位置 |
|------|------|------|
| DTO | 接收请求参数 | `dto/request/` |
| VO | 返回响应数据 | `dto/response/` |
| Entity | 数据库映射 | `entity/` |
| 禁止 | Controller直接返回Entity | — |
| 禁止 | Service层接收HttpServletRequest | — |
### 1.2 命名规范
| 对象 | 规范 | 示例 |
|------|------|------|
| 包名 | 全小写,模块开头 | `com.hospital.mgmt.modules.repair` |
| 类名 | 大驼峰 | `RepairOrderService` |
| 方法名 | 小驼峰,动词开头 | `createOrder`, `getById`, `listByStatus` |
| 常量 | 全大写下划线 | `MAX_UPLOAD_SIZE` |
| 数据库表名 | 小写下划线,模块前缀 | `repair_order`, `inspection_task` |
| 数据库字段 | 小写下划线 | `created_at`, `tenant_id` |
| 枚举值 | 全大写下划线 | `ACTIVE`, `PENDING` |
| API路径 | 小写连字符,资源复数 | `/repair-orders`, `/check-in` |
### 1.3 数据库规范
- 所有业务表必须包含 `tenant_id` 字段
- 主键使用雪花算法生成 BIGINT
- 逻辑删除:`deleted` 字段0-正常1-已删除)
- 枚举值存储为 VARCHAR禁止使用数字枚举
- JSON 字段用于存储动态配置(如 `check_items`, `skills`),禁止存储核心查询字段
- 索引规范:
- 所有表自动在 `tenant_id` 上建立索引
- 业务编码字段建立唯一索引
- 状态+时间组合查询建立复合索引
- 禁止在 JSON 字段上建索引
### 1.4 模块开发规范
- 详见 `05-接口规范.md` IModulePlugin 规范
- 每个模块必须实现 `IModulePlugin` 接口
- 模块目录结构:
```
modules/{module-code}/
├── {ModuleCode}Module.java # IModulePlugin实现类
├── config/ # 模块配置
├── controller/ # REST控制器
├── service/ # 业务服务
├── entity/ # 数据实体
├── dto/ # 数据传输对象
├── repository/ # 数据访问层
├── event/ # 模块事件
└── resources/
├── module.yml # 模块描述文件
└── db/migration/ # 数据库迁移脚本
```
- 模块间通信必须通过 Spring Event禁止跨模块直接调用 Service
- 新模块上线前必须通过审核清单(详见 `05-接口规范.md` 模块安全规范)
### 1.5 审计日志规范
- 所有写操作自动记录审计日志AOP 切面统一处理)
- 业务代码中只需在 Controller 方法上添加 `@AuditLog` 注解
- 记录内容自动采集操作人、时间、IP、模块、操作类型
- 变更前后数据快照UPDATE/DELETE 操作自动对比记录
- 禁止在业务代码中手动记录审计日志
---
## 二、前端开发规范Vue 3 + TypeScript
### 2.1 组件规范
| 规范项 | 要求 |
|--------|------|
| 组件命名 | 大驼峰,多词组合(`RepairOrderList.vue` |
| 组件结构 | `<script setup lang="ts">``<template>``<style scoped>` |
| Props 定义 | 使用 `defineProps<T>()` + TypeScript 接口 |
| Emit 定义 | 使用 `defineEmits<T>()` + TypeScript 接口 |
| 组件粒度 | 单一职责,单个组件不超过 300 行 |
| 样式隔离 | 必须使用 `<style scoped>` |
### 2.2 TypeScript 规范
| 规范项 | 要求 |
|--------|------|
| 类型定义 | 接口用 `interface`,联合类型用 `type` |
| 禁止 | 禁止使用 `any`,必须用 `unknown` + 类型守卫 |
| 枚举 | 业务状态枚举定义在 `types/enums/` 下 |
| API 响应类型 | 每个 API 定义 Request/Response 类型 |
### 2.3 状态管理规范Pinia
- 全局状态:用户信息、权限集、字典数据 → `stores/global/`
- 模块状态:按模块划分 Store → `stores/modules/`
- Store 命名:`use{Module}Store`,如 `useRepairStore`
- 异步操作统一使用 `async/await`,在 Store 的 Action 中处理
### 2.4 API 调用规范
- 所有 API 调用封装在 `services/` 目录下
- 使用 Axios 实例统一处理请求头、Token、错误拦截
- 接口函数命名:`get{Resource}List`、`create{Resource}`、`update{Resource}`、`delete{Resource}`
- 禁止在组件中直接调用 Axios
> **前端界面开发规范**开发流程、Mock数据、组件标准、H约束实现、共享组件管理、自测标准→ 详见 `07-前端界面开发规范.md`
---
## 三、小程序开发规范uni-app
### 3.1 目录规范
```
miniprogram/
├── pages/ # 页面(按功能模块分组)
│ ├── repair/ # 报修模块
│ ├── inspection/ # 巡检模块
│ └── ...
├── components/ # 公共组件
├── services/ # API调用层
├── stores/ # Pinia状态管理
├── utils/ # 工具函数
│ ├── bluetooth.ts # 蓝牙工具(统一封装)
│ ├── auth.ts # 认证工具
│ └── upload.ts # 上传工具
└── types/ # TypeScript类型
```
### 3.2 蓝牙调用规范
- 蓝牙功能统一通过 `utils/bluetooth.ts` 封装调用
- 禁止在业务代码中直接调用 `uni.createBLEConnection` 等底层 API
- **核心规则:不需要判断距离,只要成功连接上蓝牙设备即可打卡**
- 调用流程:
1. `bluetooth.scan(timeout)` — 扫描 Beacon
2. `bluetooth.connect(deviceId)` — 连接设备(连接成功即视为在岗,无需距离校验)
3. `bluetooth.disconnect()` — 断开连接
- 失败降级:
- 非强制蓝牙场景:蓝牙失败可直接手动打卡
- 强制蓝牙场景:蓝牙失败进入补录模式,需主管审核
### 3.3 图片上传规范
- 所有拍照场景必须调用 `utils/upload.ts` 统一封装
- 水印功能:通过参数 `addWatermark: true` 自动添加时间+位置水印
- 蓝牙场景拍照:上传时附带 `bluetooth_connected` 标记
---
## 四、Git 分支与提交规范
### 4.1 分支策略
| 分支 | 用途 | 命名 | 保护 |
|------|------|------|------|
| main | 生产分支 | main | 禁止直接推送,仅通过 MR 合入 |
| develop | 开发分支 | develop | 禁止直接推送,需 Code Review |
| feature | 功能分支 | feature/{module}/{description} | 从 develop 创建 |
| hotfix | 紧急修复 | hotfix/{description} | 从 main 创建 |
| release | 发布分支 | release/{version} | 从 develop 创建 |
### 4.2 分支流程
```
feature/repair/order-list develop main
│ │ │
├── 提交代码 ──▶─────────┤ │
│ │ │
│ Code Review 通过 │
│ ├──────────┤ release 合入
│ │ │
```
### 4.3 Commit Message 规范
采用 [Conventional Commits](https://www.conventionalcommits.org/) 格式:
```
<type>(<scope>): <subject>
<body>
<footer>
```
**Type 枚举**
| Type | 说明 |
|------|------|
| feat | 新功能 |
| fix | 修复 Bug |
| docs | 文档变更 |
| style | 代码格式(不影响逻辑) |
| refactor | 重构(非新功能、非修复) |
| perf | 性能优化 |
| test | 测试相关 |
| chore | 构建/工具变更 |
**Scope 枚举**`repair` / `inspection` / `cleaning` / `attendance` / `contract` / `bidding` / `auth` / `org` / `system` / `common`
**示例**
```
feat(repair): 新增工单延期审批功能
- 支持主管审批/驳回延期申请
- 审批结果通过 WebSocket 推送通知
Closes #123
```
### 4.4 分支保护规则
- main / develop 分支禁止强制推送(`--force`
- 合并到 develop 必须经过 Code Review至少1人批准
- 合并到 main 必须经过 Code Review至少2人批准
- 合并后自动删除源分支
---
## 五、前后端协作规范
### 5.1 API 联调流程
```
1. 后端定义接口路径、权限编码 → 录入接口文档Swagger
2. 前端根据文档定义 TypeScript 类型 + API 调用函数
3. 前端使用 Mock 数据开发页面
4. 后端接口开发完成 → 通知前端切换联调环境
5. 联调问题记录在 TAPD 缺陷中,标注"联调"标签
```
### 5.2 接口文档管理
- 工具Swagger / OpenAPISpringDoc 自动生成)
- 地址:开发环境 `/swagger-ui.html`
- 要求:接口文档与代码同步维护,变更接口必须同步更新文档
- 版本管理:接口变更需在文档中标注变更日期和变更说明
### 5.3 Mock 数据规范
- 前端开发阶段使用 Mock 数据,不依赖后端接口可用性
- Mock 工具Mock.js 或 json-server
- Mock 数据结构必须与接口文档定义一致
- 联调时通过环境变量切换 Mock / 真实接口
### 5.4 联调排期约定
- 每周一对齐本周联调计划,明确接口交付时间
- 后端接口延迟交付需提前1天通知前端
- 联调环境统一使用 test 环境,禁止使用开发人员本地环境
---
## 六、代码审查要求
所有代码合并到 develop 前必须经过 Code Review审查重点
- [ ] 是否遵循分层规范Controller / Service / Repository 分离)
- [ ] 是否有 SQL 注入风险(禁止拼接 SQL
- [ ] 是否有租户隔离漏洞(缺少 tenant_id 条件)
- [ ] 是否有权限校验API 声明权限要求)
- [ ] 是否有审计日志(写操作添加 @AuditLog
- [ ] 异常处理是否完善(全局异常处理 + 业务异常细分)
- [ ] 是否有硬编码配置(应使用配置文件或字典)
- [ ] 单元测试覆盖率是否达标
- [ ] 新增/修改代码是否包含对应测试用例
- [ ] 前端:是否使用 TypeScript 类型、是否有 XSS 风险
---
## 七、测试规范
### 7.1 单元测试
- **覆盖率要求**:核心业务逻辑 100% 覆盖(行覆盖 + 分支覆盖)
- **框架**JUnit 5 + Mockito
- **命名规范**`test_{方法名}_{场景}_{预期结果}`,如 `test_createOrder_withValidData_returnOrderId`
- **必须测试的场景**
- 正常流程
- 参数校验失败
- 权限不足
- 数据不存在
- 状态冲突
- 所有分支路径if/else、case 分支)
- 异常处理路径
### 7.2 测试前置流程
- **强制要求**:每次代码修改后,必须先运行测试,通过后才能提交
- **本地开发流程**
1. 编写/修改代码
2. 运行相关单元测试(`mvn test`
3. 测试通过 → 提交代码
4. 测试失败 → 修复代码 → 重新测试
- **CI 门禁**
- 代码提交自动触发流水线
- 单元测试失败 → 阻断合并
- 集成测试失败 → 阻断部署
- **测试报告**每次构建生成覆盖率报告JaCoCo
### 7.3 集成测试
| 测试场景 | 验证要点 |
|----------|----------|
| 多租户隔离 | 不同租户数据完全隔离,越权访问被拦截 |
| 读写分离 | 写操作走主库,读操作走从库,从库故障时降级到主库 |
| 权限实时生效 | 权限变更后通过 Redis Pub/Sub 毫秒级广播,各实例缓存即时刷新 |
| 权限降级保障 | Redis 连接断开时,权限缓存 TTL(2小时)到期后自动刷新 |
| 蓝牙策略配置 | 强制/非强制蓝牙场景的行为差异 |
### 7.4 蓝牙场景测试
| 测试场景 | 预期结果 |
|----------|----------|
| 蓝牙连接成功 | 打卡成功check_type=BLUETOOTH无需距离校验连接即打卡 |
| 无蓝牙信号(强制蓝牙) | 进入补录模式 |
| 无蓝牙信号(非强制蓝牙) | 允许手动打卡check_type=MANUAL |
| 拍照时蓝牙断开(强制蓝牙) | 提示蓝牙断开,无法拍照 |
| 拍照时蓝牙断开(非强制蓝牙) | 可继续拍照 |
| Beacon 离线 | 系统通知物业管理人员 |
### 7.5 性能测试
- 工具JMeter / wrk
- 场景:
- 100 并发用户持续 30 分钟API P99 < 500ms
- 单接口压测,确认无慢 SQL>1秒
- 数据库主从延迟 < 1
### 7.6 安全测试
| 测试项 | 方法 |
|--------|------|
| SQL 注入 | 自动化扫描 + 手工验证 |
| 越权访问 | 水平越权 + 垂直越权测试 |
| 敏感数据暴露 | 检查响应中是否泄露手机号、身份证等 |
| 接口鉴权 | 未认证、无权限、Token 过期三种场景 |
| XSS 攻击 | 输入恶意脚本,验证存储/反射型 XSS |
---
> **本文档为开发规范标准,所有开发人员必须严格遵守。如有疑问或需要调整,需经技术负责人审批。**