52 KiB
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 限定数据范围
统一响应格式:
{
"code": 0,
"message": "success",
"data": { ... }
}
错误响应格式:
{
"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 域间依赖关系图
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 域间数据流图
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() 系列方法,强制带项目条件 |
数据范围过滤:
// 四级数据范围
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 | 父节点 ID(NULL=顶级) |
| 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 |
索引设计:
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 |
扩展表服务接口模式:
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
已知问题:
- calculateEquipmentAge() 错误使用 SpaceNode.maintenanceContractStart 而非 Equipment.installationDate
- projectId 硬编码为全零 UUID
00000000-0000-0000-0000-000000000000 - 维保完成率固定返回 1.0(TODO 标记)
- 扣分系数(5、20、2、10)硬编码在代码中,未提取为配置
Beta → 正式演进路径:
| 阶段 | 时间 | 目标 |
|---|---|---|
| Beta(当前) | 2026 Q2 | 修复已知 Bug,提取配置项 |
| V1 | 2026 Q3 | 完善维保完成率计算,积累真实数据校准系数 |
| V2 | 2026 Q4 | 引入 IoT 数据,增加运行参数扣分维度 |
| V3 | 2027 Q1 | 机器学习模型,基于历史数据预测故障概率 |
3.7 审计日志
记录方式:@OperationLog 注解 + AOP 切面
@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 年)
索引设计:
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)
已知不足:
- 审计日志可篡改(无防篡改机制),需改为只追加
- 90 天归档实为删除,不符合合规要求(物业行业需保留 3-5 年)
- 改进方案:数据库触发器禁止 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 |
改进方向:
- 空间编码需实现自动生成规则(如 项目编码-楼栋号-单元号-房号)
- 工单/任务编号改用数据库序列或 Redis INCR 保障并发安全
- 统一编码生成服务,避免各模块各自实现
四、难点识别与应对
4.1 跨域业务流程的一致性保障
难点描述:维保任务完成后需联动更新设备信息(维保商、下次巡检日期),工单完成后需关联备件出库,能耗数据需对接账单生成。这些跨域操作需要保证数据一致性。
应对方案:
| 方案 | 适用场景 | 实现方式 | 一致性级别 |
|---|---|---|---|
| 同步调用 + 事务 | 强一致性要求 | @Transactional 跨模块 Service 调用 | 强一致 |
| 事件驱动 + 最终一致性 | 弱一致性可接受 | Spring ApplicationEvent + 异步监听 | 最终一致 |
| 补偿事务 | 需要回滚能力 | Saga 模式,失败时执行补偿操作 | 最终一致 |
当前实现:维保任务完成后同步调用 EquipmentService 更新设备,异常容错(更新设备失败不影响工单完成)。
改进计划:
- 短期(Q2 2026):保持同步调用,增加重试机制(@Retryable)
- 中期(Q3 2026):引入 Spring ApplicationEvent,关键操作发布领域事件
- 远期(Q4 2026):评估引入消息队列(RabbitMQ/Kafka)解耦跨域通信
4.2 工单状态机的并发控制
难点描述:多个用户可能同时对同一工单执行状态变更操作(如同时派单、同时完成),需要保证状态流转的正确性和幂等性。
应对方案:
| 机制 | 实现方式 | 说明 |
|---|---|---|
| 乐观锁 | version 字段 + @Version | JPA 自动版本控制,更新时检查版本号 |
| 状态校验 | 业务层前置检查 | 状态变更前校验当前状态是否允许该操作 |
| 幂等性 | 幂等键 + 去重 | 重复请求返回当前状态而非报错 |
| 分布式锁 | Redis SETNX | 防止同一工单被并发操作 |
当前实现:仅业务层前置状态校验,无乐观锁和分布式锁。
改进计划:
- 为 WorkOrder 和 MaintenanceTask 添加 version 字段(@Version)
- 状态变更操作使用 Redis 分布式锁(key:
work_order:lock:{id}) - 状态变更接口设计为幂等:重复操作返回当前状态
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 索引
改进计划:
- 短期(Q2 2026):确保 treePath 索引存在,添加 GIN 索引支持前缀查询
- 中期(Q3 2026):评估迁移至 PostgreSQL ltree 扩展,利用专用的 ltree 索引
- 远期(Q4 2026):若数据量超过 10 万节点,考虑闭包表方案
递归 CTE 查询示例(当前可用的优化方案):
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 + 预测模型 | 增加运行参数扣分维度;基于历史数据训练故障预测模型 |
配置化改进:
# 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 命令 | 原子性扣减,性能最优 |
当前实现:出库时校验库存不能为负,但无乐观锁。
改进计划:
- 为 SparePart 添加 version 字段(@Version)
- 出库操作使用 Redis DECRBY 原子扣减,成功后异步同步到数据库
- 引入库存预占机制:工单创建时预占库存,完成时确认扣减,取消时释放
4.6 能耗数据的 IoT 接入
难点描述:当前能耗数据仅支持手动录入(MANUAL),IoT 自动采集(IOT)枚举已定义但未实现对接。
当前状态:
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}
分页规范:
// 请求参数
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(待分配) |
统一响应封装:
public class ApiResponse<T> {
private int code;
private String message;
private T data;
}
5.2 数据模型规范
主键策略:
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private UUID id; // 所有实体使用 UUID 主键
软删除:
private Boolean isDeleted = false; // 核心业务实体必须有此字段
// Repository 查询方法
findByIdAndIsDeletedFalse(UUID id);
findByProjectIdAndIsDeletedFalse(UUID projectId);
约束:WorkOrder 当前使用物理删除,需统一改为逻辑删除。
审计字段:
@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 查询。
枚举策略:
// 数据库存储为字符串,JPA 实体使用枚举类型
@Enumerated(EnumType.STRING)
private UserStatus status;
// 枚举定义
public enum UserStatus {
ACTIVE, LOCKED, DISABLED
}
约束:禁止使用 EnumType.ORDINAL,统一使用 EnumType.STRING。
5.3 异常处理规范
三层异常体系:
BusinessException (业务异常)
├── ErrorCode (错误码枚举)
└── GlobalExceptionHandler (全局异常处理器)
BusinessException 使用规范:
// 正确用法
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 权限控制规范
注解式权限:
@PreAuthorize("hasAuthority('asset:equipment:create')")
public Equipment createEquipment(Equipment equipment) { ... }
数据范围过滤:
// 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 类型同步:
// 前端类型定义必须与后端枚举一致
// 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 调用封装:
// src/api/xxx.ts
import request from '@/utils/request'
export function getEquipment(id: string) {
return request.get<ApiResponse<Equipment>>(`/api/asset/equipment/${id}`)
}
约束:维保计划存在两套前端 API(maintenance.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 | 前端用户流程 | 缺失 |
优先补充的单元测试:
- WorkOrderService — 工单状态机流转
- LoginService — 登录认证流程
- EquipmentHealthService — 健康评分算法
- SparePartService — 出入库库存校验
六、数据库设计概要
6.1 ER 图(核心实体关系)
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 查询,待添加):
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)。
改进计划:
- 短期:在开发环境继续使用 JPA 自动建表
- 中期:引入 Flyway,将现有 schema 导出为初始迁移脚本
- 长期:生产环境禁止 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)核心功能标注为"待实现",需优先启动开发。