ether-docs/02-DESIGN/overview/OVERVIEW-DESIGN.md

1336 lines
52 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ether 物业管理系统 - 概要设计文档
**文档版本**: v1.0
**编制日期**: 2026-05-18
**数据来源**: REVERSE-AUTH/MDM/ASSET/OPS/FINANCE 反推设计文档 + BEST-PRACTICES-REPORT + CONSISTENCY-REPORT
**系统版本**: ether-pms v1.x (Spring Boot 3.x)
---
## 一、系统架构设计
### 1.1 总体架构
Ether 物业管理系统采用**单体模块化**架构,后端为 Spring Boot 3.x 单体应用,通过 Maven 多模块组织业务边界;前端为 Vue3 SPA 应用,按角色拆分为三套独立前端。
**技术栈总览**
| 层次 | 技术选型 | 说明 |
|------|---------|------|
| 后端框架 | Spring Boot 3.x + Spring Security 6 | Java 17+Servlet 容器 |
| 持久层 | Spring Data JPA + Hibernate | ORM 框架,自动建表 |
| 数据库 | PostgreSQL 15+ | JSONB/UUID/ltree 扩展 |
| 缓存 | Redis | 登录锁定、Session、热数据 |
| 认证 | JWT (HMAC-SHA256) | 无状态 Token 认证 |
| 前端框架 | Vue3 + TypeScript + Vite | Composition API + `<script setup>` |
| UI 组件库 | Ant Design Vue 4.x | 统一视觉风格 |
| 状态管理 | Pinia | Composition API 风格 |
| HTTP 客户端 | Axios | 请求/响应拦截器封装 |
| 构建工具 | Maven (后端) / npm (前端) | 多模块构建 |
**架构图**
```
┌──────────────────────────────────────────────────────────────────────┐
│ 客户端层 │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ ether-admin │ │ether-app- │ │ether-app- │ │
│ │ (管理后台) │ │ employee │ │ owner │ │
│ │ :5175 │ │ (员工H5) │ │ (业主H5) │ │
│ │ Vue3+AntD │ │ :5174 │ │ :5176 │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └─────────────────┼─────────────────┘ │
│ │ RESTful API (JSON) │
│ │ Authorization: Bearer {JWT} │
│ │ X-Project-ID: {projectId} │
└───────────────────────────┼──────────────────────────────────────────┘
┌───────────────────────────┼──────────────────────────────────────────┐
│ 后端服务层 (ether-pms :8080) │
│ │ │
│ ┌────────────────────────┼────────────────────────────────────┐ │
│ │ Spring Security Filter Chain │ │
│ │ JwtAuthenticationFilter → LoginAttemptFilter → ... │ │
│ └────────────────────────┼────────────────────────────────────┘ │
│ │ │
│ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │module- │ │module- │ │module- │ │module- │ │module- │ │
│ │common │ │auth │ │mdm │ │asset │ │wo │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │公共工具│ │认证授权│ │主数据 │ │设备资产│ │运维工单│ │
│ │异常/响应│ │用户/角色│ │项目/空间│ │设备/健康│ │工单/维保│ │
│ └────────┘ └────────┘ └────────┘ └────────┘ └────────┘ │
│ │ │
│ ┌────────────────────────┼────────────────────────────────────┐ │
│ │ JPA / Hibernate / Repository │ │
│ └────────────────────────┼────────────────────────────────────┘ │
│ │ │
└───────────────────────────┼──────────────────────────────────────────┘
┌───────────────────────────┼──────────────────────────────────────────┐
│ 数据层 │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ PostgreSQL │ │ Redis │ │
│ │ 15+ │ │ │ │
│ │ JSONB/UUID │ │ 登录锁定 │ │
│ │ B-tree/GIN │ │ Token缓存 │ │
│ └──────────────┘ └──────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
```
### 1.2 模块划分
| 模块 | 职责 | 核心实体 | API 前缀 |
|------|------|---------|---------|
| **module-common** | 公共工具、异常体系、统一响应、基础配置 | ErrorCode、ApiResponse | — |
| **module-auth** | 身份认证、用户管理、RBAC 权限、审计日志 | User、Role、Permission、Dept、AuditLog | `/api/auth` |
| **module-mdm** | 项目管理、空间节点、巡检标准、备件库存、能耗计量 | Project、SpaceNode、InspectionItem、SparePart、EnergyMeter | `/api/mdm`、`/api/ops` |
| **module-asset** | 设备台账、健康评分、故障历史、归属主体 | Equipment、EquipmentElevator/Hvac/Fire/Energy、EquipmentHealthScore | `/api/asset` |
| **module-wo** | 工单管理、维保计划、维保任务、巡检模板 | WorkOrder、MaintenancePlan、MaintenanceTask、InspectionTemplate | `/api/wo`、`/api/ops` |
| **module-finance** | 收费项目、账单管理、支付记录(**待实现** | FeeItem、FeeBill、FeePayment未实现 | `/api/finance`(待定) |
**模块依赖关系**
```
module-common ← module-auth ← module-mdm ← module-asset
↑ ↑ ↑
└──────────────┴────────────┘
module-wo
```
- module-common 是所有模块的基础依赖
- module-auth 提供用户/权限基础数据,被其他业务模块引用
- module-mdm 提供项目/空间基础数据,被 asset/wo 模块引用
- module-asset 和 module-wo 存在交叉引用(设备-工单关联)
### 1.3 前后端交互架构
**认证流程**
```
1. 客户端 POST /api/auth/login {username, password}
2. 后端验证 → 生成 JWT Token含 userId/username/roles
3. 客户端存储 Token → 后续请求 Header: Authorization: Bearer {token}
4. 后端 JwtAuthenticationFilter 拦截 → 验证签名和过期 → 设置 SecurityContext
```
**项目隔离机制**
```
1. 登录后获取用户项目列表 GET /api/auth/users/{id}/projects
2. 用户选择项目 → 后续请求携带 X-Project-ID Header
3. 后端 ProjectContextInterceptor 拦截 → 设置 ThreadLocal
4. 业务层 DataScopeService 过滤数据 → 按 projectId 限定数据范围
```
**统一响应格式**
```json
{
"code": 0,
"message": "success",
"data": { ... }
}
```
**错误响应格式**
```json
{
"code": 1001,
"message": "用户名或密码错误",
"data": null
}
```
**错误码分段规则**
| 段号 | 模块 | 示例 |
|------|------|------|
| 1xxx | 认证 | 1001 用户名或密码错误 |
| 2xxx | 用户 | 2001 用户不存在 |
| 3xxx | 角色 | 3001 角色代码已存在 |
| 4xxx | 权限 | 4001 权限代码已存在 |
| 5xxx | 项目 | 5001 项目编码已存在 |
| 6xxx | 空间/能耗 | 6101 仪表不存在 |
| 7xxx | 文件 | 7001 文件格式不支持 |
### 1.4 部署架构
| 组件 | 端口 | 部署方式 | 说明 |
|------|------|---------|------|
| ether-pms | 8080 | JAR 包部署 | 后端单体服务 |
| ether-admin | 5175 | Nginx 静态托管 | 管理后台前端 |
| ether-app-employee | 5174 | Nginx 静态托管 | 员工 H5 前端 |
| ether-app-owner | 5176 | Nginx 静态托管 | 业主 H5 前端 |
| ether-app-commercial | 5177 | Nginx 静态托管 | 商办 H5 前端 |
| PostgreSQL | 5432 | 独立部署 | 主数据库 |
| Redis | 6379 | 独立部署 | 缓存/登录锁定 |
**启动脚本**:项目根目录提供 `start-services.sh` / `stop-services.sh` 统一管理服务启停。
---
## 二、业务域划分与边界
### 2.1 六大业务域定义
| 域编号 | 域名称 | 核心职责 | 对应模块 | 核心实体数 |
|--------|--------|---------|---------|-----------|
| D1 | 身份与权限域 | 用户认证、RBAC 权限、项目隔离、审计日志 | module-auth | 14 |
| D2 | 空间与项目域 | 项目管理、空间节点树、项目配置、项目统计 | module-mdm | 13 |
| D3 | 设备与资产域 | 设备台账、专业扩展、健康评分、故障历史、归属管理 | module-asset | 8 |
| D4 | 运营与服务域 | 工单管理、维保计划/任务、巡检模板、备件库存 | module-wo + module-mdm(部分) | 6 |
| D5 | 财务与收费域 | 收费项目、账单管理、支付记录、能耗计费 | module-finance(待实现) | 0(待实现) |
| D6 | 前端交互域 | 管理后台、员工端、业主端、商办端 | ether-admin + ether-app-* | — |
### 2.2 域间依赖关系图
```mermaid
graph TD
D1[D1 身份与权限域<br/>module-auth]
D2[D2 空间与项目域<br/>module-mdm]
D3[D3 设备与资产域<br/>module-asset]
D4[D4 运营与服务域<br/>module-wo]
D5[D5 财务与收费域<br/>module-finance]
D6[D6 前端交互域<br/>ether-admin/apps]
D1 -->|用户/角色/权限| D2
D1 -->|用户/角色/权限| D3
D1 -->|用户/角色/权限| D4
D1 -->|用户/角色/权限| D5
D2 -->|项目/空间节点| D3
D2 -->|项目/空间节点| D4
D2 -->|项目/空间节点| D5
D3 -->|设备信息| D4
D3 -->|设备健康数据| D5
D4 -->|工单费用| D5
D1 -.->|API调用| D6
D2 -.->|API调用| D6
D3 -.->|API调用| D6
D4 -.->|API调用| D6
D5 -.->|API调用| D6
```
**依赖说明**
| 依赖关系 | 依赖内容 | 实现方式 |
|---------|---------|---------|
| D2 → D1 | 项目成员管理需要用户数据 | UserProject 关联 + ProjectStaff 扩展 |
| D3 → D2 | 设备关联空间节点 | Equipment.spaceNodeId → SpaceNode.id |
| D4 → D2 | 工单关联项目和空间 | WorkOrder.projectId / spaceId |
| D4 → D3 | 工单关联设备 | WorkOrder.equipmentId → Equipment.id |
| D4 → D3 | 维保任务完成后更新设备 | MaintenanceTask → Equipment 联动更新 |
| D5 → D2 | 账单关联项目和空间 | FeeBill.projectId / spaceNodeId |
| D5 → D3 | 能耗费用对接设备 | EnergyConsumption → Equipment |
### 2.3 域间数据流图
```mermaid
flowchart LR
subgraph D1[身份与权限域]
User[User]
Role[Role]
end
subgraph D2[空间与项目域]
Project[Project]
SpaceNode[SpaceNode]
EnergyMeter[EnergyMeter]
end
subgraph D3[设备与资产域]
Equipment[Equipment]
HealthScore[HealthScore]
FailureHistory[FailureHistory]
end
subgraph D4[运营与服务域]
WorkOrder[WorkOrder]
MaintenancePlan[MaintenancePlan]
MaintenanceTask[MaintenanceTask]
SparePart[SparePart]
end
subgraph D5[财务与收费域]
FeeItem[FeeItem]
FeeBill[FeeBill]
FeePayment[FeePayment]
end
User -->|项目成员| Project
Project -->|1:N| SpaceNode
SpaceNode -->|spaceNodeId| Equipment
Equipment -->|equipmentId| WorkOrder
Equipment -->|equipmentId| MaintenanceTask
MaintenancePlan -->|planId| MaintenanceTask
MaintenanceTask -->|完成后联动| Equipment
WorkOrder -->|relatedOrderId| SparePart
EnergyMeter -->|费用计算| FeeBill
Equipment -->|健康数据| HealthScore
Equipment -->|故障记录| FailureHistory
FailureHistory -->|关联工单| WorkOrder
```
### 2.4 域间接口契约
| 接口 | 提供方 | 消费方 | 契约内容 |
|------|--------|--------|---------|
| 用户项目列表 | D1 (auth) | D2 (mdm) | `GET /api/auth/users/{id}/projects``List<UserProject>` |
| 项目成员管理 | D2 (mdm) | D1 (auth) | `GET/POST/DELETE /api/mdm/projects/{id}/members` |
| 空间节点查询 | D2 (mdm) | D3 (asset) | Equipment.spaceNodeId → SpaceNode.id通过 JPA 关联 |
| 设备查询 | D3 (asset) | D4 (wo) | WorkOrder.equipmentId → Equipment.id通过 JPA 关联 |
| 维保完成后设备更新 | D4 (wo) | D3 (asset) | MaintenanceTask 完成时更新 Equipment.maintenanceVendor/nextInspectionDate |
| 备件出库关联工单 | D4 (wo) | D2 (mdm) | SparePartRecord.relatedOrderId → WorkOrder.id |
| 能耗数据对接账单 | D2 (mdm) | D5 (finance) | EnergyConsumption.amount → FeeBill 数据来源(待实现) |
---
## 三、核心技术实现路径
### 3.1 多租户数据隔离
**隔离策略**:共享数据库 + projectId 字段隔离
**实现机制**
| 层次 | 机制 | 实现细节 |
|------|------|---------|
| 数据层 | projectId 字段 | 所有业务表均含 project_id 列,索引覆盖 |
| 请求层 | X-Project-ID Header | 前端每次请求携带当前项目 ID |
| 拦截层 | ProjectContextInterceptor | 拦截请求,将 projectId 存入 ThreadLocal |
| 服务层 | DataScopeService | 提供 canAccessAllData()、getPermittedProjectIds() 等判断方法 |
| 查询层 | Repository 方法 | findByProjectIdAndXxx() 系列方法,强制带项目条件 |
**数据范围过滤**
```java
// 四级数据范围
ALL 不做数据过滤可查看所有项目数据
PROJECT 过滤 project_id = 当前项目
DEPARTMENT 过滤 project_id + dept_id = 用户部门
SELF 过滤 assigned_to / creator = 当前用户
```
**已知不足与改进方向**
- 当前 DataScopeService 仅提供判断方法,未实现 SQL 自动注入,数据过滤依赖业务层手动调用,存在遗漏风险
- 改进方案:通过 JPA Specification 或 MyBatis Interceptor 自动拼接数据过滤条件
### 3.2 RBAC 权限模型
**模型结构**User ←M2M→ Role ←M2M→ Permission
**三级角色体系**
| 角色类型 | 枚举值 | 说明 | 数据范围 |
|---------|--------|------|---------|
| 系统级 | SYSTEM | 跨项目全局角色 | ALL |
| 项目级 | PROJECT | 绑定特定项目的角色 | PROJECT |
| 部门级 | DEPARTMENT | 部门范围角色 | DEPARTMENT |
**双层角色分配**
```
用户所有角色 = 用户直接角色(auth_user_role) 项目员工角色(ProjectStaffRole)
```
- 用户直接角色:通过 `auth_user_role` 中间表关联,用户创建时或 UserController.assignRoles 分配
- 项目员工角色:通过 `ProjectStaffRole` 关联,项目成员管理时分配
**权限类型**
| 类型 | 说明 | 示例 |
|------|------|------|
| MENU | 菜单权限 | 系统管理、设备管理 |
| BUTTON | 按钮权限 | 新增设备、删除工单 |
| API | 接口权限 | POST /api/asset/equipment |
**权限代码格式**`module:resource:action`,如 `asset:equipment:create`
**四级数据范围**
| 数据范围 | 编码 | 过滤逻辑 |
|---------|------|---------|
| 全部数据 | ALL | 不做数据过滤 |
| 本项目数据 | PROJECT | WHERE project_id = ? |
| 本部门数据 | DEPARTMENT | WHERE project_id = ? AND dept_id = ? |
| 仅本人数据 | SELF | WHERE assigned_to = ? OR created_by = ? |
### 3.3 树形结构管理
**适用实体**SpaceNode空间节点、Dept部门、SparePartCategory备件分类
**实现方案**treePath 字符串路径 + parentId 自引用
**核心字段**
| 字段 | 类型 | 说明 |
|------|------|------|
| parentId | UUID | 父节点 IDNULL=顶级) |
| treePath | String(1000) | 物理路径,格式 `id1.id2.id3` |
| treePathName | String(1000) | 名称路径,格式 `项目/楼栋/单元/房间` |
| level | Integer | 层级深度,根节点为 0 |
**SpaceNode 空间层级**
```
项目 (Project)
├── 楼栋 (BUILDING) ← NodeCategory.BUILDING, level=1
│ ├── 单元 (UNIT) ← NodeCategory.BUILDING, level=2
│ │ ├── 楼层 (FLOOR) ← NodeCategory.BUILDING, level=3
│ │ │ └── 房间 (ROOM) ← NodeCategory.BUILDING, level=4
│ │ └── 房间 (ROOM) ← 可跳过楼层直接挂房间
│ └── 公共用房 (PUBLIC_ROOM)
├── 商铺 (SHOP) ← NodeCategory.BUILDING, level=2
├── 车库 (GARAGE) ← NodeCategory.PARKING, level=1
│ ├── 停车区域 (PARKING_AREA) ← level=2
│ │ └── 车位 (PARKING_SPACE) ← level=3
├── 设备房 (EQUIPMENT_ROOM) ← NodeCategory.FACILITY, level=1
├── 公共区域 (PUBLIC_AREA) ← NodeCategory.AREA, level=1
└── 绿化区域 (GREEN_AREA) ← NodeCategory.AREA, level=1
```
**查询模式**
| 查询需求 | 实现方式 | SQL 示例 |
|---------|---------|---------|
| 查子节点 | parentId 查询 | `WHERE parent_id = ?` |
| 查所有子孙 | treePath LIKE | `WHERE tree_path LIKE 'parentPath.%'` |
| 查祖先链 | treePath 解析 | 应用层拆分 treePath 获取祖先 ID 列表 |
| 构建完整树 | 扁平列表 + 递归 | Controller 层递归构建树形 VO |
**索引设计**
```sql
idx_space_node_tree_path (tree_path) -- 路径前缀查询
idx_sn_project_parent (project_id, parent_id) -- 项目+父节点
idx_sn_project_type (project_id, node_type) -- 项目+类型
```
**已知不足**treePath LIKE 查询在大数据量下性能不佳,未使用 PostgreSQL ltree 扩展或闭包表方案。后续可评估升级。
### 3.4 设备扩展表模式
**设计原则**:主表存储公共字段,扩展表存储专业参数,通过 equipmentType 决定扩展表。
**模式结构**
```
Equipment (主表, ~40个公共字段)
├── EquipmentElevator (电梯扩展) ← equipment_id UNIQUE
├── EquipmentHvac (暖通扩展) ← equipment_id UNIQUE
├── EquipmentFire (消防扩展) ← equipment_id UNIQUE
└── EquipmentEnergy (能源计量扩展) ← equipment_id UNIQUE
```
**设备类型与扩展表映射**
| 设备类型 | 枚举值 | 扩展表 | 无扩展表时 |
|---------|--------|--------|-----------|
| 电梯系统 | ELEVATOR | EquipmentElevator | — |
| 暖通空调 | HVAC | EquipmentHvac | — |
| 消防系统 | FIRE_PROTECTION | EquipmentFire | — |
| 能源计量 | ENERGY_METER | EquipmentEnergy | — |
| 给排水系统 | PLUMBING | — | 使用 attributes JSON |
| 电气系统 | ELECTRICAL | — | 使用 attributes JSON |
| 弱电系统 | SECURITY | — | 使用 attributes JSON |
| 景观绿化 | LANDSCAPE | — | 使用 attributes JSON |
| 厨余设备 | KITCHEN | — | 使用 attributes JSON |
| 其他设备 | OTHER | — | 使用 attributes JSON |
**扩展表服务接口模式**
```java
public interface EquipmentElevatorService {
Optional<EquipmentElevator> getByEquipmentId(UUID equipmentId);
EquipmentElevator saveOrUpdate(EquipmentElevator elevator);
}
```
**扩展表 API 路径**
```
GET /api/asset/equipment/{id}/elevator → 获取电梯扩展
PUT /api/asset/equipment/{id}/elevator → 更新电梯扩展
GET /api/asset/equipment/{id}/hvac → 获取暖通扩展
PUT /api/asset/equipment/{id}/hvac → 更新暖通扩展
GET /api/asset/equipment/{id}/fire → 获取消防扩展
PUT /api/asset/equipment/{id}/fire → 更新消防扩展
GET /api/asset/equipment/{id}/energy → 获取能源扩展
PUT /api/asset/equipment/{id}/energy → 更新能源扩展
```
**已知问题**module-mdm 的 SpaceNode 也内嵌了设备扩展字段isEquipment 标记),与 module-asset 的独立 Equipment 实体形成双体系并存,需统一。
### 3.5 工单状态机
**WorkOrder 状态机6 状态)**
```
┌─────────────┐
│ PENDING │ ← 创建工单(默认状态)
│ (待分配) │
└──────┬──────┘
│ assign (派单)
┌─────────────┐
│ ASSIGNED │ ← 分配负责人/服务商
│ (已派单) │
└──────┬──────┘
│ start (开始执行)
┌─────────────┐
│ IN_PROGRESS │ ← 记录 actualStart
│ (执行中) │
└──────┬──────┘
│ complete (完成)
┌─────────────┐
│ COMPLETED │ ← 记录故障原因/解决方案/费用
│ (已完成) │
└──────┬──────┘
│ verify (验收)
┌─────────────┐
│ VERIFIED │ ← 记录验收人/评分/备注
│ (已验收) │
└─────────────┘
特殊: CANCELLED ← PENDING/ASSIGNED/IN_PROGRESS 可取消
COMPLETED/VERIFIED 不可取消
```
**状态流转约束**
| 当前状态 | 允许操作 | 下一状态 | 自动处理 |
|---------|---------|---------|---------|
| PENDING | assign | ASSIGNED | 设置 assignedTo/assignedVendor/assignedDate |
| ASSIGNED | start | IN_PROGRESS | 设置 actualStart = now() |
| IN_PROGRESS | complete | COMPLETED | 设置 actualEnd = now(),自动计算 actualHours |
| COMPLETED | verify | VERIFIED | 设置 verifiedBy/verifiedDate/rating |
| PENDING/ASSIGNED/IN_PROGRESS | cancel | CANCELLED | — |
**MaintenanceTask 状态机6 状态,与工单类似但有差异)**
| 差异点 | WorkOrder | MaintenanceTask |
|--------|-----------|-----------------|
| 完成方式 | 仅一种 complete | 两种complete简版+ complete-details详版 |
| 评分方式 | 验收时评分 | 验收时评分 + 独立 rate 接口 |
| 删除策略 | 物理删除 | 逻辑删除(设为 CANCELLED |
| 完成后联动 | 无 | 自动更新设备维保记录 |
**工单编号生成规则**
| 类型 | 格式 | 示例 |
|------|------|------|
| 工单 | WO-YYYYMMDD-XXXX | WO-20260518-0001 |
| 维保任务 | EQ-YYYYMMDD-XXXX | EQ-20260518-0001 |
**已知风险**:编号生成使用 findMaxWorkNoByPrefix 查询最大编号 +1并发场景可能生成重复编号需改用数据库序列或 Redis INCR。
### 3.6 健康评分算法 [Beta]
**评分公式**
```
健康度 = 基础分(100) - 故障扣分 - 维保扣分 - 年龄扣分
最低分 = 0不会为负数
```
**三维扣分规则**
| 扣分项 | 计算公式 | 参数 | 上限 |
|--------|----------|------|------|
| 故障扣分 | 故障次数(近30天) x 5 | FAILURE_DEDUCTION_PER_COUNT = 5 | 无上限 |
| 维保扣分 | (1 - 维保完成率) x 20 | MAINTENANCE_DEDUCTION_FACTOR = 20 | 20 分 |
| 年龄扣分 | 设备年龄(年) x 2 | AGE_DEDUCTION_PER_YEAR = 2 | 10 分 (MAX_AGE_DEDUCTION) |
**5 级健康等级**
| 等级 | 枚举值 | 分数范围 | 前端颜色 |
|------|--------|---------|---------|
| 优秀 | EXCELLENT | [90, 100) | 绿色 |
| 良好 | GOOD | [75, 90) | 青色 |
| 一般 | FAIR | [60, 75) | 橙色 |
| 较差 | POOR | [40, 60) | 红色 |
| 危急 | CRITICAL | [0, 40) | 红色 |
**MTBF 计算(平均故障间隔时间)**
```
MTBF = 运行时间(小时) / 故障次数
```
- 计算周期:默认 30 天,可自定义
- 运行时间:从第一个故障到最后一个故障的时间跨度
- 仅 1 次故障:使用默认期间天数 x 24 小时
- 无故障时返回 0
**MTTR 计算(平均修复时间)**
```
MTTR = 总修复时间(小时) / 修复次数
```
- 仅统计已完成修复的故障记录repairDurationHours 不为空)
- 无修复记录时返回 0
**已知问题**
1. calculateEquipmentAge() 错误使用 SpaceNode.maintenanceContractStart 而非 Equipment.installationDate
2. projectId 硬编码为全零 UUID `00000000-0000-0000-0000-000000000000`
3. 维保完成率固定返回 1.0TODO 标记)
4. 扣分系数5、20、2、10硬编码在代码中未提取为配置
**Beta → 正式演进路径**
| 阶段 | 时间 | 目标 |
|------|------|------|
| Beta当前 | 2026 Q2 | 修复已知 Bug提取配置项 |
| V1 | 2026 Q3 | 完善维保完成率计算,积累真实数据校准系数 |
| V2 | 2026 Q4 | 引入 IoT 数据,增加运行参数扣分维度 |
| V3 | 2027 Q1 | 机器学习模型,基于历史数据预测故障概率 |
### 3.7 审计日志
**记录方式**`@OperationLog` 注解 + AOP 切面
```java
@OperationLog(operation = "创建用户", module = "USER", action = AuditLog.ActionType.CREATE)
public User createUser(User user) { ... }
```
**异步持久化**:通过 `auditLogExecutor` 线程池异步保存,避免影响业务性能
**核心字段**
| 字段 | 说明 |
|------|------|
| userId / username | 操作人 |
| operation | 操作描述 |
| module | 模块标识USER/ROLE/PERMISSION/PROJECT/AUTH/DEPT |
| action | 操作类型CREATE/UPDATE/DELETE/QUERY/VIEW/LOGIN/LOGOUT/EXPORT/IMPORT/ASSIGN/REVOKE |
| targetType / targetId | 操作目标 |
| content | 操作内容 |
| params / result | 请求参数 / 操作结果 |
| executionTimeMs | 执行耗时 |
| status | SUCCESS / FAIL |
**查询窗口**:强制限制 30 天,超过 30 天的查询自动截断起始时间
**归档策略**90 天以上日志归档当前实现为直接删除TODO: 导出至对象存储保留 3-5 年)
**索引设计**
```sql
idx_audit_log_created_at (created_at)
idx_audit_log_user_id (user_id)
idx_audit_log_module (module)
idx_audit_log_action (action)
idx_al_user_createdat (user_id, created_at DESC)
```
**已知不足**
1. 审计日志可篡改(无防篡改机制),需改为只追加
2. 90 天归档实为删除,不符合合规要求(物业行业需保留 3-5 年)
3. 改进方案:数据库触发器禁止 UPDATE/DELETE + 90 天后导出至 OSS/S3
### 3.8 编码生成规则
| 实体 | 编码格式 | 生成方式 | 唯一性保障 |
|------|---------|---------|-----------|
| 项目编码 | 正则 `^[a-zA-Z0-9_-]+$` | 后端 generateCode() | 数据库 UNIQUE |
| 空间编码 | **未实现** | — | — |
| 设备编码 | equipmentCode | 创建时指定 | 数据库 UNIQUE |
| 工单编号 | WO-YYYYMMDD-XXXX | findMaxWorkNoByPrefix + 1 | 应用层(有并发风险) |
| 维保任务编号 | EQ-YYYYMMDD-XXXX | 同上 | 应用层(有并发风险) |
| 计划编码 | planCode | 创建时指定 | 数据库 UNIQUE |
| 备件编码 | sparePartCode | 创建时指定 | 数据库 UNIQUE |
| 计量点编码 | EM + yyyyMMddHHmmss | generateMeterCode() | 冲突时追加后缀 |
| 记录编码 | recordCode | 创建时指定 | 数据库 UNIQUE |
**改进方向**
1. 空间编码需实现自动生成规则(如 项目编码-楼栋号-单元号-房号)
2. 工单/任务编号改用数据库序列或 Redis INCR 保障并发安全
3. 统一编码生成服务,避免各模块各自实现
---
## 四、难点识别与应对
### 4.1 跨域业务流程的一致性保障
**难点描述**:维保任务完成后需联动更新设备信息(维保商、下次巡检日期),工单完成后需关联备件出库,能耗数据需对接账单生成。这些跨域操作需要保证数据一致性。
**应对方案**
| 方案 | 适用场景 | 实现方式 | 一致性级别 |
|------|---------|---------|-----------|
| 同步调用 + 事务 | 强一致性要求 | @Transactional 跨模块 Service 调用 | 强一致 |
| 事件驱动 + 最终一致性 | 弱一致性可接受 | Spring ApplicationEvent + 异步监听 | 最终一致 |
| 补偿事务 | 需要回滚能力 | Saga 模式,失败时执行补偿操作 | 最终一致 |
**当前实现**:维保任务完成后同步调用 EquipmentService 更新设备,异常容错(更新设备失败不影响工单完成)。
**改进计划**
1. 短期Q2 2026保持同步调用增加重试机制@Retryable
2. 中期Q3 2026引入 Spring ApplicationEvent关键操作发布领域事件
3. 远期Q4 2026评估引入消息队列RabbitMQ/Kafka解耦跨域通信
### 4.2 工单状态机的并发控制
**难点描述**:多个用户可能同时对同一工单执行状态变更操作(如同时派单、同时完成),需要保证状态流转的正确性和幂等性。
**应对方案**
| 机制 | 实现方式 | 说明 |
|------|---------|------|
| 乐观锁 | version 字段 + @Version | JPA 自动版本控制,更新时检查版本号 |
| 状态校验 | 业务层前置检查 | 状态变更前校验当前状态是否允许该操作 |
| 幂等性 | 幂等键 + 去重 | 重复请求返回当前状态而非报错 |
| 分布式锁 | Redis SETNX | 防止同一工单被并发操作 |
**当前实现**:仅业务层前置状态校验,无乐观锁和分布式锁。
**改进计划**
1. 为 WorkOrder 和 MaintenanceTask 添加 version 字段(@Version
2. 状态变更操作使用 Redis 分布式锁key: `work_order:lock:{id}`
3. 状态变更接口设计为幂等:重复操作返回当前状态
### 4.3 树形结构的高效查询
**难点描述**SpaceNode 使用 treePath 字符串路径(如 `uuid1.uuid2.uuid3`),查询子孙节点需 LIKE 匹配,大数据量下性能堪忧。
**应对方案**
| 方案 | 查询性能 | 维护成本 | 适用场景 |
|------|---------|---------|---------|
| treePath LIKE当前 | O(n) 全表扫描 | 低 | 数据量 < 1万 |
| PostgreSQL ltree 扩展 | O(log n) 索引扫描 | | 数据量 1-10万 |
| 闭包表 (Closure Table) | O(1) 直接查询 | 需额外表 | 数据量 > 10万 |
| 递归 CTE | O(depth) | 低 | 深度有限(< 10层 |
**当前实现**treePath LIKE + B-tree 索引
**改进计划**
1. 短期Q2 2026确保 treePath 索引存在添加 GIN 索引支持前缀查询
2. 中期Q3 2026评估迁移至 PostgreSQL ltree 扩展利用专用的 ltree 索引
3. 远期Q4 2026若数据量超过 10 万节点考虑闭包表方案
**递归 CTE 查询示例**当前可用的优化方案
```sql
WITH RECURSIVE space_tree AS (
SELECT * FROM mdm_space_node WHERE id = :rootId
UNION ALL
SELECT n.* FROM mdm_space_node n
JOIN space_tree st ON n.parent_id = st.id
)
SELECT * FROM space_tree;
```
### 4.4 健康评分的数据积累与算法迭代
**难点描述**健康评分算法当前为 Beta 扣分系数基于经验设定缺乏真实数据校准维保完成率固定为 1.0影响评分准确性
**应对方案**
| 阶段 | 目标 | 具体措施 |
|------|------|---------|
| Beta V1 | 修复 Bug + 提取配置 | 修正设备年龄计算projectId 硬编码提取扣分系数为 @ConfigurationProperties |
| V1 V2 | 数据校准 + 完善计算 | 实现维保完成率真实计算积累 3 个月数据后用线性回归校准系数 |
| V2 V3 | 引入 IoT + 预测模型 | 增加运行参数扣分维度基于历史数据训练故障预测模型 |
**配置化改进**
```yaml
# application.yml
equipment:
health:
failure-deduction-per-count: 5
maintenance-deduction-factor: 20
age-deduction-per-year: 2
max-age-deduction: 10
calculation-period-days: 30
default-inspection-cycle-days: 30
```
### 4.5 备件库存的并发出入库
**难点描述**多个工单可能同时使用同一备件导致库存超卖或数据不一致
**应对方案**
| 机制 | 实现方式 | 说明 |
|------|---------|------|
| 乐观锁 | currentStock + @Version | 出库时检查版本号冲突时重试 |
| 库存校验 | 出库前检查 currentStock >= quantity | 防止库存为负 |
| 事务隔离 | @Transactional(isolation = SERIALIZABLE) | 最高隔离级别,性能影响大 |
| Redis 原子操作 | DECRBY 命令 | 原子性扣减,性能最优 |
**当前实现**:出库时校验库存不能为负,但无乐观锁。
**改进计划**
1. 为 SparePart 添加 version 字段(@Version
2. 出库操作使用 Redis DECRBY 原子扣减,成功后异步同步到数据库
3. 引入库存预占机制:工单创建时预占库存,完成时确认扣减,取消时释放
### 4.6 能耗数据的 IoT 接入
**难点描述**当前能耗数据仅支持手动录入MANUALIoT 自动采集IOT枚举已定义但未实现对接。
**当前状态**
```java
public enum RecordMethod {
MANUAL, // 手动录入 — 已实现
IOT // IoT自动采集 — 枚举已定义,对接未实现
}
```
**扩展路径**
| 阶段 | 目标 | 技术方案 |
|------|------|---------|
| Phase 1当前 | 手动录入 | 前端表单 + 后端 API |
| Phase 2 | IoT 数据接入 | MQTT Broker + Spring Integration 消费消息 |
| Phase 3 | 实时监控 | WebSocket 推送 + 时序数据库TimescaleDB |
| Phase 4 | 智能告警 | 规则引擎 + 异常检测算法 |
**Phase 2 架构设计**
```
IoT 设备 → MQTT Broker → Spring Integration → EnergyConsumptionService.recordConsumption()
recordMethod = IOT
自动获取 previousReading
自动计算 consumption 和 amount
```
---
## 五、跨模块跨功能实现规范
### 5.1 API 设计规范
**路径前缀**
```
/api/{module}/{resource}
```
| 模块 | 路径前缀 | 示例 |
|------|---------|------|
| auth | /api/auth | /api/auth/users, /api/auth/roles |
| mdm | /api/mdm | /api/mdm/projects, /api/mdm/space-nodes |
| asset | /api/asset | /api/asset/equipment |
| wo | /api/wo | /api/wo/work-orders |
| ops | /api/ops | /api/ops/maintenance-tasks, /api/ops/energy |
**版本管理**(待实现):
```
当前: /api/{module}/{resource}
目标: /api/v1/{module}/{resource}
```
**分页规范**
```java
// 请求参数
GET /api/mdm/projects?page=0&size=20&sortBy=createdAt&sortDirection=DESC
// 响应格式
{
"code": 0,
"message": "success",
"data": {
"content": [...],
"totalElements": 100,
"totalPages": 5,
"number": 0,
"size": 20
}
}
```
**约束**所有列表接口必须支持分页禁止全量返回。WorkOrder 当前返回 `List<WorkOrder>` 全量数据需改造。
**错误码规范**
| 段号 | 模块 | 范围 |
|------|------|------|
| 1xxx | 认证 | 1000-1999 |
| 2xxx | 用户 | 2000-2999 |
| 3xxx | 角色 | 3000-3999 |
| 4xxx | 权限 | 4000-4999 |
| 5xxx | 项目 | 5000-5999 |
| 6xxx | 空间/能耗 | 6000-6999 |
| 7xxx | 文件 | 7000-7999 |
| 8xxx | 工单 | 8000-8999待分配 |
| 9xxx | 财务 | 9000-9999待分配 |
**统一响应封装**
```java
public class ApiResponse<T> {
private int code;
private String message;
private T data;
}
```
### 5.2 数据模型规范
**主键策略**
```java
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id; // 所有实体使用 UUID 主键
```
**软删除**
```java
private Boolean isDeleted = false; // 核心业务实体必须有此字段
// Repository 查询方法
findByIdAndIsDeletedFalse(UUID id);
findByProjectIdAndIsDeletedFalse(UUID projectId);
```
**约束**WorkOrder 当前使用物理删除,需统一改为逻辑删除。
**审计字段**
```java
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime updatedAt;
@Column(updatable = false)
private UUID createdBy;
private UUID updatedBy;
```
**约束**:所有实体必须有 createdAt 和 updatedAt 字段,使用 JPA Auditing 自动填充。
**JSONB 使用规范**
| 场景 | 字段类型 | 说明 |
|------|---------|------|
| 照片列表 | JSONB | `List<String>``List<EquipmentPhoto>` |
| 文档列表 | JSONB | `List<EquipmentDocument>` |
| 扩展属性 | JSONB | `Map<String, Object>` 或 String 存储 JSON |
| 检查项结果 | JSONB | 结构化 JSON 数组 |
**约束**SpaceNode.attributes 当前为 String(2000),需改为 JSONB 类型以支持 GIN 索引和原生 JSON 查询。
**枚举策略**
```java
// 数据库存储为字符串JPA 实体使用枚举类型
@Enumerated(EnumType.STRING)
private UserStatus status;
// 枚举定义
public enum UserStatus {
ACTIVE, LOCKED, DISABLED
}
```
**约束**:禁止使用 EnumType.ORDINAL统一使用 EnumType.STRING。
### 5.3 异常处理规范
**三层异常体系**
```
BusinessException (业务异常)
├── ErrorCode (错误码枚举)
└── GlobalExceptionHandler (全局异常处理器)
```
**BusinessException 使用规范**
```java
// 正确用法
throw new BusinessException(ErrorCode.USER_NOT_FOUND);
// 错误用法(禁止)
throw new RuntimeException("用户不存在");
```
**约束**WorkOrderServiceImpl 中存在 `throw new RuntimeException("工单不存在")`,需替换为 BusinessException + ErrorCode。
**GlobalExceptionHandler 处理规则**
| 异常类型 | HTTP 状态码 | 处理方式 |
|---------|-----------|---------|
| BusinessException | 200 (body 含错误码) | 返回 ApiResponse(code, message, null) |
| MethodArgumentNotValidException | 200 | 返回参数校验错误信息 |
| DataAccessException | 200 | 脱敏后返回数据库错误 |
| Exception | 200 | 通用异常兜底 |
**改进方向**:业务错误码 4xx/5xx 应映射为对应 HTTP 状态码,非标准码保持 200 但在 body 中体现。
### 5.4 权限控制规范
**注解式权限**
```java
@PreAuthorize("hasAuthority('asset:equipment:create')")
public Equipment createEquipment(Equipment equipment) { ... }
```
**数据范围过滤**
```java
// Service 层手动调用
if (!dataScopeService.canAccessAllData(currentUser)) {
List<UUID> permittedProjectIds = dataScopeService.getPermittedProjectIds(currentUser);
// 过滤查询结果
}
```
**改进方向**:通过 JPA Specification 自动拼接数据过滤条件,避免业务层遗漏。
**菜单动态渲染**(待实现):
```
1. 前端登录后请求 GET /api/auth/users/{id}/menus
2. 后端根据用户角色返回有权限的菜单列表
3. 前端动态生成路由和菜单
```
### 5.5 前后端协作规范
**TypeScript 类型同步**
```typescript
// 前端类型定义必须与后端枚举一致
// equipment.ts
export enum EquipmentType {
ELEVATOR = 'ELEVATOR',
HVAC = 'HVAC',
FIRE_PROTECTION = 'FIRE_PROTECTION',
// ... 与后端 EquipmentType 枚举完全一致
}
```
**约束**当前前端能源类型ELECTRICITY/WATER/GAS/CENTRAL_HEATING/CENTRAL_COOLING与后端LIGHTING/HVAC/POWER/SPECIAL/WATER/GAS不一致需统一。
**枚举一致性检查清单**
| 枚举 | 前端文件 | 后端位置 | 是否一致 |
|------|---------|---------|---------|
| EquipmentType | equipment.ts | Equipment.java | 需校验 |
| EnergyType | energy.ts | EnergyMeter.java | 不一致(需修复) |
| WorkOrderStatus | work-order.ts | WorkOrder.java | 需校验 |
| MaintenanceTaskStatus | maintenance.ts | MaintenanceTask.java | 不一致(需修复) |
| TriggerType | maintenance.ts | MaintenanceTask.java | 不一致(需修复) |
**API 调用封装**
```typescript
// src/api/xxx.ts
import request from '@/utils/request'
export function getEquipment(id: string) {
return request.get<ApiResponse<Equipment>>(`/api/asset/equipment/${id}`)
}
```
**约束**:维保计划存在两套前端 APImaintenance.ts + maintenance-plan.ts需合并为统一 API 文件。
### 5.6 测试规范
**TDD 开发流程**
```
1. 编写失败测试Red
2. 编写最小实现代码Green
3. 重构优化Refactor
```
**测试分层**
| 层次 | 框架 | 覆盖范围 | 当前状态 |
|------|------|---------|---------|
| 单元测试 | JUnit 5 + Mockito | Service 层业务逻辑 | 仅 EnergyMeterServiceTest |
| API 测试 | Spring MockMvc | Controller 层接口 | 缺失 |
| 集成测试 | @SpringBootTest | 跨模块交互 | 缺失 |
| E2E 测试 | Playwright/Cypress | 前端用户流程 | 缺失 |
**优先补充的单元测试**
1. WorkOrderService — 工单状态机流转
2. LoginService — 登录认证流程
3. EquipmentHealthService — 健康评分算法
4. SparePartService — 出入库库存校验
---
## 六、数据库设计概要
### 6.1 ER 图(核心实体关系)
```mermaid
erDiagram
User ||--o{ Role : "auth_user_role"
Role ||--o{ Permission : "auth_role_permission"
User ||--|| EnterpriseUser : "共享主键1:1"
User ||--|| ProjectStaff : "1:1"
User ||--|| Resident : "共享主键1:1"
ProjectStaff ||--o{ ProjectStaffRole : "1:N"
ProjectStaffRole }o--|| Role : "N:1"
Resident ||--o{ ResidentSpace : "1:N"
ResidentSpace }o--|| Space : "N:1"
User ||--o{ UserProject : "1:N"
UserProject }o--|| Project : "N:1"
Dept ||--o{ Dept : "parentId自引用"
Project ||--|| ProjectConfig : "1:1"
Project ||--|| ProjectStatistics : "1:1"
Project ||--o{ ProjectStatusHistory : "1:N"
Project ||--o{ SpaceNode : "1:N"
SpaceNode ||--o{ SpaceNode : "parentId自引用"
Equipment ||--o| EquipmentElevator : "1:1"
Equipment ||--o| EquipmentHvac : "1:1"
Equipment ||--o| EquipmentFire : "1:1"
Equipment ||--o| EquipmentEnergy : "1:1"
Equipment ||--o{ EquipmentHealthScore : "1:N"
Equipment ||--o{ EquipmentFailureHistory : "1:N"
Equipment }o--|| OwnershipEntity : "N:1"
Equipment }o--o| SpaceNode : "spaceNodeId"
MaintenancePlan ||--o{ MaintenanceTask : "1:N"
WorkOrder ||--o{ WorkOrderItem : "1:N"
WorkOrder }o--o| MaintenancePlan : "planId"
WorkOrder }o--o| Equipment : "equipmentId"
MaintenanceTask }o--o| Equipment : "equipmentId"
SparePartCategory ||--o{ SparePartCategory : "parentId自引用"
SparePartCategory ||--o{ SparePart : "1:N"
SparePart ||--o{ SparePartRecord : "1:N"
EnergyMeter ||--o{ EnergyConsumption : "1:N"
EnergyMeter }o--o| SpaceNode : "spaceNodeId"
```
### 6.2 表命名规范
**格式**`{模块前缀}_{实体名}`
| 模块前缀 | 示例 | 说明 |
|---------|------|------|
| auth_ | auth_user, auth_role, auth_permission | 认证授权模块 |
| mdm_ | mdm_project, mdm_space_node | 主数据模块 |
| asset_ | asset_equipment, asset_equipment_elevator | 设备资产模块 |
| ops_ | ops_work_order, ops_maintenance_plan | 运维工单模块 |
| fin_ | fin_fee_item, fin_fee_bill | 财务模块(待实现) |
| sys_ | sys_audit_log, sys_config | 系统级表 |
**列命名规范**
- 使用 snake_case`project_id`、`created_at`、`is_deleted`
- 外键列:`{关联实体}_id``equipment_id`、`space_node_id`
- 布尔列:`is_` 前缀:`is_deleted`、`is_equipment`
- 时间列:`_at` 后缀:`created_at`、`updated_at`
- 日期列:`_date` 后缀:`installation_date`、`next_inspection_date`
### 6.3 索引策略
**B-tree 索引**(等值查询、范围查询、排序):
| 表 | 索引列 | 用途 |
|----|--------|------|
| ops_work_order | (project_id, status) | 按项目+状态查询工单 |
| ops_work_order | (status, created_at) | 按状态+时间查询 |
| ops_work_order | (created_at DESC) | 时间倒序 |
| asset_equipment | (project_id, status) | 按项目+状态查询设备 |
| asset_equipment | (project_id, equipment_type) | 按项目+类型查询设备 |
| asset_equipment | (equipment_code) UNIQUE | 编码唯一 |
| mdm_space_node | (project_id, parent_id) | 项目+父节点 |
| mdm_space_node | (project_id, node_type) | 项目+类型 |
| mdm_space_node | (tree_path) | 路径前缀查询 |
| ops_equipment_failure_history | (equipment_id, failure_time DESC) | 设备故障时间线 |
| sys_audit_log | (user_id, created_at DESC) | 用户操作时间线 |
**GIN 索引**JSONB 查询,待添加):
```sql
CREATE INDEX idx_equipment_attributes ON asset_equipment USING GIN (attributes);
CREATE INDEX idx_equipment_photos ON asset_equipment USING GIN (photos);
CREATE INDEX idx_space_node_attributes ON mdm_space_node USING GIN (attributes);
```
**JSONB 索引使用场景**
| 表 | 字段 | 查询场景 |
|----|------|---------|
| asset_equipment | attributes | 按扩展属性筛选设备 |
| asset_equipment | photos | 按照片类型查询 |
| ops_maintenance_task | parts_used | 按备件 ID 查询使用该备件的工单 |
| mdm_inspection_record | items | 按检查项结果查询 |
### 6.4 数据迁移策略
**工具选型**Flyway
**迁移脚本命名规范**
```
V{版本号}__{描述}.sql
示例:
V1__init_auth_tables.sql
V2__init_mdm_tables.sql
V3__init_asset_tables.sql
V4__init_ops_tables.sql
V5__add_equipment_health_score.sql
V6__add_space_node_indexes.sql
```
**当前状态**:未使用 Flyway依赖 JPA 自动建表ddl-auto: update
**改进计划**
1. 短期:在开发环境继续使用 JPA 自动建表
2. 中期:引入 Flyway将现有 schema 导出为初始迁移脚本
3. 长期:生产环境禁止 ddl-auto: update所有变更通过 Flyway 迁移脚本执行
---
## 七、技术选型与依赖
### 7.1 后端技术栈
| 技术 | 版本 | 用途 | 说明 |
|------|------|------|------|
| Spring Boot | 3.x | 应用框架 | Java 17+Servlet 容器 |
| Spring Security | 6.x | 安全框架 | JWT 认证 + RBAC 授权 |
| Spring Data JPA | 3.x | ORM 框架 | Hibernate 实现,自动建表 |
| Hibernate | 6.x | JPA 实现 | 实体映射、懒加载、审计 |
| MapStruct | — | 对象映射 | Entity ↔ DTO 转换 |
| Lombok | — | 代码简化 | @Data、@Builder、@RequiredArgsConstructor |
| BCrypt | — | 密码加密 | Spring Security PasswordEncoder |
| JJWT | — | JWT 工具 | Token 生成与验证 |
| Spring AOP | — | 切面编程 | 审计日志 @OperationLog |
| Spring Validation | — | 参数校验 | @NotNull、@Size、@Pattern |
| Spring Web | — | REST API | @RestController、@RequestMapping |
### 7.2 前端技术栈
| 技术 | 版本 | 用途 | 说明 |
|------|------|------|------|
| Vue | 3.x | 前端框架 | Composition API + `<script setup>` |
| TypeScript | 5.x | 类型系统 | 类型安全 |
| Ant Design Vue | 4.x | UI 组件库 | 统一视觉风格 |
| Pinia | 2.x | 状态管理 | Composition API 风格,支持持久化 |
| Vite | 5.x | 构建工具 | 快速 HMR |
| Axios | 1.x | HTTP 客户端 | 请求/响应拦截器封装 |
| Vue Router | 4.x | 路由管理 | 路由守卫 + 权限控制 |
| ECharts | 5.x | 图表库 | 健康评分趋势图 |
### 7.3 数据库
| 技术 | 版本 | 用途 | 说明 |
|------|------|------|------|
| PostgreSQL | 15+ | 主数据库 | JSONB、UUID、ltree 扩展 |
| JSONB | — | 半结构化数据 | 照片列表、文档列表、扩展属性、检查项结果 |
| UUID | — | 主键类型 | 所有实体主键使用 UUID |
| Redis | 7+ | 缓存 | 登录失败锁定、Token 缓存 |
**PostgreSQL 特性使用**
| 特性 | 使用场景 | 当前状态 |
|------|---------|---------|
| JSONB | Equipment.photos/documents/attributes、InspectionRecord.items/problems | 部分使用SpaceNode.attributes 降级为 String |
| UUID | 所有实体主键 | 已使用 |
| ltree | 空间树形结构 | 未使用(使用 treePath 字符串替代) |
| GIN 索引 | JSONB 字段查询 | 未使用(待添加) |
| PostGIS | 地图空间查询 | 未使用 |
### 7.4 开发工具
| 工具 | 用途 | 说明 |
|------|------|------|
| Maven | 后端构建 | 多模块项目管理 |
| npm | 前端构建 | 依赖管理 |
| Git | 版本控制 | 分支管理 |
| Flyway | 数据库迁移 | 待引入 |
| SpringDoc/OpenAPI | API 文档 | 待引入 |
---
## 附录 A实现状态总览
| 功能模块 | 实现状态 | 核心实体 | 说明 |
|---------|---------|---------|------|
| 用户管理 | 已实现 | User/EnterpriseUser/ProjectStaff/Resident | 4 种用户类型扩展 |
| 角色权限 | 已实现 | Role/Permission/ProjectStaffRole | 三级角色 + 四级数据范围 |
| 部门管理 | 已实现 | Dept | 树形结构5 种部门类型 |
| 项目管理 | 已实现 | Project/ProjectConfig/ProjectStatistics | 状态流转 + 配置 + 统计 |
| 空间节点 | 已实现 | SpaceNode | 统一空间模型 + 设备扩展字段 |
| 设备台账 | 已实现 | Equipment + 4 张扩展表 | 主表 + 扩展表模式 |
| 健康评分 | 已实现(Beta) | EquipmentHealthScore | MTBF/MTTR + 三维扣分 |
| 故障历史 | 已实现 | EquipmentFailureHistory | 4 级故障 + 4 种修复结果 |
| 归属管理 | 已实现 | OwnershipEntity | 4 种归属 + 3 种主体 |
| 工单管理 | 已实现 | WorkOrder/WorkOrderItem | 6 状态状态机 |
| 维保计划 | 已实现 | MaintenancePlan | 周期性维保调度 |
| 维保任务 | 已实现 | MaintenanceTask | 6 状态 + 自动优先级判定 |
| 巡检标准 | 已实现 | InspectionItem/InspectionTemplate | 标准项库 + 模板管理 |
| 巡检记录 | 已实现 | InspectionRecord | 签到 + JSONB 结果 |
| 备件库存 | 已实现 | SparePart/SparePartCategory/SparePartRecord | 出入库 + 低库存预警 |
| 能耗计量 | 已实现 | EnergyMeter/EnergyConsumption | 手动录入 + 简单费用计算 |
| 审计日志 | 已实现 | AuditLog | AOP + 异步 + 30 天窗口 |
| 系统配置 | 已实现 | SysConfig | 键值对配置 |
| 消息通知 | **未实现** | — | NotificationChannel/Template/Rule/History |
| 收费项目 | **未实现** | — | FeeItem |
| 账单管理 | **未实现** | — | FeeBill |
| 支付记录 | **未实现** | — | FeePayment |
| 设备二维码 | **未实现** | — | 原需求有但未实现 |
| IoT 集成 | **未实现** | — | 枚举已定义,对接未实现 |
| 地图服务 | **未实现** | — | PostGIS + 高德地图 |
| SLA 管理 | **未实现** | — | 响应时间/处理时间/超时升级 |
## 附录 B关键风险与优先行动
| 优先级 | 风险 | 行动项 | 预估工作量 |
|--------|------|--------|-----------|
| P0 | 财务域核心功能完全缺失 | 创建 module-finance实现 FeeItem/FeeBill/FeePayment | 5 天 |
| P0 | 消息通知系统完全缺失 | 实现 NotificationChannel/Template/Rule/History | 8 天 |
| P0 | 工单全量查询 OOM 风险 | 改为分页查询 | 1 天 |
| P0 | 健康评分算法 Bug | 修正设备年龄计算和 projectId 硬编码 | 1 天 |
| P1 | 工单状态机缺少挂起/退回 | 增加 SUSPENDED/RETURNED 状态 | 3 天 |
| P1 | 工单流转记录缺失 | 实现 WorkOrderFlow | 2 天 |
| P1 | 前后端枚举不一致 | 统一能源类型/维保状态/触发类型 | 1 天 |
| P1 | 权限相关端点缺失 | 实现权限树/权限校验/用户菜单 | 3 天 |
| P2 | API 无版本管理 | 引入 /api/v1/ 前缀 | 3 天 |
| P2 | SpaceNode.attributes 非 JSONB | 改为 JSONB + GIN 索引 | 2 天 |
| P2 | 审计日志可篡改 | 改为只追加 + 归档而非删除 | 2 天 |
| P2 | 设备模型双体系并存 | 统一 MDM SpaceNode 内嵌设备与 ASSET Equipment | 3 天 |
---
> **文档说明**:本概要设计文档基于 REVERSE-AUTH/MDM/ASSET/OPS/FINANCE 五份反推设计文档、BEST-PRACTICES-REPORT 行业最佳实践评估报告、CONSISTENCY-REPORT 需求一致性评估报告综合编制,反映 2026-05-18 代码库状态。财务域D5核心功能标注为"待实现",需优先启动开发。