ether-docs/02-DESIGN/detail/DETAIL-OPS.md

52 KiB
Raw Permalink Blame History

运营与服务域 - 详细设计

文档编号: DETAIL-OPS 版本: v1.0 模块: module-wo + module-mdm备件/能耗部分) 生成日期: 2026-05-18 数据来源: ether-pms/module-wo + module-mdm 实际代码 + REVERSE-OPS.md 反推文档


一、功能点清单

功能ID 功能名称 优先级 实现状态 对应需求ID
OPS-001 工单创建 P0 已完成 02-OPERATIONS-001
OPS-002 工单查询(分页) P0 已完成 02-OPERATIONS-001
OPS-003 工单详情 P0 已完成 02-OPERATIONS-001
OPS-004 工单更新 P1 已完成 02-OPERATIONS-001
OPS-005 工单删除(逻辑删除) P1 已完成 02-OPERATIONS-001
OPS-006 工单派单 P0 已完成 02-OPERATIONS-002
OPS-007 工单开始执行 P0 已完成 02-OPERATIONS-002
OPS-008 工单完成 P0 已完成 02-OPERATIONS-002
OPS-009 工单验收 P0 已完成 02-OPERATIONS-002
OPS-010 工单取消 P1 已完成 02-OPERATIONS-002
OPS-011 工单挂起 P1 已完成 02-OPERATIONS-002
OPS-012 工单恢复 P1 已完成 02-OPERATIONS-002
OPS-013 工单退回 P1 已完成 02-OPERATIONS-002
OPS-014 工单统计 P1 已完成 02-OPERATIONS-003
OPS-015 工单明细查询 P1 已完成 02-OPERATIONS-004
OPS-016 工单明细批量添加 P1 已完成 02-OPERATIONS-004
OPS-017 维保任务创建 P0 已完成 02-OPERATIONS-005
OPS-018 维保任务查询 P0 已完成 02-OPERATIONS-005
OPS-019 维保任务分配 P0 已完成 02-OPERATIONS-005
OPS-020 维保任务开始执行 P0 已完成 02-OPERATIONS-005
OPS-021 维保任务完成(简版) P0 已完成 02-OPERATIONS-005
OPS-022 维保任务完成(详版) P0 已完成 02-OPERATIONS-005
OPS-023 维保任务验收 P0 已完成 02-OPERATIONS-005
OPS-024 维保任务取消 P1 已完成 02-OPERATIONS-005
OPS-025 维保任务评分 P2 已完成 02-OPERATIONS-005
OPS-026 维保任务统计 P1 已完成 02-OPERATIONS-006
OPS-027 维保计划管理 P1 已完成 02-OPERATIONS-007
OPS-028 巡检模板管理 P1 已完成 02-OPERATIONS-008
OPS-029 巡检模板复制 P2 已完成 02-OPERATIONS-008
OPS-030 备件CRUD P0 已完成 02-OPERATIONS-009
OPS-031 备件分类管理 P1 已完成 02-OPERATIONS-009
OPS-032 备件入库 P0 已完成 02-OPERATIONS-010
OPS-033 备件出库 P0 已完成 02-OPERATIONS-010
OPS-034 备件低库存预警 P1 已完成 02-OPERATIONS-010
OPS-035 备件出入库记录 P1 已完成 02-OPERATIONS-010
OPS-036 能源计量点管理 P1 已完成 02-OPERATIONS-011
OPS-037 能耗抄表记录 P0 已完成 02-OPERATIONS-012
OPS-038 能耗按类型统计 P1 已完成 02-OPERATIONS-013
OPS-039 单位面积能耗 P2 已完成 02-OPERATIONS-013
OPS-040 消息通知系统 P1 未实现 02-OPERATIONS-014
OPS-041 工单流转记录 P2 未实现 02-OPERATIONS-015
OPS-042 SLA监控 P2 未实现 02-OPERATIONS-016
OPS-043 智能派单 P3 未实现 02-OPERATIONS-017

二、数据结构设计

2.1 WorkOrder工单

表名: ops_work_order 实体类: com.ether.pms.ops.entity.WorkOrder

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
workNo VARCHAR(50) 自动生成 工单编号,格式: WO-YYYYMMDD-XXXXUNIQUE
source ENUM - 工单来源6种
type ENUM - 工单类型6种
priority ENUM MEDIUM 优先级4级
status ENUM PENDING 工单状态8种
previousStatus ENUM - 前一状态(挂起恢复用)
title VARCHAR(200) - 工单标题
description VARCHAR(2000) - 工单描述
projectId UUID - 所属项目
equipmentId UUID - 关联设备
spaceId UUID - 关联空间
planId UUID - 关联维保计划
triggerType ENUM - 触发类型4种
assignedTo VARCHAR(200) - 负责人
assignedVendor VARCHAR(200) - 服务商
assignedDate DATE - 派单日期
actualStart TIMESTAMP - 实际开始时间
actualEnd TIMESTAMP - 实际结束时间
actualHours DECIMAL(6,2) - 实际工时(小时)
faultCause VARCHAR(2000) - 故障原因
solution VARCHAR(5000) - 解决方案
result VARCHAR(2000) - 处理结果
laborCost DECIMAL(12,2) - 人工费
partsCost DECIMAL(12,2) - 备件费
totalCost DECIMAL(12,2) - 总费用
completedBy VARCHAR(200) - 完成人
completedDate DATE - 完成日期
verifiedBy VARCHAR(200) - 验收人
verifiedDate DATE - 验收日期
rating INTEGER - 评分1-5星
remark VARCHAR(1000) - 备注
photos JSONB - 照片URL列表(List<String>)
signature VARCHAR(2000) - 签名
isDeleted BOOLEAN false 逻辑删除标记
createdAt TIMESTAMP now() 创建时间
updatedAt TIMESTAMP now() 更新时间
createdBy VARCHAR(200) - 创建人

枚举定义:

