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/06-项目技术要求.md

493 lines
22 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.1
> 定位:内部团队开发标准,所有开发人员必须严格按照此标准执行
> 日期2026-04-16
---
## 一、技术栈选型与版本要求
### 1.1 后端技术栈
| 技术 | 版本要求 | 用途 |
|------|----------|------|
| Java | 17+ | 开发语言 |
| Spring Boot | 3.x | 应用框架 |
| MariaDB | 10.6+ | 主数据库(主从复制读写分离) |
| Redis | 7.x | 缓存(权限/字典/菜单)、分布式锁 |
| MyBatis-Plus | 3.5+ | ORM框架 |
| Spring Security | 6.x | 认证与授权 |
| JWT (jjwt) | 0.12+ | Token生成与校验 |
| 腾讯云COS SDK | 最新稳定版 | 文件存储 |
| ShedLock | 5.x+ | 分布式定时任务锁 |
### 1.2 前端Web技术栈
| 技术 | 版本要求 | 用途 |
|------|----------|------|
| Vue | 3.x | 前端框架 |
| TypeScript | 5.x | 类型安全 |
| Vite | 5.x | 构建工具 |
| Pinia | 2.x | 状态管理 |
| Vue Router | 4.x | 路由管理 |
| Element Plus | 最新稳定版 | UI组件库 |
| Axios | 1.x | HTTP客户端 |
| ECharts | 5.x | 图表可视化 |
### 1.3 微信小程序技术栈
| 技术 | 版本要求 | 用途 |
|------|----------|------|
| uni-app | 3.x | 跨端框架Vue 3模式 |
| uni-ui | 最新稳定版 | UI组件库 |
| uni-ble | 兼容最新版 | 蓝牙低功耗(BLE)插件 |
### 1.4 基础设施
| 技术 | 用途 |
|------|------|
| Docker + Docker Compose | 私有云容器化部署 |
| Nginx | 反向代理 + 静态资源 |
| Jenkins / GitLab CI | CI/CD流水线 |
| Git | 版本管理 |
---
## 二、架构设计要求
### 2.1 整体架构
```
┌─────────────────────────────────────────────────┐
│ 客户端层 │
│ Vue3 Web管理后台 │ uni-app微信小程序 │
└───────────┬───────────┴───────────┬──────────────┘
│ HTTPS │
┌───────────▼───────────────────────▼──────────────┐
│ 网关层 │
│ Nginx 反向代理 │
└───────────┬──────────────────────────────────────┘
┌───────────▼──────────────────────────────────────┐
│ 应用层 │
│ Spring Boot 单体应用(模块化 IModulePlugin
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │报修 │ │巡检 │ │保洁 │ │考勤 │ │合同 │... │
│ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ └──┬───┘ │
│ └────────┴────────┴────────┴────────┘ │
│ Spring Event 模块间通信 │
└───────────┬──────────────────────────────────────┘
┌───────────▼──────────────────────────────────────┐
│ 数据层 │
│ MariaDB主库 ──复制──▶ MariaDB从库读写分离
│ Redis 缓存(权限/字典/菜单) │
│ 腾讯云COS照片/附件/合同文件) │
└──────────────────────────────────────────────────┘
```
### 2.2 多租户方案
- **隔离方式**:共享数据库 + 行级隔离(`tenant_id`字段)
- **实现方式**MyBatis-Plus `TenantLineInnerInterceptor` 自动注入 `tenant_id` 条件
- **租户识别**从JWT Token中提取 `tenant_id`,无需前端传递
- **超管例外**:超级管理员操作不受租户隔离限制
### 2.3 模块化架构
- **核心接口**`IModulePlugin`(详见 `05-接口规范.md`
- **模块注册**:系统启动时自动扫描并注册所有 `IModulePlugin` 实现类
- **模块通信**Spring `ApplicationEvent` + `ApplicationEventPublisher`
- **模块隔离**各模块独立目录结构禁止跨模块直接调用Service必须通过Event解耦
- **租户级控制**:支持按租户启用/禁用特定模块(`sys_tenant_module` 表)
### 2.4 前后端分离
- Web端与后端通过RESTful API通信
- 小程序端与后端通过同一套API通信
- 前端路由由后端权限接口动态驱动
- 统一JWT认证Web端存localStorage小程序端存本地Storage
### 2.5 读写分离方案
- **实现方式**MariaDB主从复制 + MyBatis-Plus动态数据源切换
- **路由规则**
- 写操作INSERT/UPDATE/DELETE→ 主库
- 读操作SELECT→ 从库
- **注解标记**:自定义 `@ReadOnly` 注解标记读操作AOP切面切换数据源
- **容错机制**从库不可用时自动降级到主库读取超时阈值3秒
- **配置要求**:在 `application.yml` 中分别配置 `spring.datasource.master``spring.datasource.slave` 两套数据源连接地址
---
## 三、去中间件方案
**不引入RocketMQ/Kafka等消息中间件**采用以下Spring Boot内置机制替代
### 3.1 权限变更实时通知
- **替代方案**Redis Pub/Sub + Spring Event
- **实现细节**
1. 权限变更时,通过 Redis Pub/Sub 发布变更消息 `PUBLISH permission:changed <version>`
2. 各服务实例订阅 `permission:changed` 频道,收到消息后触发 Spring Event
3. 监听器刷新本地权限缓存
- **优势**:毫秒级延迟,零数据库压力,复用已有 Redis 实例
- **降级策略**Redis 连接断开时,权限缓存 TTL(2小时)到期后自动刷新
- **实现要点**
1. 权限变更时通过 `StringRedisTemplate.convertAndSend()` 发布消息到 `permission:changed` 频道
2. 各实例 `MessageListener` 订阅该频道,收到消息后发布 Spring Event
3. `@EventListener` 监听事件并刷新本地权限缓存
### 3.2 异步任务处理
- **替代方案**Spring `@Async` + 自定义线程池
- **线程池配置要求**
- 核心线程数CPU核心数默认4
- 最大线程数CPU核心数×2默认8
- 队列容量1000
- 线程空闲时间60秒
- 拒绝策略CallerRunsPolicy调用者线程执行
- **适用场景**:报表导出、消息推送、日志异步写入、图片处理
- **持久化保障**:关键任务必须先落库再异步执行,避免线程池丢失任务
### 3.3 模块间事件通信
- **替代方案**Spring `ApplicationEvent` + `ApplicationEventPublisher`
- **进程内通信**直接使用Spring Event事件定义在共享API模块中
- **跨实例通信**Redis Pub/Sub 广播事件(与权限通知同一机制)
- **预定义事件**
| 事件类型 | 来源模块 | 消费方 |
|----------|----------|--------|
| ORDER_COMPLETED | repair | evaluation(触发评价) |
| INSPECTION_ABNORMAL | inspection | repair(生成报修) |
| CLEANING_TIMEOUT | cleaning | notification(推送预警) |
| BEACON_OFFLINE | device | notification(推送预警) |
| PERMISSION_CHANGED | permission | 各模块(刷新缓存) |
### 3.4 定时任务
- **替代方案**Spring `@Scheduled` + 数据库分布式锁
- **分布式锁实现**ShedLock 或数据库行锁(`SELECT ... FOR UPDATE`
- **适用场景**巡检任务自动生成、保洁超时预警、合同到期提醒、Beacon心跳检测
- **实现要点**:定时方法加 `@Scheduled` 注解声明cron表达式配合 `@ShedLock` 注解声明锁名称、最少/最多持有时间,确保多实例部署时同一时刻仅一个实例执行
---
## 四、安全要求
### 4.1 认证方案
| 场景 | 认证方式 | Token管理 |
|------|----------|-----------|
| Web端登录 | 用户名+密码 → JWT | localStorage存储2小时过期 |
| 小程序登录 | 微信openid静默登录 → JWT | 本地Storage存储2小时过期 |
| 小程序首次使用 | 微信授权openid + 手机号绑定 | 自动创建账号 |
**JWT载荷标准字段**
| 字段 | 说明 |
|------|------|
| sub | 用户ID |
| tid | 租户ID |
| utype | 用户类型 |
| hid | 医院ID |
| pid | 物业公司ID |
| sid | 员工ID |
| iat | 签发时间 |
| exp | 过期时间 |
### 4.2 四级权限体系
权限按 **功能菜单 → 页面 → 功能点 → 动作** 四级树形结构划分:
- **7种动作类型**:查看(view)、新增(create)、编辑(update)、删除(delete)、审批(approve)、导出(export)、分配(assign)
- **权限编码规范**`{module}:{page}:{action}`,如 `repair:list:create`
- **自动同步**:新模块通过 `IModulePlugin.getPermissionDefinitions()` 自动注册到权限配置表
- **实时生效**权限变更后毫秒级生效Redis Pub/Sub无需重新登录
### 4.3 数据权限(行级隔离)
| 角色 | 数据范围 | 实现方式 |
|------|----------|----------|
| 超级管理员 | 全局所有数据 | 不注入tenant_id条件 |
| 医院账号 | 本医院+关联物业公司数据 | 注入hospital_id条件只读 |
| 物业公司管理员 | 绑定医院数据 | 注入tenant_id + hospital_id条件 |
| 主管 | 本班组数据 | 注入team_id条件 |
| 员工 | 仅本人数据 | 注入staff_id条件 |
**实现方式**MyBatis-Plus拦截器自动注入SQL条件禁止手动拼接数据权限条件。
### 4.4 蓝牙策略配置
蓝牙打卡/巡检/拍照是否强制要求连接,由物业公司配置、医院账号审核:
- **配置方**:物业公司管理员
- **审核方**:医院账号
- **配置项**:各场景是否强制蓝牙连接
| 场景 | 配置项 | 强制蓝牙时的行为 | 非强制蓝牙时的行为 |
|------|--------|-----------------|-------------------|
| 巡检打卡 | `inspection_check_in` | 必须连接Beacon打卡失败进补录 | 可手动打卡(check_type=MANUAL) |
| 巡检拍照 | `inspection_photo` | 必须在蓝牙连接下拍照 | 可自由拍照 |
| 保洁打卡 | `cleaning_check_in` | 必须连接Beacon打卡失败进补录 | 可手动打卡(check_type=MANUAL) |
| 保洁拍照 | `cleaning_photo` | 必须在蓝牙连接下拍照 | 可自由拍照 |
| 考勤打卡 | `attendance_check` | 必须连接Beacon打卡失败提交异常申诉 | 可手动打卡(check_type=MANUAL) |
- **数据标记**:所有打卡记录区分 `check_type`BLUETOOTH/MANUAL后台列表和统计报表明确显示
- **降级逻辑**
- 非强制蓝牙场景:蓝牙失败可直接手动打卡
- 强制蓝牙场景:蓝牙失败进入补录模式,需主管审核
- **审核流程**:物业公司提交配置 → 医院账号审核通过后生效 → 审核拒绝则维持原配置
### 4.5 审计日志
- **记录范围**所有写操作CREATE/UPDATE/DELETE/APPROVE/ASSIGN/EXPORT自动记录
- **实现方式**AOP切面统一处理业务代码无感知
- **记录内容**操作人、时间、IP、模块、操作类型、变更前后数据快照
- **权限变更日志**:单独记录,展示变更前后权限对比
- **数据补录日志**:单独记录,标记补录原因和审核状态
- **日志保留**至少保留1年支持导出
### 4.6 通用安全要求
| 安全项 | 要求 |
|--------|------|
| SQL注入防护 | 必须使用MyBatis-Plus参数化查询禁止拼接SQL |
| XSS防护 | 所有用户输入必须HTML转义后存储前端渲染使用v-text而非v-html |
| 密码存储 | BCrypt加密禁止明文存储 |
| 敏感数据 | 手机号脱敏显示138****1234身份证号如需存储需AES加密 |
| 接口鉴权 | 所有API必须声明权限要求除公开接口外 |
| 跨域控制 | Nginx配置白名单域名禁止 `Access-Control-Allow-Origin: *` |
| 请求限流 | Redis令牌桶限流API默认100次/分钟/用户 |
---
## 五、性能要求
### 5.1 响应时间基线
| 指标 | 要求 | 测量方式 |
|------|------|----------|
| API平均响应时间 | < 300ms | 服务端P50 |
| API P99响应时间 | < 500ms | 服务端P99 |
| 列表查询(含分页) | < 500ms | 端到端 |
| 报表生成(单月数据) | < 5s | 端到端 |
| 蓝牙扫描超时 | 3 | 客户端 |
| 蓝牙连接建立 | < 3 | 客户端 |
### 5.2 并发与容量
- 单实例支持100 QPS
- 支持水平扩展(无状态设计,SessionRedis
- 数据库连接池:HikariCP,最大连接数 = CPU核心数 * 2 + 1
- Redis连接池:Lettuce,最大连接数 = CPU核心数 * 2
### 5.3 缓存策略
| 缓存对象 | 过期策略 | 刷新机制 |
|----------|----------|----------|
| 用户权限集 | 2小时TTL | 权限变更时实时刷新(毫秒级,Redis Pub/Sub |
| 字典数据 | 24小时TTL | 字典变更时手动/自动刷新 |
| 菜单配置 | 24小时TTL | 菜单变更时手动/自动刷新 |
| 业务数据 | 按需懒加载 | 不缓存,实时查询 |
### 5.4 蓝牙交互可靠性
| 指标 | 要求 |
|------|------|
| 连接判定 | **不判断距离,只要成功连接蓝牙设备即可打卡** |
| 信号阈值 | RSSI > -70dBm可配置仅用于判定是否能建立连接 |
| 扫描超时 | 3秒 |
| 重试次数 | 3次 |
| 补录降级 | 蓝牙失败后必须提供补录/手动打卡入口 |
| 心跳检测 | Beacon每5分钟上报心跳超15分钟标记OFFLINE |
---
## 六、数据库备份与恢复
### 6.1 备份策略
| 备份类型 | 频率 | 工具 | 保留时间 |
|----------|------|------|----------|
| 全量备份 | 每日凌晨2:00 | mysqldump --single-transaction | 30天 |
| 增量备份 | 每4小时 | MariaDB binlog | 7天 |
| 异地备份 | 每日 | rsync/scp到备份服务器 | 30天 |
### 6.2 备份存储
- **主存储**:私有云本地磁盘(独立磁盘,与数据盘分离)
- **异地存储**:异地备份服务器(不同机房或不同物理机)
- **备份文件命名**`hospital_mgmt_full_YYYYMMDD_HHmmss.sql.gz`、`hospital_mgmt_incr_YYYYMMDD_HHmmss.binlog.gz`
### 6.3 恢复方案
| 指标 | 要求 |
|------|------|
| RTO恢复时间目标 | < 2小时 |
| RPO(恢复点目标) | < 4小时(增量备份间隔) |
| 恢复方式 | 全量恢复 + binlog重放 |
| 恢复流程 | 1. 停止应用 2. 恢复最近全量备份 3. 重放binlog到故障时间点 4. 验证数据完整性 5. 启动应用 |
### 6.4 恢复演练
- **频率**:每季度一次
- **内容**:在测试环境执行完整恢复流程,验证RTORPO
- **记录**:演练结果记录文档,问题纳入改进计划
- **责任人**DBA + 运维
### 6.5 备份脚本要求
- 全量备份使用 `mysqldump --single-transaction` 导出并gzip压缩
- 备份文件命名格式:`hospital_mgmt_full_YYYYMMDD_HHmmss.sql.gz`(增量:`hospital_mgmt_incr_YYYYMMDD_HHmmss.binlog.gz`
- 自动清理30天前的全量备份文件
- 备份完成后通过 rsync 同步到异地备份服务器
---
## 七、开发与测试规范
> 开发规范、测试规范已独立为 `04-开发与测试规范.md`,本章仅保留引用。
- **后端开发规范**(代码分层、命名、数据库、模块开发、审计日志)→ 详见 `04-开发与测试规范.md` 第一章
- **前端开发规范**Vue3组件、TypeScript、状态管理、API调用)→ 详见 `04-开发与测试规范.md` 第二章
- **小程序开发规范**(目录、蓝牙、图片上传)→ 详见 `04-开发与测试规范.md` 第三章
- **Git分支与提交规范** 详见 `04-开发与测试规范.md` 第四章
- **前后端协作规范** 详见 `04-开发与测试规范.md` 第五章
- **代码审查要求** 详见 `04-开发与测试规范.md` 第六章
- **测试规范**(单元测试、集成测试、蓝牙测试、性能测试、安全测试)→ 详见 `04-开发与测试规范.md` 第七章
---
## 八、部署与运维要求
### 8.1 部署架构(私有云)
```
┌──────────────────────────────────────────┐
│ 私有云服务器 │
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ Nginx │ │ Docker Compose │ │
│ │ 反向代理 │──│ ┌────────────┐ │ │
│ │ 静态资源 │ │ │ Spring Boot│ │ │
│ └─────────────┘ │ │ 应用容器 │ │ │
│ │ └────────────┘ │ │
│ │ ┌────────────┐ │ │
│ │ │ Redis │ │ │
│ │ │ 缓存容器 │ │ │
│ │ └────────────┘ │ │
│ └─────────────────┘ │
│ │
│ ┌─────────────┐ ┌─────────────────┐ │
│ │ MariaDB主库 │ │ MariaDB从库 │ │
│ │ 写操作 │──│ 读操作 │ │
│ └─────────────┘ └─────────────────┘ │
└──────────────────────────────────────────┘
```
### 8.2 Docker Compose部署要求
部署包含以下服务容器:
| 服务 | 镜像 | 说明 |
|------|------|------|
| app | hospital-mgmt:latest | Spring Boot应用,端口8080,依赖RedisMariaDB主库 |
| redis | redis:7-alpine | 缓存服务,持久化存储 |
| mariadb-master | mariadb:10.6 | 主库(写),持久化存储 |
| mariadb-slave | mariadb:10.6 | 从库(读),依赖主库,持久化存储 |
| nginx | nginx:alpine | 反向代理+静态资源,端口80/443,挂载自定义nginx.conf和前端dist目录 |
- **环境变量注入**:通过 `SPRING_PROFILES_ACTIVE`、`SPRING_DATASOURCE_URL`、`SPRING_DATASOURCE_SLAVE_URL`、`SPRING_REDIS_HOST` 等环境变量配置连接信息,禁止硬编码
### 8.3 小程序版本更新策略
```
小程序启动
调用 GET /system/versions/latest 获取最新版本号
与本地版本号比较
├── 版本一致 ──▶ 正常使用
├── 小版本更新(兼容) ──▶ 提示"发现新版本,是否更新?"
└── 大版本更新(不兼容) ──▶ 强制更新,引导前往微信更新
```
### 8.4 缓存管理策略
| 触发方式 | 清理范围 | 说明 |
|----------|----------|------|
| 系统启动 | 全部缓存 | 启动时自动清理 |
| 权限变更 | 权限缓存 | 变更后毫秒级自动刷新(Redis Pub/Sub |
| 手动清理 | 指定模块缓存 | 超管在"缓存管理"页面操作 |
| 系统更新 | 全部缓存 | 部署新版本后自动清理 |
### 8.5 监控与告警
| 监控项 | 告警条件 | 通知方式 |
|--------|----------|----------|
| 应用健康 | 健康检查失败 | 邮件+企业微信 |
| 数据库连接 | 连接池使用率>80% | 企业微信 |
| Redis连接 | 连接池使用率>80% | 企业微信 |
| Beacon离线 | 离线超过15分钟 | 系统内通知 |
| Beacon低电量 | 电量<20% | 系统内通知 |
| 磁盘空间 | 使用率>85% | 邮件+企业微信 |
| 备份失败 | 备份任务失败 | 邮件 |
---
## 九、接口规范
> 接口规范已独立为 `05-接口规范.md`,本章仅保留引用。
- **全局约定**(请求头、统一响应格式、错误码、查询参数)→ 详见 `05-接口规范.md` 第一章
- **认证规范**认证方式、JWT载荷、权限编码→ 详见 `05-接口规范.md` 第二章
- **文件上传规范** → 详见 `05-接口规范.md` 第三章
- **模块化架构规范**IModulePlugin、模块注册、事件通信、版本升级、安全规范→ 详见 `05-接口规范.md` 第四~八章
- **接口权限汇总** → 详见 `05-接口规范.md` 第九章
---
## 十、环境配置管理
### 10.1 环境划分
| 环境 | 用途 | 数据库 | 配置文件 |
|------|------|--------|----------|
| dev | 本地开发 | 本地MariaDB | application-dev.yml |
| test | 集成测试 | 测试MariaDB | application-test.yml |
| staging | 预发布 | 预发布MariaDB | application-staging.yml |
| prod | 生产 | 生产MariaDB主从 | application-prod.yml |
### 10.2 敏感配置管理
- 数据库密码、Redis密码、JWT密钥、腾讯云SecretKey等 **禁止硬编码**
- 使用环境变量注入:`SPRING_DATASOURCE_PASSWORD`, `JWT_SECRET`, `COS_SECRET_KEY`
- 生产环境密码定期轮换(每季度)
### 10.3 配置项清单
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `jwt.expiration` | Token过期时间 | 7200 |
| `jwt.refresh-expiration` | Refresh Token过期时间 | 604800 |
| `bluetooth.rssi-threshold` | 蓝牙信号阈值dBm | -70 |
| `bluetooth.distance-threshold` | ~~已废弃~~ 蓝牙不判断距离,连接即打卡 | — |
| `bluetooth.scan-timeout` | 蓝牙扫描超时(秒) | 3 |
| `permission.redis-channel` | 权限变更Redis频道名 | permission:changed |
| `async.pool.core-size` | 异步线程池核心线程数 | CPU核心数 |
| `async.pool.max-size` | 异步线程池最大线程数 | CPU核心数*2 |
| `upload.max-size` | 文件上传大小限制MB | 20 |
| `cos.bucket-name` | 腾讯云COS存储桶名称 | — |
| `backup.full-cron` | 全量备份cron | 0 2 * * ? |
| `backup.incr-interval-hours` | 增量备份间隔(小时) | 4 |
---
> **本文档为内部开发标准,所有开发人员必须严格按照此标准执行。如有疑问或需要调整,需经技术负责人审批。**