枚举 中文
Source OWNER 业主报修
MAINTENANCE 维保计划
INSPECTION 巡检触发
FAULT 故障触发
REGULATORY 法规巡检
MANUAL 手动创建
Type REPAIR 维修
INSPECTION 巡检
SECURITY 安保
CLEANING 保洁
PROPERTY 物业
CONSULTATION 咨询
Priority LOW / MEDIUM / HIGH / URGENT 低/中/高/紧急
Status PENDING / ASSIGNED / IN_PROGRESS / SUSPENDED / RETURNED / COMPLETED / VERIFIED / CANCELLED 见状态机
TriggerType PLAN / INSPECTION / FAULT / MANUAL 计划/巡检/故障/手动

索引:

索引名 字段 用途
idx_wo_project_status project_id, status 项目+状态查询
idx_wo_priority_status priority, status 优先级+状态查询
idx_wo_plan_createdat plan_id, created_at 计划关联查询
idx_wo_status_createdat status, created_at 状态+时间查询
idx_wo_createdat_desc created_at DESC 时间倒序

2.2 WorkOrderItem工单明细

表名: ops_work_order_item 实体类: com.ether.pms.ops.entity.WorkOrderItem

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
workOrderId UUID - 所属工单ID
itemType ENUM - 明细类型3种
itemName VARCHAR(200) - 明细名称
quantity DECIMAL(10,2) 1 数量
unit VARCHAR(50) - 单位
unitPrice DECIMAL(12,2) - 单价
totalPrice DECIMAL(12,2) - 总价
isNormal BOOLEAN - 是否正常
observation VARCHAR(2000) - 观察记录
suggestion VARCHAR(2000) - 建议
sortOrder INTEGER 0 排序序号
createdAt TIMESTAMP now() 创建时间

枚举定义:

枚举 中文
ItemType PART 备件
INSPECTION_ITEM 巡检项
CHECKPOINT 检查点

2.3 MaintenancePlan维保计划

表名: ops_maintenance_plan 实体类: com.ether.pms.ops.entity.MaintenancePlan

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
planCode VARCHAR(50) 自动生成 计划编码UNIQUE
planName VARCHAR(200) - 计划名称
planContent VARCHAR(5000) - 计划内容
projectId UUID - 所属项目
equipmentId UUID - 关联设备
planType ENUM - 计划类型2种
cycleDays INTEGER - 周期天数
estimatedHours DECIMAL(6,2) - 预估工时
assignedVendor VARCHAR(200) - 指定服务商
status ENUM ACTIVE 计划状态3种
lastDate DATE - 上次执行日期
nextDate DATE - 下次执行日期
createdAt TIMESTAMP now() 创建时间
updatedAt TIMESTAMP now() 更新时间
createdBy VARCHAR(200) - 创建人

枚举定义:

枚举 中文
PlanType PREVENTIVE 预防性维护
CORRECTIVE 纠正性维护
PlanStatus ACTIVE 启用
INACTIVE 停用
SUSPENDED 暂停

2.4 MaintenanceTask维保任务

表名: ops_maintenance_task 实体类: com.ether.pms.ops.entity.MaintenanceTask

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
taskNo VARCHAR(50) 自动生成 任务编号,格式: EQ-YYYYMMDD-XXXXUNIQUE
planId UUID - 关联维保计划ID
equipmentId UUID - 关联设备ID
projectId UUID - 所属项目
taskType ENUM - 任务类型3种
triggerType ENUM - 触发类型4种
priority ENUM 自动判定 优先级4级
status ENUM PENDING 任务状态6种
title VARCHAR(200) - 任务标题
description VARCHAR(2000) - 任务描述
assignedTo VARCHAR(200) - 负责人
assignedVendor VARCHAR(200) - 服务商
assignedDate DATE - 派单日期
actualStart TIMESTAMP - 实际开始时间
actualEnd TIMESTAMP - 实际结束时间
actualHours DECIMAL(6,2) - 实际工时
faultCause VARCHAR(2000) - 故障原因
solution VARCHAR(5000) - 解决方案
result VARCHAR(2000) - 处理结果
partsUsed JSONB - 使用备件列表(List<Map>)
laborCost DECIMAL(12,2) - 人工费
partsCost DECIMAL(12,2) - 备件费
totalCost DECIMAL(12,2) - 总费用
completedBy VARCHAR(200) - 完成人
completedDate DATE - 完成日期
verifiedBy VARCHAR(200) - 验收人
verifiedDate DATE - 验收日期
rating INTEGER - 评分1-5
remark VARCHAR(1000) - 备注
photos JSONB - 照片URL列表
signature VARCHAR(2000) - 签名
createdAt TIMESTAMP now() 创建时间
updatedAt TIMESTAMP now() 更新时间
createdBy VARCHAR(200) - 创建人

枚举定义:

枚举 中文
TaskType PREVENTIVE 预防性维护
CORRECTIVE 纠正性维护
EMERGENCY 紧急维修
TriggerType PLAN 计划触发
INSPECTION 巡检触发
FAULT 故障触发
MANUAL 手动创建
Priority LOW / MEDIUM / HIGH / URGENT 低/中/高/紧急
Status PENDING / ASSIGNED / IN_PROGRESS / COMPLETED / VERIFIED / CANCELLED 见状态机

partsUsed JSONB 结构:

[
  {
    "partsId": "uuid",
    "partsName": "备件名称",
    "quantity": 2,
    "unitPrice": 100.00,
    "totalPrice": 200.00
  }
]

索引:

索引名 字段 用途
idx_mt_equipment_status equipment_id, status 设备+状态查询
idx_mt_project_status project_id, status 项目+状态查询
idx_mt_plan_createdat plan_id, created_at 计划关联查询
idx_mt_status_assigneddate status, assigned_date 状态+派单日期查询

2.5 InspectionTemplate巡检模板

表名: ops_inspection_template 实体类: com.ether.pms.mdm.entity.InspectionTemplate位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
templateCode VARCHAR(50) 自动生成 模板编码UNIQUE
templateName VARCHAR(200) - 模板名称
description VARCHAR(2000) - 描述
projectId UUID - 所属项目
spaceId UUID - 关联空间
category VARCHAR(50) - 分类
status ENUM ACTIVE 模板状态2种
createdAt TIMESTAMP now() 创建时间
updatedAt TIMESTAMP now() 更新时间
createdBy VARCHAR(200) - 创建人
items List<InspectionItem> - - 检查项列表(@Transient非持久化

枚举定义:

枚举 中文
TemplateStatus ACTIVE 启用
INACTIVE 停用

2.6 InspectionItem巡检项

表名: ops_inspection_item 实体类: com.ether.pms.mdm.entity.InspectionItem位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
templateId UUID - 所属模板ID
itemName VARCHAR(200) - 检查项名称
description VARCHAR(2000) - 描述
checkMethod VARCHAR(2000) - 检查方法
standard VARCHAR(2000) - 检查标准
isMandatory BOOLEAN true 是否必检
isNormalRequired BOOLEAN true 是否需要正常判定
sortOrder INTEGER 0 排序序号
createdAt TIMESTAMP now() 创建时间

2.7 SparePart备件

表名: ops_spare_part 实体类: com.ether.pms.mdm.entity.SparePart位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
projectId UUID - 所属项目
sparePartCode VARCHAR 自动生成 备件编码UNIQUE格式: SP+yyyyMMddHHmmss
sparePartName VARCHAR - 备件名称
categoryId UUID - 分类ID
specification VARCHAR(500) - 规格
unit VARCHAR(50) - 单位
safeStock INTEGER 0 安全库存
currentStock INTEGER 0 当前库存
unitPrice DECIMAL(10,2) - 单价
supplier VARCHAR(200) - 供应商
supplierContact VARCHAR - 供应商联系方式
location VARCHAR(200) - 存放位置
remarks VARCHAR(1000) - 备注
status ENUM ACTIVE 状态2种
createdAt TIMESTAMP now() 创建时间
updatedAt TIMESTAMP now() 更新时间

枚举定义:

枚举 中文
Status ACTIVE 启用
INACTIVE 停用

索引:

索引名 字段 用途
idx_sp_project_status project_id, status 项目+状态查询

2.8 SparePartCategory备件分类

表名: ops_spare_part_category 实体类: com.ether.pms.mdm.entity.SparePartCategory位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
parentId UUID - 父分类ID支持树形结构
categoryCode VARCHAR 自动生成 分类编码UNIQUE格式: CC+yyyyMMddHHmmss
categoryName VARCHAR - 分类名称
description VARCHAR(500) - 描述
sortOrder INTEGER - 排序序号
createdAt TIMESTAMP now() 创建时间

2.9 SparePartRecord备件出入库记录

表名: ops_spare_part_record 实体类: com.ether.pms.mdm.entity.SparePartRecord位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
recordCode VARCHAR 自动生成 记录编码UNIQUE格式: REC+类型+yyyyMMddHHmmss
recordType ENUM - 记录类型4种
sparePartId UUID - 备件ID
quantity INTEGER - 数量
balance INTEGER - 操作后余额
relatedOrderId UUID - 关联工单ID
recordedBy UUID - 操作人
recordDate TIMESTAMP now() 操作时间
remarks VARCHAR(1000) - 备注

枚举定义:

枚举 中文 说明
RecordType IN 入库 库存增加
OUT 出库 库存减少,可关联工单
CHECK 盘点 库存校准
ADJUST 调整 库存调整

2.10 EnergyMeter能源计量点

表名: ops_energy_meter 实体类: com.ether.pms.mdm.entity.EnergyMeter位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
projectId UUID - 所属项目
meterCode VARCHAR 自动生成 计量点编码UNIQUE
meterName VARCHAR - 计量点名称
energyType ENUM - 能源类型6种
spaceNodeId UUID - 关联空间节点
installationLocation VARCHAR - 安装位置
ratedCapacity DECIMAL(10,2) - 额定容量
unitPrice DECIMAL(10,4) - 单价
status ENUM ACTIVE 状态2种
createdAt TIMESTAMP now() 创建时间
updatedAt TIMESTAMP now() 更新时间

枚举定义:

枚举 中文 说明
EnergyType LIGHTING 照明插座用电 建筑分项能耗分类
HVAC 空调用电 建筑分项能耗分类
POWER 动力用电 建筑分项能耗分类
SPECIAL 特殊用电 建筑分项能耗分类
WATER 给排水 水耗计量
GAS 燃气 气耗计量
Status ACTIVE 启用 可正常抄表
INACTIVE 停用 不可抄表

2.11 EnergyConsumption能耗记录

表名: ops_energy_consumption 实体类: com.ether.pms.mdm.entity.EnergyConsumption位于module-mdm

字段 类型 必填 默认值 说明
id UUID 自动生成 主键
projectId UUID - 项目ID
meterId UUID - 计量点ID
consumptionDate DATE - 消耗日期
previousReading DECIMAL(12,2) - 上次读数
currentReading DECIMAL(12,2) - 当前读数
consumption DECIMAL(12,2) - 消耗量 = currentReading - previousReading
amount DECIMAL(10,2) - 费用 = consumption x unitPrice
recordedBy UUID - 抄表人
recordMethod ENUM MANUAL 抄表方式2种
remarks VARCHAR(1000) - 备注
createdAt TIMESTAMP now() 创建时间

枚举定义:

枚举 中文 说明
RecordMethod MANUAL 手动录入 人工抄表
IOT IoT自动采集 自动采集(预留)

索引:

索引名 字段 用途
idx_ec_meter_date meter_id, consumption_date 计量点+日期查询
idx_ec_project_date project_id, consumption_date 项目+日期查询

2.12 ER关系图

erDiagram
    MaintenancePlan ||--o{ MaintenanceTask : "1:N planId"
    MaintenancePlan }o--|| Equipment : "equipmentId"
    WorkOrder ||--o{ WorkOrderItem : "1:N workOrderId"
    WorkOrder }o--o| MaintenancePlan : "planId"
    WorkOrder }o--o| Equipment : "equipmentId"
    InspectionTemplate ||--o{ InspectionItem : "1:N templateId"
    SparePartCategory ||--o{ SparePart : "1:N categoryId"
    SparePart ||--o{ SparePartRecord : "1:N sparePartId"
    EnergyMeter ||--o{ EnergyConsumption : "1:N meterId"

    WorkOrder {
        UUID id PK
        String workNo UK
        Source source
        Type type
        Priority priority
        Status status
        Status previousStatus
        UUID projectId FK
        UUID equipmentId FK
        UUID planId FK
    }

    WorkOrderItem {
        UUID id PK
        UUID workOrderId FK
        ItemType itemType
        String itemName
        BigDecimal quantity
        BigDecimal totalPrice
    }

    MaintenancePlan {
        UUID id PK
        String planCode UK
        String planName
        PlanType planType
        Integer cycleDays
        PlanStatus status
        UUID equipmentId FK
    }

    MaintenanceTask {
        UUID id PK
        String taskNo UK
        UUID planId FK
        UUID equipmentId FK
        TaskType taskType
        TriggerType triggerType
        Priority priority
        Status status
    }

    InspectionTemplate {
        UUID id PK
        String templateCode UK
        String templateName
        String category
        TemplateStatus status
    }

    InspectionItem {
        UUID id PK
        UUID templateId FK
        String itemName
        String checkMethod
        String standard
        Boolean isMandatory
    }

    SparePart {
        UUID id PK
        String sparePartCode UK
        String sparePartName
        UUID categoryId FK
        Integer currentStock
        Integer safeStock
    }

    SparePartRecord {
        UUID id PK
        String recordCode UK
        RecordType recordType
        UUID sparePartId FK
        Integer quantity
        Integer balance
        UUID relatedOrderId FK
    }

    EnergyMeter {
        UUID id PK
        String meterCode UK
        String meterName
        EnergyType energyType
        BigDecimal unitPrice
    }

    EnergyConsumption {
        UUID id PK
        UUID meterId FK
        LocalDate consumptionDate
        BigDecimal consumption
        BigDecimal amount
    }

三、API设计

3.1 WorkOrderController

基础路径: /api/wo/work-orders 控制器类: com.ether.pms.ops.controller.WorkOrderController

工单 CRUD

方法 路径 说明 请求体 响应 功能ID
POST / 创建工单 WorkOrder ApiResponse<WorkOrder> OPS-001
GET / 查询工单列表(分页) QueryParams ApiResponse<PageResponse<WorkOrder>> OPS-002
GET /{id} 获取工单详情 - ApiResponse<WorkOrder> OPS-003
PUT /{id} 更新工单 WorkOrder ApiResponse<WorkOrder> OPS-004
DELETE /{id} 删除工单(逻辑删除) - ApiResponse<Void> OPS-005

查询参数GET /:

参数 类型 必填 默认值 说明
projectId UUID - 按项目筛选
equipmentId UUID - 按设备筛选
source Source - 按来源筛选
type Type - 按类型筛选
status Status - 按状态筛选
priority Priority - 按优先级筛选
assignedTo String - 按负责人筛选
keyword String - 关键词搜索
page int 0 页码
size int 20 每页大小

工单状态流转

方法 路径 说明 请求体 响应 功能ID
POST /{id}/assign 派单 AssignRequest ApiResponse<WorkOrder> OPS-006
POST /{id}/start 开始执行 - ApiResponse<WorkOrder> OPS-007
POST /{id}/complete 完成工单 WorkOrder ApiResponse<WorkOrder> OPS-008
POST /{id}/verify 验收工单 VerifyRequest ApiResponse<WorkOrder> OPS-009
POST /{id}/cancel 取消工单 - ApiResponse<WorkOrder> OPS-010
POST /{id}/suspend 挂起工单 - ApiResponse<WorkOrder> OPS-011
POST /{id}/resume 恢复工单 - ApiResponse<WorkOrder> OPS-012
POST /{id}/return 退回工单 - ApiResponse<WorkOrder> OPS-013

请求体定义:

// 派单请求
AssignRequest {
    String assignedTo;       // 负责人
    String assignedVendor;   // 服务商
    LocalDate assignedDate;  // 派单日期
}

// 验收请求
VerifyRequest {
    String verifiedBy;  // 验收人
    String remark;      // 备注
    Integer rating;     // 评分1-5
}

工单统计与明细

方法 路径 说明 请求体 响应 功能ID
GET /stats 工单统计 - ApiResponse<WorkOrderStatsDTO> OPS-014
GET /{id}/items 获取工单明细 - ApiResponse<List<WorkOrderItem>> OPS-015
POST /{id}/items 批量添加工单明细 List<WorkOrderItem> ApiResponse<WorkOrder> OPS-016

WorkOrderStatsDTO:

字段 类型 说明
total long 工单总数
pending long 待分配数
assigned long 已派单数
inProgress long 执行中数
completed long 已完成数
verified long 已验收数
cancelled long 已取消数
suspended long 已挂起数
returned long 已退回数
completedToday long 今日完成数
createdToday long 今日创建数
overdue long 逾期数
bySource Map<String, Long> 按来源分布
byType Map<String, Long> 按类型分布
byPriority Map<String, Long> 按优先级分布

3.2 MaintenanceTaskController

基础路径: /api/ops/maintenance-tasks 控制器类: com.ether.pms.ops.controller.MaintenanceTaskController

维保任务 CRUD

方法 路径 说明 请求体 响应 功能ID
POST / 创建维保任务 MaintenanceTask ApiResponse<MaintenanceTask> OPS-017
GET / 查询维保任务列表 QueryParams ApiResponse<List<MaintenanceTask>> OPS-018
GET /{id} 获取任务详情 - ApiResponse<MaintenanceTask> OPS-018
PUT /{id} 更新任务 MaintenanceTask ApiResponse<MaintenanceTask> OPS-018
DELETE /{id} 删除任务逻辑删除设为CANCELLED - ApiResponse<Void> OPS-024

查询参数GET /:

参数 类型 必填 说明
equipmentId UUID 按设备筛选
planId UUID 按计划筛选
status Status 按状态筛选
priority Priority 按优先级筛选
assignedTo String 按负责人筛选
overdueDate LocalDate 逾期截止日期

查询参数互斥优先级equipmentId > planId > status > priority > assignedTo > overdueDate

维保任务状态流转

方法 路径 说明 请求体 响应 功能ID
POST /{id}/assign 分配任务 AssignRequest ApiResponse<MaintenanceTask> OPS-019
POST /{id}/start 开始执行 - ApiResponse<MaintenanceTask> OPS-020
POST /{id}/complete 完成任务(简版) CompleteRequest ApiResponse<MaintenanceTask> OPS-021
POST /{id}/complete-details 完成任务(详版) MaintenanceTask ApiResponse<MaintenanceTask> OPS-022
POST /{id}/verify 验收任务 VerifyRequest ApiResponse<MaintenanceTask> OPS-023
POST /{id}/cancel 取消任务 - ApiResponse<MaintenanceTask> OPS-024
POST /{id}/rate 评分 rating (query param) ApiResponse<MaintenanceTask> OPS-025

请求体定义:

// 分配请求
AssignRequest {
    String assignedTo;
    LocalDate assignedDate;
}

// 完成请求(简版)
CompleteRequest {
    String result;
    BigDecimal actualHours;
    BigDecimal cost;
    String completedBy;
}

// 验收请求
VerifyRequest {
    String verifiedBy;
    String remark;
    Integer rating;
}

维保任务统计

方法 路径 说明 请求体 响应 功能ID
GET /stats 任务统计 - ApiResponse<MaintenanceTaskStatsDTO> OPS-026

MaintenanceTaskStatsDTO:

字段 类型 说明
total long 任务总数
pending long 待分配数
assigned long 已派单数
inProgress long 执行中数
completed long 已完成数
verified long 已验收数
cancelled long 已取消数
completedToday long 今日完成数
createdToday long 今日创建数
overdue long 逾期数
avgCompleteHours BigDecimal 平均完成工时
avgRating BigDecimal 平均评分
byPriority Map<String, Long> 按优先级分布
byTriggerType Map<String, Long> 按触发类型分布

3.3 InspectionTemplateController

基础路径: /api/ops/inspection-templates 控制器类: com.ether.pms.mdm.controller.InspectionTemplateController位于module-mdm

方法 路径 说明 请求体 响应 功能ID
GET / 按项目查询模板 projectId ApiResponse<List<InspectionTemplate>> OPS-028
POST / 创建模板 InspectionTemplate ApiResponse<InspectionTemplate> OPS-028
GET /{id} 获取模板详情 - ApiResponse<InspectionTemplate> OPS-028
PUT /{id} 更新模板 InspectionTemplate ApiResponse<InspectionTemplate> OPS-028
POST /{id}/copy 复制模板 newName (query param) ApiResponse<InspectionTemplate> OPS-029
GET /by-type/{equipmentType} 按设备类型查询 - ApiResponse<List<InspectionTemplate>> OPS-028

3.4 SparePartController

基础路径: /api/ops/spare-parts 控制器类: com.ether.pms.mdm.controller.SparePartController位于module-mdm

分类管理

方法 路径 说明 请求体 响应 功能ID
GET /categories 获取所有分类 - ApiResponse<List<SparePartCategory>> OPS-031
POST /categories 创建分类 SparePartCategory ApiResponse<SparePartCategory> OPS-031

备件管理

方法 路径 说明 请求体 响应 功能ID
GET / 查询备件列表 projectId, categoryId(可选) ApiResponse<List<SparePart>> OPS-030
GET /{id} 获取备件详情 - ApiResponse<SparePart> OPS-030
POST / 创建备件 SparePart ApiResponse<SparePart> OPS-030
PUT /{id} 更新备件 SparePart ApiResponse<SparePart> OPS-030
DELETE /{id} 删除备件设为INACTIVE - ApiResponse<Void> OPS-030
GET /low-stock 低库存预警 projectId ApiResponse<List<SparePart>> OPS-034

库存操作

方法 路径 说明 请求体 响应 功能ID
POST /in-stock 入库 StockRequest ApiResponse<SparePartRecord> OPS-032
POST /out-stock 出库 OutStockRequest ApiResponse<SparePartRecord> OPS-033
GET /{id}/records 获取出入库记录 - ApiResponse<List<SparePartRecord>> OPS-035

请求体定义:

// 入库请求
StockRequest {
    @NotNull UUID sparePartId;
    @NotNull Integer quantity;
    UUID recordedBy;
    String remarks;
}

// 出库请求
OutStockRequest {
    @NotNull UUID sparePartId;
    @NotNull Integer quantity;
    UUID relatedOrderId;    // 关联工单ID
    UUID recordedBy;
    String remarks;
}

3.5 EnergyController

基础路径: /api/ops/energy 控制器类: com.ether.pms.mdm.controller.EnergyController位于module-mdm

计量点管理

方法 路径 说明 请求体 响应 功能ID
POST /meters 创建计量点 EnergyMeter ApiResponse<EnergyMeter> OPS-036
GET /meters 查询计量点 projectId, energyType(可选) ApiResponse<List<EnergyMeter>> OPS-036
GET /meters/{id} 获取计量点详情 - ApiResponse<EnergyMeter> OPS-036
PUT /meters/{id} 更新计量点 EnergyMeter ApiResponse<EnergyMeter> OPS-036
DELETE /meters/{id} 删除计量点 - ApiResponse<Void> OPS-036

能耗记录

方法 路径 说明 请求体 响应 功能ID
POST /consumption 抄表记录 RecordConsumptionRequest ApiResponse<EnergyConsumption> OPS-037
GET /consumption/{meterId} 获取能耗记录 startDate, endDate(可选) ApiResponse<List<EnergyConsumption>> OPS-037

能耗统计

方法 路径 说明 参数 响应 功能ID
GET /statistics/by-type 按类型统计 projectId, month ApiResponse<Map<EnergyType, BigDecimal>> OPS-038
GET /statistics/unit-consumption 单位面积能耗 projectId, month ApiResponse<BigDecimal> OPS-039

请求体定义:

// 抄表请求
RecordConsumptionRequest {
    @NotNull UUID meterId;
    @NotNull BigDecimal currentReading;
    UUID recordedBy;
}

四、业务规则

4.1 工单状态机

完整状态流转图

stateDiagram-v2
    [*] --> PENDING : 创建工单

    PENDING --> ASSIGNED : 派单(assign)
    PENDING --> CANCELLED : 取消(cancel)

    ASSIGNED --> IN_PROGRESS : 开始执行(start)
    ASSIGNED --> SUSPENDED : 挂起(suspend)
    ASSIGNED --> RETURNED : 退回(return)
    ASSIGNED --> CANCELLED : 取消(cancel)

    IN_PROGRESS --> COMPLETED : 完成(complete)
    IN_PROGRESS --> SUSPENDED : 挂起(suspend)
    IN_PROGRESS --> CANCELLED : 取消(cancel)

    SUSPENDED --> IN_PROGRESS : 恢复(resume)\n[默认回到IN_PROGRESS]
    SUSPENDED --> ASSIGNED : 恢复(resume)\n[previousStatus=ASSIGNED时]

    RETURNED --> PENDING : 退回后重新变为待分配

    COMPLETED --> VERIFIED : 验收(verify)

    VERIFIED --> [*]
    CANCELLED --> [*]

8种状态说明

状态 中文 说明 可转入状态
PENDING 待分配 工单创建后的初始状态 ASSIGNED, CANCELLED
ASSIGNED 已派单 已分配负责人/服务商 IN_PROGRESS, SUSPENDED, RETURNED, CANCELLED
IN_PROGRESS 执行中 正在处理 COMPLETED, SUSPENDED, CANCELLED
SUSPENDED 已挂起 暂停处理,记录前一状态 IN_PROGRESS, ASSIGNED取决于previousStatus
RETURNED 已退回 被退回重新分配 PENDING
COMPLETED 已完成 处理完毕 VERIFIED
VERIFIED 已验收 验收通过 终态
CANCELLED 已取消 工单取消 终态

每个流转的前置条件与自动处理

当前状态 操作 目标状态 前置条件 自动处理
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 status 非 COMPLETED/VERIFIED -
ASSIGNED/IN_PROGRESS suspend SUSPENDED - 保存 previousStatus = 当前状态
SUSPENDED resume previousStatus status == SUSPENDED 恢复到 previousStatus默认 IN_PROGRESS
ASSIGNED return PENDING status == ASSIGNED 清空 assignedTo/assignedVendor/assignedDate

previousStatus回溯机制

挂起时:
  workOrder.previousStatus = workOrder.status  // 保存当前状态
  workOrder.status = SUSPENDED

恢复时:
  targetStatus = workOrder.previousStatus != null
      ? workOrder.previousStatus
      : IN_PROGRESS  // 默认恢复到IN_PROGRESS
  workOrder.previousStatus = null  // 清空
  workOrder.status = targetStatus

工单编号生成规则

格式: WO-YYYYMMDD-XXXX
示例: WO-20260518-0001

生成算法:
1. 日期前缀: "WO-" + LocalDate.now().format("yyyyMMdd") + "-"
2. 查询当天最大编号: findMaxWorkNoByPrefix(prefix + "%")
3. 序号递增: maxWorkNo存在时取后4位+1否则从1开始
4. 格式化: String.format("%04d", sequence)

完成工单自动计算工时

actualHours = Duration.between(actualStart, actualEnd).toMinutes() / 60.0
// 精度保留2位小数四舍五入

4.2 维保任务触发机制

4种触发类型

触发类型 枚举值 说明 优先级自动判定
计划触发 PLAN 由维保计划周期性触发 MEDIUM
巡检触发 INSPECTION 巡检发现异常时触发 HIGH
故障触发 FAULT 设备故障时触发 HIGH含紧急关键词时URGENT
手动创建 MANUAL 人工手动创建 MEDIUM

自动优先级判定算法

输入: MaintenanceTask (taskType, triggerType, title, description)

1. IF taskType == EMERGENCY
   → return URGENT

2. IF triggerType == FAULT
   → 检查 title + description 是否包含紧急关键词
   → 紧急关键词: [困人, 漏水, 停电, 火灾, 爆炸, 漏电, 冒烟, 故障停机]
   → IF 包含任一关键词 → return URGENT
   → ELSE → return HIGH

3. IF triggerType == INSPECTION
   → return HIGH

4. IF triggerType == PLAN
   → return MEDIUM

5. 默认 → return MEDIUM

维保任务状态机

stateDiagram-v2
    [*] --> PENDING : 创建任务

    PENDING --> ASSIGNED : 分配(assign)
    PENDING --> CANCELLED : 取消(cancel)

    ASSIGNED --> IN_PROGRESS : 开始执行(start)
    ASSIGNED --> CANCELLED : 取消(cancel)

    IN_PROGRESS --> COMPLETED : 完成(complete/complete-details)
    IN_PROGRESS --> CANCELLED : 取消(cancel)

    COMPLETED --> VERIFIED : 验收(verify)

    VERIFIED --> [*]
    CANCELLED --> [*]

维保任务与工单状态机差异

差异点 WorkOrder MaintenanceTask
状态数量 8种含SUSPENDED/RETURNED 6种无SUSPENDED/RETURNED
完成方式 仅一种 complete 两种complete简版+ complete-details详版
评分方式 验收时评分 验收时评分 + 独立 rate 接口
删除行为 逻辑删除isDeleted=true 逻辑删除设为CANCELLED
完成后联动 自动更新设备维保记录
挂起/恢复 支持 不支持
退回 支持ASSIGNED→PENDING 不支持

维保任务完成后联动

维保任务完成completeTaskWithDetails时自动更新设备信息

1. 更新设备维保商:
   equipment.maintenanceVendor = task.assignedVendor

2. 更新下次巡检日期(仅预防性维护):
   IF task.taskType == PREVENTIVE
   THEN equipment.nextInspectionDate = now() + equipment.inspectionCycle
   默认周期: 30天

3. 异常容错:
   更新设备失败不影响工单完成catch异常仅打印日志

任务编号生成规则

格式: EQ-YYYYMMDD-XXXX
示例: EQ-20260518-0001

生成算法: 与工单编号类似,前缀为 EQ-

4.3 巡检模板管理

模板创建规则:

  • templateCode 自动生成UNIQUE约束
  • 模板创建时可同时配置检查项列表(@Transient字段需单独持久化
  • 模板状态默认为 ACTIVE

模板复制规则:

  • 复制模板时创建新模板,名称使用传入的 newName
  • 检查项同时复制到新模板
  • 新模板的 templateCode 自动生成

检查项配置:

  • InspectionItem 通过 templateId 关联模板
  • isMandatory = true 的检查项为必检项,不可跳过
  • isNormalRequired = true 的检查项需要判定正常/异常
  • sortOrder 控制检查项的展示顺序

4.4 备件库存管理

入库流程

1. 校验: quantity > 0
2. 查询备件: getSparePartById(sparePartId)
3. 更新库存: currentStock += quantity
4. 创建入库记录: RecordType=IN, balance=更新后库存
5. 生成记录编码: REC + IN + yyyyMMddHHmmss

出库流程

1. 校验: quantity > 0
2. 查询备件: getSparePartById(sparePartId)
3. 校验库存: currentStock >= quantity
   → 不满足: 抛出 BusinessException("库存不足当前库存X需要出库Y")
4. 更新库存: currentStock -= quantity
5. 创建出库记录: RecordType=OUT, balance=更新后库存, relatedOrderId=关联工单
6. 生成记录编码: REC + OUT + yyyyMMddHHmmss

低库存预警

预警条件: currentStock < safeStock
查询方式: sparePartRepository.findLowStockParts(projectId)

库存余额计算

每次出入库操作后:
  record.balance = sparePart.currentStock  (操作后的库存余额)

关联工单

  • 出库时可指定 relatedOrderId 关联工单
  • 用于追踪工单的备件消耗

并发场景考虑

当前实现未使用乐观锁或悲观锁,存在并发安全问题:

并发场景 风险 当前处理 建议方案
同时出库 库存超卖 无保护 添加 @Version 乐观锁或 SELECT FOR UPDATE 悲观锁
同时入库 库存计算错误 无保护 添加 @Version 乐观锁
并发读写 读到中间状态 无保护 使用数据库事务隔离级别

建议并发控制方案:

// 方案1: 乐观锁(推荐)
@Version
private Long version;

// 出库时:
SparePart sp = repository.findById(id);
if (sp.getCurrentStock() < quantity) throw ...;
sp.setCurrentStock(sp.getCurrentStock() - quantity);
repository.save(sp);  // version不匹配时抛出OptimisticLockException

// 方案2: 悲观锁
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT sp FROM SparePart sp WHERE sp.id = :id")
SparePart findByIdForUpdate(@Param("id") UUID id);

4.5 能耗计量管理

抄表流程

1. 校验计量点: meterId 存在且 status == ACTIVE
2. 获取上次抄表记录: findTopByMeterIdOrderByConsumptionDateDesc
3. 计算消耗量: consumption = currentReading - previousReading
4. 校验读数: consumption >= 0当前读数不能小于上次读数
5. 计算费用: amount = consumption x meter.unitPrice
6. 创建能耗记录: recordMethod=MANUAL

消耗量计算

consumption = currentReading - previousReading

特殊情况:
- 首次抄表: previousReading = 0
- 读数倒退: 抛出 BusinessException("当前读数不能小于上次读数")

费用计算

amount = consumption x meter.unitPrice

条件:
- meter.unitPrice 不为空
- consumption > 0

按类型统计

输入: projectId, month (LocalDate)
1. 计算月份范围: startDate = month.withDayOfMonth(1), endDate = month.withDayOfMonth(length)
2. 初始化所有EnergyType为0
3. 查询项目总消耗: sumConsumptionByProjectAndDateRange
4. 当前实现: 将总消耗分配给LIGHTING类型TODO: 应按meter.energyType汇总

当前按类型统计实现不完整所有消耗归入LIGHTING类型需改为按meter.energyType分别汇总。

单位面积能耗

输入: projectId, month
1. 获取项目所有ACTIVE状态的计量点
2. 遍历每个计量点,查询当月消耗量
3. 累加总消耗量

注意: 当前实现未除以建筑面积,仅返回总消耗量
TODO: 需要获取项目建筑面积,计算 单位面积能耗 = 总消耗量 / 建筑面积

4.6 工单明细管理

3种明细类型

类型 枚举值 中文 用途
PART 备件 记录工单使用的备件及费用
INSPECTION_ITEM 巡检项 记录工单的巡检检查项
CHECKPOINT 检查点 记录工单的关键检查点

费用计算

前端计算:
  item.totalPrice = item.quantity x item.unitPrice
  partsCost = SUM(item.totalPrice)  WHERE item.itemType == PART
  totalCost = laborCost + partsCost

批量添加

  • 支持批量添加工单明细
  • 受 BatchOperationValidator 限制(校验批量操作大小)
  • 每条明细的 workOrderId 自动设置为当前工单ID
  • sortOrder 控制明细展示顺序

五、执行约束

5.1 工单编号唯一性

  • workNo 字段在数据库层设置 UNIQUE 约束
  • 生成算法基于日期前缀+4位序号按日期递增
  • 编号格式: WO-YYYYMMDD-XXXX
  • 同一天内序号从0001开始递增

5.2 任务编号唯一性

  • taskNo 字段在数据库层设置 UNIQUE 约束
  • 编号格式: EQ-YYYYMMDD-XXXX
  • 生成算法与工单编号类似

5.3 备件库存非负约束

  • 出库时校验: currentStock >= quantity
  • 不满足时抛出 BusinessException(6104, "库存不足当前库存X需要出库Y")
  • 入库数量必须 > 0否则抛出 BusinessException(6102, "入库数量必须大于0")
  • 出库数量必须 > 0否则抛出 BusinessException(6103, "出库数量必须大于0")

5.4 能耗读数递增约束

  • 抄表时校验: currentReading >= previousReading
  • 不满足时抛出 BusinessException(6103, "当前读数不能小于上次读数")
  • 首次抄表时 previousReading = 0

5.5 工单状态流转约束

  • 只能按合法路径流转,非法流转抛出 RuntimeException
  • COMPLETED/VERIFIED 状态不可取消
  • SUSPENDED 状态只能恢复resume不能直接转为其他状态
  • RETURNED 状态自动转为 PENDING

合法流转矩阵:

当前\目标 PENDING ASSIGNED IN_PROGRESS SUSPENDED RETURNED COMPLETED VERIFIED CANCELLED
PENDING - V - - - - - V
ASSIGNED - - V V V - - V
IN_PROGRESS - - - V - V - V
SUSPENDED - V* V* - - - - -
RETURNED V - - - - - - -
COMPLETED - - - - - - V -
VERIFIED - - - - - - - -
CANCELLED - - - - - - - -

V* 表示 SUSPENDED 恢复时回到 previousStatus

5.6 维保计划周期约束

  • cycleDays 必须 > 0周期天数必须为正数
  • nextDate = lastDate + cycleDays下次执行日期由周期推算
  • 计划状态变更ACTIVE 可转为 INACTIVE 或 SUSPENDED

六、权限控制

API路径 操作 所需权限 说明
POST /api/wo/work-orders 创建工单 wo:work-order:create 需项目级权限
GET /api/wo/work-orders 查询工单 wo:work-order:read 需项目级权限
PUT /api/wo/work-orders/{id} 更新工单 wo:work-order:update 需项目级权限
DELETE /api/wo/work-orders/{id} 删除工单 wo:work-order:delete 需项目级权限
POST /api/wo/work-orders/{id}/assign 派单 wo:work-order:assign 需项目级权限
POST /api/wo/work-orders/{id}/start 开始执行 wo:work-order:execute 需项目级权限
POST /api/wo/work-orders/{id}/complete 完成工单 wo:work-order:execute 需项目级权限
POST /api/wo/work-orders/{id}/verify 验收工单 wo:work-order:verify 需项目级权限
POST /api/wo/work-orders/{id}/cancel 取消工单 wo:work-order:cancel 需项目级权限
POST /api/wo/work-orders/{id}/suspend 挂起工单 wo:work-order:suspend 需项目级权限
POST /api/wo/work-orders/{id}/resume 恢复工单 wo:work-order:resume 需项目级权限
POST /api/wo/work-orders/{id}/return 退回工单 wo:work-order:return 需项目级权限
POST /api/ops/maintenance-tasks 创建维保任务 ops:maintenance-task:create 需项目级权限
POST /api/ops/maintenance-tasks/{id}/assign 分配任务 ops:maintenance-task:assign 需项目级权限
POST /api/ops/maintenance-tasks/{id}/start 开始执行 ops:maintenance-task:execute 需项目级权限
POST /api/ops/maintenance-tasks/{id}/complete 完成任务 ops:maintenance-task:execute 需项目级权限
POST /api/ops/maintenance-tasks/{id}/verify 验收任务 ops:maintenance-task:verify 需项目级权限
POST /api/ops/spare-parts/in-stock 入库 ops:spare-part:stock-in 需项目级权限
POST /api/ops/spare-parts/out-stock 出库 ops:spare-part:stock-out 需项目级权限
POST /api/ops/energy/consumption 抄表 ops:energy:record 需项目级权限

当前实现中权限控制尚未集成Spring Security以上为设计预期权限矩阵。


七、例外情况处理

例外场景 触发条件 处理方式 错误码/信息
工单状态流转非法 从PENDING直接complete 抛出RuntimeException "只能完成进行中的工单"
工单已完成后取消 status=COMPLETED/VERIFIED时cancel 抛出RuntimeException "无法取消已完成的工单"
挂起非ASSIGNED/IN_PROGRESS工单 status不合法时suspend 抛出RuntimeException "只能挂起已派单或执行中的工单"
恢复非SUSPENDED工单 status!=SUSPENDED时resume 抛出RuntimeException "只能恢复已挂起的工单"
退回非ASSIGNED工单 status!=ASSIGNED时return 抛出RuntimeException "只能退回已派单的工单"
备件库存不足 出库数量>当前库存 抛出BusinessException 6104 "库存不足当前库存X需要出库Y"
入库数量非法 quantity <= 0 抛出BusinessException 6102 "入库数量必须大于0"
出库数量非法 quantity <= 0 抛出BusinessException 6103 "出库数量必须大于0"
能耗读数倒退 currentReading < previousReading 抛出BusinessException 6103 "当前读数不能小于上次读数"
能源仪表不存在 meterId无效 抛出BusinessException 6101 "能源仪表不存在"
仪表非ACTIVE状态 抄表时meter.status!=ACTIVE 抛出BusinessException 6102 "只能对ACTIVE状态的仪表进行抄表"
维保计划关联设备不存在 equipmentId无效 数据库外键约束 需添加业务校验
维保任务不存在 taskId无效 抛出BusinessException ErrorCode.NOT_FOUND "维保工单不存在"
工单不存在 workOrderId无效或已删除 抛出RuntimeException "工单不存在: {id}"
维保任务评分越界 rating < 1 或 rating > 5 抛出BusinessException 6006 "评分必须在1-5之间"
维保任务评分状态非法 非COMPLETED/VERIFIED状态评分 抛出BusinessException 6005 "只有已完成或已验收的工单才能评分"
巡检模板被引用不能删除 模板被巡检记录引用 - 当前无校验,建议增加
备件不存在 sparePartId无效 抛出BusinessException 6101 "备件不存在"

附录:已知代码问题与改进建议

问题 位置 影响 建议
备件出入库无并发控制 SparePartServiceImpl 高并发下可能库存超卖 添加 @Version 乐观锁或 SELECT FOR UPDATE
能耗按类型统计实现不完整 EnergyConsumptionServiceImpl 所有消耗归入LIGHTING类型 按 meter.energyType 分别汇总
单位面积能耗未除以建筑面积 EnergyConsumptionServiceImpl 返回的是总消耗量而非单位面积能耗 获取项目建筑面积做除法
工单查询参数互斥 WorkOrderController/MaintenanceTaskController 多条件同时传入只生效一个 改为 Specification 动态查询
维保任务查询无分页 MaintenanceTaskController 数据量大时可能OOM 改为分页查询
工单删除/退回使用RuntimeException WorkOrderServiceImpl 异常信息不够结构化 改为 BusinessException + ErrorCode
维保任务删除实际是取消 MaintenanceTaskServiceImpl deleteTask 实际设置 status=CANCELLED 命名与行为不一致,建议重命名
前后端状态枚举不一致 maintenance.ts vs MaintenanceTask 前端含ACCEPTED后端含ASSIGNED/VERIFIED 统一前后端状态定义
前端维保计划两套API maintenance.ts + maintenance-plan.ts 接口重复,维护困难 统一为一套API
工单无流转记录 WorkOrderServiceImpl 无法追溯工单状态变更历史 新增 WorkOrderFlow 实体