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

1037 lines
43 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.

# 设备与资产域 - 详细设计
**文档编号**: DETAIL-ASSET
**版本**: v1.0
**模块**: module-asset
**生成日期**: 2026-05-18
**数据来源**: ether-pms/module-asset 实际代码 + REVERSE-ASSET.md 反推文档
---
## 一、功能点清单
| 功能ID | 功能名称 | 优先级 | 实现状态 | 对应需求ID |
|--------|----------|--------|----------|------------|
| ASSET-001 | 设备台账CRUD | P0 | 已完成 | 03-ASSET-001 |
| ASSET-002 | 设备批量删除 | P1 | 已完成 | 03-ASSET-001 |
| ASSET-003 | 设备按项目查询 | P0 | 已完成 | 03-ASSET-002 |
| ASSET-004 | 设备按空间查询 | P0 | 已完成 | 03-ASSET-002 |
| ASSET-005 | 设备按类型查询 | P1 | 已完成 | 03-ASSET-002 |
| ASSET-006 | 设备按归属查询 | P1 | 已完成 | 03-ASSET-002 |
| ASSET-007 | 设备按类型统计 | P1 | 已完成 | 03-ASSET-003 |
| ASSET-008 | 设备按归属统计 | P1 | 已完成 | 03-ASSET-003 |
| ASSET-009 | 项目设备总数 | P1 | 已完成 | 03-ASSET-003 |
| ASSET-010 | 电梯扩展表管理 | P0 | 已完成 | 03-ASSET-004 |
| ASSET-011 | 暖通扩展表管理 | P0 | 已完成 | 03-ASSET-004 |
| ASSET-012 | 消防扩展表管理 | P0 | 已完成 | 03-ASSET-004 |
| ASSET-013 | 能源计量扩展表管理 | P0 | 已完成 | 03-ASSET-004 |
| ASSET-014 | 设备Excel导入 | P1 | 已完成 | 03-ASSET-005 |
| ASSET-015 | 设备Excel导出 | P1 | 已完成 | 03-ASSET-005 |
| ASSET-016 | 设备健康评分计算 | P1 | Beta | 03-ASSET-006 |
| ASSET-017 | 设备健康历史查询 | P1 | Beta | 03-ASSET-006 |
| ASSET-018 | MTBF计算 | P1 | Beta | 03-ASSET-006 |
| ASSET-019 | MTTR计算 | P1 | Beta | 03-ASSET-006 |
| ASSET-020 | 故障历史记录 | P0 | 已完成 | 03-ASSET-007 |
| ASSET-021 | 故障历史查询 | P0 | 已完成 | 03-ASSET-007 |
| ASSET-022 | 归属主体CRUD | P1 | 已完成 | 03-ASSET-008 |
| ASSET-023 | 归属主体按类型查询 | P1 | 已完成 | 03-ASSET-008 |
| ASSET-024 | 设备照片管理 | P2 | 已完成 | 03-ASSET-009 |
| ASSET-025 | 设备文档管理 | P2 | 已完成 | 03-ASSET-009 |
| ASSET-026 | 设备二维码 | P2 | 未实现 | 03-ASSET-010 |
| ASSET-027 | IoT集成 | P3 | 未实现 | 03-ASSET-011 |
| ASSET-028 | 故障自动工单(事件驱动) | P2 | 未实现 | 03-ASSET-012 |
| ASSET-029 | 维保到期定时提醒 | P2 | 未实现 | 03-ASSET-013 |
---
## 二、数据结构设计
### 2.1 实体定义
#### 2.1.1 Equipment设备主表
**表名**: `asset_equipment`
**实体类**: `com.ether.pms.asset.entity.Equipment`
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | UUID | 是 | 自动生成 | 主键 |
| projectId | UUID | 是 | - | 所属项目ID |
| spaceNodeId | UUID | 否 | - | 关联空间节点ID |
| equipmentCode | VARCHAR(50) | 是 | - | 设备编码,全局唯一 |
| equipmentName | VARCHAR(100) | 是 | - | 设备名称 |
| equipmentType | VARCHAR(30) | 是 | - | 设备类型枚举10种 |
| equipmentCategory | VARCHAR(50) | 否 | - | 设备分类 |
| systemType | VARCHAR(50) | 否 | - | 系统类型枚举9种 |
| ownershipType | VARCHAR(20) | 是 | PROJECT | 归属类型枚举4种 |
| owningEntityId | UUID | 否 | - | 归属主体ID |
| owningEntityName | VARCHAR(100) | 否 | - | 归属主体名称(冗余) |
| assetCode | VARCHAR(50) | 否 | - | 资产编号 |
| serialNumber | VARCHAR(100) | 否 | - | 出厂编号 |
| model | VARCHAR(100) | 否 | - | 型号 |
| manufacturer | VARCHAR(100) | 否 | - | 厂商 |
| supplier | VARCHAR(100) | 否 | - | 供应商 |
| status | VARCHAR(20) | 是 | ACTIVE | 设备状态枚举4种 |
| operationStatus | VARCHAR(20) | 否 | - | 运行状态 |
| installationLocation | VARCHAR(200) | 否 | - | 安装位置 |
| installationDate | DATE | 否 | - | 安装日期 |
| designLifeYears | INTEGER | 否 | - | 设计寿命(年) |
| ratedPower | DECIMAL(10,2) | 否 | - | 额定功率(kW) |
| ratedVoltage | VARCHAR(20) | 否 | - | 额定电压(V) |
| ratedCurrent | DECIMAL(10,2) | 否 | - | 额定电流(A) |
| maintenanceVendor | VARCHAR(100) | 否 | - | 维保商 |
| maintenanceVendorContact | VARCHAR(50) | 否 | - | 维保联系人 |
| maintenanceVendorPhone | VARCHAR(20) | 否 | - | 维保电话 |
| maintenanceContractNo | VARCHAR(50) | 否 | - | 维保合同编号 |
| maintenanceContractStart | DATE | 否 | - | 维保合同开始日期 |
| maintenanceContractEnd | DATE | 否 | - | 维保合同结束日期 |
| purchaseDate | DATE | 否 | - | 购置日期 |
| purchasePrice | DECIMAL(12,2) | 否 | - | 购置价格(元) |
| warrantyExpireDate | DATE | 否 | - | 保修到期日期 |
| energyConsumptionStandard | DECIMAL(12,2) | 否 | - | 能耗标准(kW*h/年) |
| inspectionCycle | INTEGER | 否 | - | 年检周期(月) |
| nextInspectionDate | DATE | 否 | - | 下次年检日期 |
| lastInspectionDate | DATE | 否 | - | 上次年检日期 |
| lastInspectionResult | VARCHAR(20) | 否 | - | 上次年检结果 |
| specialEquipmentType | VARCHAR(50) | 否 | - | 特种设备类型 |
| specialEquipmentCert | VARCHAR(100) | 否 | - | 特种设备证书 |
| attributes | JSON/TEXT | 否 | - | 扩展属性(JSON) |
| photos | JSONB | 否 | - | 设备照片列表(List\<EquipmentPhoto\>) |
| documents | JSONB | 否 | - | 电子文档列表(List\<EquipmentDocument\>) |
| manualUrl | VARCHAR(500) | 否 | - | 手册URL |
| remarks | VARCHAR(1000) | 否 | - | 备注 |
| isDeleted | BOOLEAN | 否 | false | 逻辑删除标记 |
| createdAt | DATETIME | 是 | now() | 创建时间 |
| updatedAt | DATETIME | 是 | now() | 更新时间 |
| createdBy | UUID | 否 | - | 创建人 |
| updatedBy | UUID | 否 | - | 更新人 |
**索引**:
| 索引名 | 字段 | 类型 | 用途 |
|--------|------|------|------|
| idx_equipment_project | project_id | 普通索引 | 按项目查询 |
| idx_equipment_space | space_node_id | 普通索引 | 按空间查询 |
| idx_equipment_type | equipment_type | 普通索引 | 按类型查询 |
| idx_equipment_ownership | ownership_type | 普通索引 | 按归属查询 |
| idx_equipment_code | equipment_code | 唯一索引 | 编码唯一性 |
| idx_equipment_status | status | 普通索引 | 按状态查询 |
| idx_eq_project_status | project_id, status | 联合索引 | 项目+状态组合查询 |
| idx_eq_project_type | project_id, equipment_type | 联合索引 | 项目+类型组合查询 |
| idx_eq_project_deleted | project_id, is_deleted | 联合索引 | 项目+未删除组合查询 |
**内嵌类型**:
EquipmentPhoto设备照片:
| 字段 | 类型 | 说明 |
|------|------|------|
| type | String | 照片类型:外观/铭牌/安装位置/环境 |
| url | String | 照片URL |
| remark | String | 备注 |
EquipmentDocument电子文档:
| 字段 | 类型 | 说明 |
|------|------|------|
| name | String | 文档名称 |
| url | String | 文档URL |
| size | Long | 文件大小 |
| type | String | 文档类型manual/certificate/contract/other |
| remark | String | 备注 |
#### 2.1.2 EquipmentElevator电梯扩展表
**表名**: `asset_equipment_elevator`
**实体类**: `com.ether.pms.asset.entity.EquipmentElevator`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | 是 | 主键 |
| equipmentId | UUID | 是 | 关联设备IDUNIQUE外键 |
| elevatorType | VARCHAR(30) | 否 | 电梯类型 |
| elevatorModel | VARCHAR(50) | 否 | 电梯型号 |
| loadCapacity | INTEGER | 否 | 载重(kg) |
| speed | DECIMAL(10,2) | 否 | 速度(m/s) |
| floorCount | INTEGER | 否 | 楼层数 |
| shaftDimensions | VARCHAR(50) | 否 | 井道尺寸 |
| pitDepth | DECIMAL(10,2) | 否 | 底坑深度 |
| overheadHeight | DECIMAL(10,2) | 否 | 顶层高度 |
| registrationNo | VARCHAR(50) | 否 | 注册登记号 |
| inspectionCertificate | VARCHAR(100) | 否 | 检验证书 |
| nextInspectionDate | DATE | 否 | 下次检验日期 |
| energyConsumption | DECIMAL(12,2) | 否 | 能耗 |
| maintenanceLevel | VARCHAR(20) | 否 | 维保等级 |
| rescuePlan | VARCHAR(5000) | 否 | 应急救援预案 |
| createdAt | DATETIME | 否 | 创建时间 |
| updatedAt | DATETIME | 否 | 更新时间 |
#### 2.1.3 EquipmentHvac暖通空调扩展表
**表名**: `asset_equipment_hvac`
**实体类**: `com.ether.pms.asset.entity.EquipmentHvac`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | 是 | 主键 |
| equipmentId | UUID | 是 | 关联设备IDUNIQUE外键 |
| hvacType | VARCHAR(30) | 否 | 暖通类型 |
| coolingCapacity | DECIMAL(12,2) | 否 | 制冷量 |
| heatingCapacity | DECIMAL(12,2) | 否 | 制热量 |
| airFlow | DECIMAL(12,2) | 否 | 风量 |
| refrigerantType | VARCHAR(30) | 否 | 制冷剂类型 |
| refrigerantCharge | DECIMAL(10,2) | 否 | 制冷剂充注量 |
| energyEfficiencyRatio | DECIMAL(10,2) | 否 | 能效比(EER) |
| coefficientOfPerformance | DECIMAL(10,2) | 否 | 性能系数(COP) |
| installationDate | DATE | 否 | 安装日期 |
| warrantyExpireDate | DATE | 否 | 保修到期日期 |
| filterReplacementCycle | INTEGER | 否 | 滤网更换周期 |
| lastFilterReplacement | DATE | 否 | 上次滤网更换日期 |
| ductType | VARCHAR(30) | 否 | 风管类型 |
| ductDimensions | VARCHAR(50) | 否 | 风管尺寸 |
| createdAt | DATETIME | 否 | 创建时间 |
| updatedAt | DATETIME | 否 | 更新时间 |
#### 2.1.4 EquipmentFire消防扩展表
**表名**: `asset_equipment_fire`
**实体类**: `com.ether.pms.asset.entity.EquipmentFire`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | 是 | 主键 |
| equipmentId | UUID | 是 | 关联设备IDUNIQUE外键 |
| fireEquipmentType | VARCHAR(30) | 否 | 消防设备类型 |
| installationArea | DECIMAL(10,2) | 否 | 安装面积 |
| installationHeight | DECIMAL(10,2) | 否 | 安装高度 |
| detectionRange | DECIMAL(10,2) | 否 | 探测范围 |
| systemType | VARCHAR(30) | 否 | 系统类型 |
| zoneNumber | VARCHAR(20) | 否 | 分区编号 |
| loopNumber | VARCHAR(20) | 否 | 回路编号 |
| linkageEnabled | BOOLEAN | 否 | 是否启用联动 |
| linkageAction | VARCHAR(100) | 否 | 联动动作 |
| inspectionCycle | INTEGER | 否 | 巡检周期 |
| lastInspectionDate | DATE | 否 | 上次巡检日期 |
| nextInspectionDate | DATE | 否 | 下次巡检日期 |
| inspectionResult | VARCHAR(20) | 否 | 巡检结果 |
| specialRequirement | VARCHAR(2000) | 否 | 特殊要求 |
| createdAt | DATETIME | 否 | 创建时间 |
| updatedAt | DATETIME | 否 | 更新时间 |
#### 2.1.5 EquipmentEnergy能源计量扩展表
**表名**: `asset_equipment_energy`
**实体类**: `com.ether.pms.asset.entity.EquipmentEnergy`
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | 是 | 主键 |
| equipmentId | UUID | 是 | 关联设备IDUNIQUE外键 |
| meterType | VARCHAR(30) | 否 | 表计类型 |
| energyType | VARCHAR(30) | 否 | 能源类型 |
| meterModel | VARCHAR(50) | 否 | 表计型号 |
| meterSpecification | VARCHAR(50) | 否 | 表计规格 |
| meterConstant | DECIMAL(10,4) | 否 | 表常数 |
| accuracyClass | VARCHAR(10) | 否 | 精度等级 |
| readingType | VARCHAR(20) | 否 | 抄表方式 |
| lastReadingDate | DATE | 否 | 上次抄表日期 |
| lastReadingValue | DECIMAL(12,2) | 否 | 上次读数 |
| currentReadingValue | DECIMAL(12,2) | 否 | 当前读数 |
| unitPrice | DECIMAL(10,4) | 否 | 单价 |
| billingType | VARCHAR(20) | 否 | 计费方式 |
| communicationType | VARCHAR(30) | 否 | 通讯方式 |
| communicationAddress | VARCHAR(50) | 否 | 通讯地址 |
| verificationCycle | INTEGER | 否 | 检定周期 |
| nextVerificationDate | DATE | 否 | 下次检定日期 |
| verificationCertificate | VARCHAR(100) | 否 | 检定证书 |
| createdAt | DATETIME | 否 | 创建时间 |
| updatedAt | DATETIME | 否 | 更新时间 |
#### 2.1.6 EquipmentHealthScore健康评分表
**表名**: `ops_equipment_health_score`
**实体类**: `com.ether.pms.asset.entity.EquipmentHealthScore`
**状态**: Beta -- 数据准确性待验证
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| id | UUID | 是 | 主键 |
| projectId | UUID | 是 | 项目ID |
| equipmentId | UUID | 是 | 设备ID |
| equipmentCode | VARCHAR(50) | 否 | 设备编码(冗余) |
| equipmentName | VARCHAR(100) | 否 | 设备名称(冗余) |
| healthScore | DECIMAL(5,2) | 是 | 健康度评分(0-100) |
| failureDeduction | DECIMAL(5,2) | 否 | 故障扣分 |
| maintenanceDeduction | DECIMAL(5,2) | 否 | 维保扣分 |
| ageDeduction | DECIMAL(5,2) | 否 | 年龄扣分 |
| failureCount30d | INTEGER | 否 | 近30天故障次数 |
| maintenanceCompletionRate | DECIMAL(5,4) | 否 | 维保完成率 |
| equipmentAgeYears | DECIMAL(10,2) | 否 | 设备年龄(年) |
| operationHours30d | DECIMAL(12,2) | 否 | 近30天运行时长 |
| mtbfHours | DECIMAL(12,2) | 否 | MTBF(小时) |
| mttrHours | DECIMAL(12,2) | 否 | MTTR(小时) |
| healthLevel | VARCHAR(20) | 否 | 健康等级枚举5级 |
| calculatedAt | DATETIME | 是 | 计算时间 |
| calculationPeriodDays | INTEGER | 否 | 计算周期天数 |
| remarks | VARCHAR(1000) | 否 | 备注 |
| createdAt | DATETIME | 否 | 创建时间 |
| updatedAt | DATETIME | 否 | 更新时间 |
**索引**:
| 索引名 | 字段 | 用途 |
|--------|------|------|
| idx_health_equipment | equipment_id | 按设备查询 |
| idx_health_calc_time | calculated_at | 按计算时间查询 |
| idx_health_project | project_id | 按项目查询 |
#### 2.1.7 EquipmentFailureHistory故障历史表
**表名**: `ops_equipment_failure_history`
**实体类**: `com.ether.pms.asset.entity.EquipmentFailureHistory`
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | UUID | 是 | 自动生成 | 主键 |
| projectId | UUID | 是 | - | 项目ID |
| equipmentId | UUID | 是 | - | 设备ID |
| equipmentCode | VARCHAR(50) | 否 | - | 设备编码(冗余) |
| equipmentName | VARCHAR(100) | 否 | - | 设备名称(冗余) |
| failureTime | DATETIME | 是 | - | 故障时间 |
| failureType | VARCHAR(50) | 否 | - | 故障类型枚举4种 |
| failureLevel | VARCHAR(20) | 否 | - | 故障等级枚举4级 |
| failureReason | VARCHAR(2000) | 否 | - | 故障原因 |
| failureDescription | VARCHAR(2000) | 否 | - | 故障描述 |
| repairStartTime | DATETIME | 否 | - | 修复开始时间 |
| repairEndTime | DATETIME | 否 | - | 修复结束时间 |
| repairDurationHours | DOUBLE | 否 | 自动计算 | 修复时长(小时) |
| repairPerson | VARCHAR(100) | 否 | - | 修复人 |
| repairResult | VARCHAR(20) | 否 | - | 修复结果枚举4种 |
| downtimeHours | DOUBLE | 否 | 自动计算 | 停机时长(小时) |
| maintenanceCost | DECIMAL(12,2) | 否 | - | 维修费用 |
| isScheduled | BOOLEAN | 是 | false | 是否计划停机 |
| relatedTaskId | UUID | 否 | - | 关联工单ID |
| remarks | VARCHAR(1000) | 否 | - | 备注 |
| createdAt | DATETIME | 否 | - | 创建时间 |
| updatedAt | DATETIME | 否 | - | 更新时间 |
| createdBy | UUID | 否 | - | 创建人 |
**索引**:
| 索引名 | 字段 | 用途 |
|--------|------|------|
| idx_failure_equipment | equipment_id | 按设备查询 |
| idx_failure_time | failure_time | 按时间查询 |
| idx_failure_project | project_id | 按项目查询 |
| idx_efh_project_time | project_id, failure_time | 项目+时间组合查询 |
| idx_efh_equipment_time | equipment_id, failure_time DESC | 设备+时间倒序查询 |
#### 2.1.8 OwnershipEntity归属主体表
**表名**: `asset_ownership_entity`
**实体类**: `com.ether.pms.asset.entity.OwnershipEntity`
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | UUID | 是 | 自动生成 | 主键 |
| entityType | VARCHAR(20) | 是 | - | 主体类型枚举3种 |
| entityName | VARCHAR(100) | 是 | - | 主体名称 |
| entityCode | VARCHAR(50) | 否 | - | 主体编码 |
| contactPerson | VARCHAR(50) | 否 | - | 联系人 |
| contactPhone | VARCHAR(20) | 否 | - | 联系电话 |
| contactAddress | VARCHAR(255) | 否 | - | 联系地址 |
| businessLicense | VARCHAR(50) | 否 | - | 营业执照号 |
| legalRepresentative | VARCHAR(50) | 否 | - | 法人代表 |
| contractNo | VARCHAR(50) | 否 | - | 合同编号 |
| contractStartDate | DATE | 否 | - | 合同开始日期 |
| contractEndDate | DATE | 否 | - | 合同结束日期 |
| rentalFee | DECIMAL(12,2) | 否 | - | 租赁费用 |
| status | VARCHAR(20) | 否 | ACTIVE | 状态 |
| isDeleted | BOOLEAN | 否 | false | 逻辑删除 |
| createdAt | DATETIME | 否 | - | 创建时间 |
| updatedAt | DATETIME | 否 | - | 更新时间 |
**索引**:
| 索引名 | 字段 | 用途 |
|--------|------|------|
| idx_ownership_entity_type | entity_type | 按类型查询 |
| idx_ownership_entity_code | entity_code | 按编码查询 |
### 2.2 枚举定义
#### EquipmentType设备类型 -- 10种
| 枚举值 | 中文 | 对应扩展表 | 说明 |
|--------|------|------------|------|
| ELEVATOR | 电梯系统 | EquipmentElevator | 含载重/速度/注册号/检验证书/应急救援预案 |
| HVAC | 暖通空调 | EquipmentHvac | 含制冷/制热量/制冷剂/能效比(EER)/性能系数(COP) |
| FIRE_PROTECTION | 消防系统 | EquipmentFire | 含探测范围/分区/回路编号/联动控制/巡检周期 |
| ENERGY_METER | 能源计量 | EquipmentEnergy | 含表常数/精度等级/通讯方式/检定周期 |
| PLUMBING | 给排水系统 | -- | 使用主表通用字段 + attributes JSON |
| ELECTRICAL | 电气系统 | -- | 使用主表通用字段 + attributes JSON |
| SECURITY | 弱电系统 | -- | 使用主表通用字段 + attributes JSON |
| LANDSCAPE | 景观绿化 | -- | 使用主表通用字段 + attributes JSON |
| KITCHEN | 厨余设备 | -- | 使用主表通用字段 + attributes JSON |
| OTHER | 其他设备 | -- | 使用主表通用字段 + attributes JSON |
#### SystemType系统类型 -- 9种商业地产8大系统+其他)
| 枚举值 | 中文 | 说明 |
|--------|------|------|
| HVAC | 暖通空调 | 对应设备类型 HVAC |
| FIRE | 消防系统 | 对应设备类型 FIRE_PROTECTION |
| ELEVATOR | 电梯系统 | 对应设备类型 ELEVATOR |
| ELECTRICAL | 电气系统 | 对应设备类型 ELECTRICAL |
| PLUMBING | 给排水 | 对应设备类型 PLUMBING |
| BAS | 弱电智能化 | 对应设备类型 SECURITY |
| KITCHEN | 餐饮厨房 | 对应设备类型 KITCHEN |
| LANDSCAPE | 景观 | 对应设备类型 LANDSCAPE |
| OTHER | 其他 | 对应设备类型 OTHER |
#### EquipmentStatus设备状态 -- 4种
| 枚举值 | 中文 | 说明 |
|--------|------|------|
| ACTIVE | 在用 | 设备正常运行 |
| INACTIVE | 停用 | 设备暂停使用 |
| MAINTENANCE | 维保中 | 设备正在维保 |
| SCRAPPED | 已报废 | 设备已报废处理 |
#### OwnershipType归属类型 -- 4种
| 枚举值 | 中文 | 关联主体类型 | 说明 |
|--------|------|-------------|------|
| PROJECT | 项目自有 | 无需关联 | 项目自有的设备 |
| COMPANY | 公司统筹 | EntityType=COMPANY | 公司统一调配的设备 |
| OWNER | 业主自置 | EntityType=OWNER | 业主自行购置的设备 |
| RENTAL | 租赁设备 | EntityType=RENTAL_COMPANY | 租赁使用的设备 |
#### FailureType故障类型 -- 4种
| 枚举值 | 中文 | 说明 |
|--------|------|------|
| SUDDEN | 突发故障 | 非预期的设备故障 |
| SCHEDULED | 计划停机 | 计划内的设备停机 |
| WARNING | 预警 | 设备异常预警 |
| OTHER | 其他 | 其他类型故障 |
#### FailureLevel故障等级 -- 4级
| 枚举值 | 中文 | 典型场景 | 响应时间要求 |
|--------|------|----------|-------------|
| LOW | 轻微 | 指示灯故障、外观损伤 | 48小时内 |
| MEDIUM | 一般 | 单个传感器故障、局部渗漏 | 24小时内 |
| HIGH | 严重 | 主控制器故障、系统部分失效 | 4小时内 |
| CRITICAL | 危急 | 电梯困人、消防系统瘫痪 | 立即响应(30分钟内) |
#### RepairResult修复结果 -- 4种
| 枚举值 | 中文 | 说明 |
|--------|------|------|
| FIXED | 已修复 | 故障已完全修复 |
| PARTIAL_FIXED | 部分修复 | 故障部分修复,需后续跟进 |
| REPLACED | 更换新设备 | 设备整体更换 |
| PENDING | 待处理 | 故障尚未处理 |
#### HealthLevel健康等级 -- 5级
| 枚举值 | 中文 | 分数范围 | 前端颜色 |
|--------|------|----------|----------|
| EXCELLENT | 优秀 | [90, 100) | 绿色 |
| GOOD | 良好 | [75, 90) | 青色 |
| FAIR | 一般 | [60, 75) | 橙色 |
| POOR | 较差 | [40, 60) | 红色 |
| CRITICAL | 危急 | [0, 40) | 红色 |
#### EntityType归属主体类型 -- 3种
| 枚举值 | 中文 | 对应归属类型 |
|--------|------|-------------|
| COMPANY | 公司 | OwnershipType=COMPANY |
| OWNER | 业主 | OwnershipType=OWNER |
| RENTAL_COMPANY | 租赁公司 | OwnershipType=RENTAL |
### 2.3 ER关系图
```mermaid
erDiagram
Equipment ||--o| EquipmentElevator : "1:1 equipmentId"
Equipment ||--o| EquipmentHvac : "1:1 equipmentId"
Equipment ||--o| EquipmentFire : "1:1 equipmentId"
Equipment ||--o| EquipmentEnergy : "1:1 equipmentId"
Equipment ||--o{ EquipmentHealthScore : "1:N equipmentId"
Equipment ||--o{ EquipmentFailureHistory : "1:N equipmentId"
Equipment }o--o| OwnershipEntity : "owningEntityId"
Equipment }o--o| SpaceNode : "spaceNodeId (module-mdm)"
Equipment {
UUID id PK
UUID projectId FK
UUID spaceNodeId FK
String equipmentCode UK
String equipmentName
EquipmentType equipmentType
SystemType systemType
OwnershipType ownershipType
UUID owningEntityId FK
String owningEntityName
EquipmentStatus status
}
EquipmentElevator {
UUID id PK
UUID equipmentId UK_FK
String elevatorType
Integer loadCapacity
BigDecimal speed
String registrationNo
String rescuePlan
}
EquipmentHvac {
UUID id PK
UUID equipmentId UK_FK
String hvacType
BigDecimal coolingCapacity
BigDecimal heatingCapacity
BigDecimal energyEfficiencyRatio
}
EquipmentFire {
UUID id PK
UUID equipmentId UK_FK
String fireEquipmentType
BigDecimal detectionRange
Boolean linkageEnabled
String zoneNumber
}
EquipmentEnergy {
UUID id PK
UUID equipmentId UK_FK
String meterType
String energyType
BigDecimal meterConstant
String accuracyClass
}
EquipmentHealthScore {
UUID id PK
UUID equipmentId FK
BigDecimal healthScore
BigDecimal failureDeduction
BigDecimal maintenanceDeduction
BigDecimal ageDeduction
HealthLevel healthLevel
}
EquipmentFailureHistory {
UUID id PK
UUID equipmentId FK
LocalDateTime failureTime
FailureType failureType
FailureLevel failureLevel
RepairResult repairResult
}
OwnershipEntity {
UUID id PK
EntityType entityType
String entityName
String entityCode
String contactPerson
}
```
---
## 三、API设计
### 3.1 EquipmentController
**基础路径**: `/api/asset/equipment`
**控制器类**: `com.ether.pms.asset.controller.EquipmentController`
#### 设备主表 CRUD
| 方法 | 路径 | 说明 | 请求体 | 响应 | 功能ID |
|------|------|------|--------|------|--------|
| POST | `/` | 创建设备 | Equipment | ApiResponse\<Equipment\> | ASSET-001 |
| GET | `/{id}` | 获取设备详情 | - | ApiResponse\<Equipment\> | ASSET-001 |
| PUT | `/{id}` | 更新设备 | Equipment | ApiResponse\<Equipment\> | ASSET-001 |
| DELETE | `/{id}` | 删除设备(逻辑删除) | - | ApiResponse\<Void\> | ASSET-001 |
| POST | `/batch-delete` | 批量删除 | List\<UUID\> | ApiResponse\<Void\> | ASSET-002 |
#### 设备导入导出
| 方法 | 路径 | 说明 | 请求 | 响应 | 功能ID |
|------|------|------|------|------|--------|
| POST | `/import` | Excel导入 | MultipartFile + projectId | ApiResponse\<Map\<String, Object\>\> | ASSET-014 |
| GET | `/export` | Excel导出 | projectId | ResponseEntity\<byte[]\> | ASSET-015 |
**导入返回结构**:
```json
{
"successCount": 95,
"failCount": 5,
"failDetails": [
{"row": 3, "reason": "设备编码已存在"},
{"row": 7, "reason": "设备类型无效"}
]
}
```
#### 设备查询
| 方法 | 路径 | 说明 | 参数 | 响应 | 功能ID |
|------|------|------|------|------|--------|
| GET | `/by-project/{projectId}` | 按项目查询 | - | ApiResponse\<List\<Equipment\>\> | ASSET-003 |
| GET | `/by-space/{spaceNodeId}` | 按空间查询 | - | ApiResponse\<List\<Equipment\>\> | ASSET-004 |
| GET | `/by-type` | 按类型查询 | type: EquipmentType | ApiResponse\<List\<Equipment\>\> | ASSET-005 |
| GET | `/by-ownership` | 按归属查询 | ownership: OwnershipType | ApiResponse\<List\<Equipment\>\> | ASSET-006 |
#### 设备统计
| 方法 | 路径 | 说明 | 参数 | 响应 | 功能ID |
|------|------|------|------|------|--------|
| GET | `/stats/by-type/{projectId}` | 按类型统计 | - | ApiResponse\<Map\<String, Long\>\> | ASSET-007 |
| GET | `/stats/by-ownership/{projectId}` | 按归属统计 | - | ApiResponse\<Map\<String, Long\>\> | ASSET-008 |
| GET | `/stats/count/{projectId}` | 项目设备总数 | - | ApiResponse\<Long\> | ASSET-009 |
#### 电梯扩展
| 方法 | 路径 | 说明 | 请求体 | 响应 | 功能ID |
|------|------|------|--------|------|--------|
| GET | `/{id}/elevator` | 获取电梯扩展 | - | ApiResponse\<EquipmentElevator\> | ASSET-010 |
| PUT | `/{id}/elevator` | 更新电梯扩展 | EquipmentElevator | ApiResponse\<EquipmentElevator\> | ASSET-010 |
#### 暖通扩展
| 方法 | 路径 | 说明 | 请求体 | 响应 | 功能ID |
|------|------|------|--------|------|--------|
| GET | `/{id}/hvac` | 获取暖通扩展 | - | ApiResponse\<EquipmentHvac\> | ASSET-011 |
| PUT | `/{id}/hvac` | 更新暖通扩展 | EquipmentHvac | ApiResponse\<EquipmentHvac\> | ASSET-011 |
#### 能源计量扩展
| 方法 | 路径 | 说明 | 请求体 | 响应 | 功能ID |
|------|------|------|--------|------|--------|
| GET | `/{id}/energy` | 获取能源扩展 | - | ApiResponse\<EquipmentEnergy\> | ASSET-013 |
| PUT | `/{id}/energy` | 更新能源扩展 | EquipmentEnergy | ApiResponse\<EquipmentEnergy\> | ASSET-013 |
#### 消防扩展
| 方法 | 路径 | 说明 | 请求体 | 响应 | 功能ID |
|------|------|------|--------|------|--------|
| GET | `/{id}/fire` | 获取消防扩展 | - | ApiResponse\<EquipmentFire\> | ASSET-012 |
| PUT | `/{id}/fire` | 更新消防扩展 | EquipmentFire | ApiResponse\<EquipmentFire\> | ASSET-012 |
### 3.2 EquipmentHealthController
**基础路径**: `/api/asset/equipment-health`
**控制器类**: `com.ether.pms.asset.controller.EquipmentHealthController`
| 方法 | 路径 | 说明 | 请求体/参数 | 响应 | 功能ID |
|------|------|------|-------------|------|--------|
| GET | `/{equipmentId}` | 获取最新健康度 | - | ApiResponse\<EquipmentHealthScore\> | ASSET-016 |
| GET | `/{equipmentId}/history` | 健康度历史 | - | ApiResponse\<List\<EquipmentHealthScore\>\> | ASSET-017 |
| POST | `/calculate` | 计算健康度 | { equipmentId: UUID } | ApiResponse\<EquipmentHealthScore\> | ASSET-016 |
| POST | `/failure-history` | 记录故障 | EquipmentFailureHistory | ApiResponse\<EquipmentFailureHistory\> | ASSET-020 |
| GET | `/failure-history/{equipmentId}` | 获取故障历史 | - | ApiResponse\<List\<EquipmentFailureHistory\>\> | ASSET-021 |
| GET | `/mtbf/{equipmentId}` | 计算MTBF | days: Integer (默认30) | ApiResponse\<MTBFResponse\> | ASSET-018 |
| GET | `/mttr/{equipmentId}` | 计算MTTR | days: Integer (默认30) | ApiResponse\<MTTRResponse\> | ASSET-019 |
**请求体定义**:
```java
// 计算健康度请求
CalculateHealthRequest {
@NotNull UUID equipmentId;
}
// MTBF响应
MTBFResponse {
UUID equipmentId;
Integer days;
BigDecimal mtbfHours;
}
// MTTR响应
MTTRResponse {
UUID equipmentId;
Integer days;
BigDecimal mttrHours;
}
```
> 注意: 健康评分相关接口返回时附带 "[Beta] 健康评分数据准确性待验证" 提示信息。
### 3.3 OwnershipEntityController
**基础路径**: `/api/asset/ownership-entity`
**控制器类**: `com.ether.pms.asset.controller.OwnershipEntityController`
| 方法 | 路径 | 说明 | 请求体 | 响应 | 功能ID |
|------|------|------|--------|------|--------|
| POST | `/` | 创建归属主体 | OwnershipEntity | ApiResponse\<OwnershipEntity\> | ASSET-022 |
| GET | `/{id}` | 获取归属主体 | - | ApiResponse\<OwnershipEntity\> | ASSET-022 |
| PUT | `/{id}` | 更新归属主体 | OwnershipEntity | ApiResponse\<OwnershipEntity\> | ASSET-022 |
| DELETE | `/{id}` | 删除归属主体(逻辑删除) | - | ApiResponse\<Void\> | ASSET-022 |
| GET | `/by-type` | 按类型查询 | type: EntityType | ApiResponse\<List\<OwnershipEntity\>\> | ASSET-023 |
| GET | `/` | 获取全部(未删除) | - | ApiResponse\<List\<OwnershipEntity\>\> | ASSET-022 |
> 注意: OwnershipEntityController 直接注入 Repository未经过 Service 层,属于简化实现,后续应重构为标准三层架构。
---
## 四、业务规则
### 4.1 设备分类体系EquipmentType x SystemType矩阵
设备分类采用双维度体系:设备类型(EquipmentType)描述设备专业属性,系统类型(SystemType)描述设备所属的建筑机电系统。
| EquipmentType \ SystemType | HVAC | FIRE | ELEVATOR | ELECTRICAL | PLUMBING | BAS | KITCHEN | LANDSCAPE | OTHER |
|---------------------------|------|------|----------|------------|----------|-----|---------|-----------|-------|
| ELEVATOR | | | V | | | | | | |
| HVAC | V | | | | | | | | |
| FIRE_PROTECTION | | V | | | | | | | |
| ENERGY_METER | | | | V | | | | | |
| PLUMBING | | | | | V | | | | |
| ELECTRICAL | | | | V | | | | | |
| SECURITY | | | | | | V | | | |
| LANDSCAPE | | | | | | | | V | |
| KITCHEN | | | | | | | V | | |
| OTHER | | | | | | | | | V |
**扩展策略**:
- 4种有扩展表的设备类型ELEVATOR/HVAC/FIRE_PROTECTION/ENERGY_METER通过扩展表存储专业参数
- 6种无扩展表的设备类型通过主表的 `attributes` JSON 字段存储额外属性
- 设备类型与系统类型存在对应关系但非严格1:1映射
### 4.2 主表+扩展表模式
**设计原则**:
- 主表(Equipment)存储所有设备类型的公共字段约40个
- 扩展表通过 `equipment_id`UNIQUE约束一对一关联主表
- 扩展表仅存储专业特有字段
- 扩展表的读写通过主设备ID路径`GET /{id}/elevator`、`PUT /{id}/elevator`
**创建设备时扩展表处理规则**:
| 操作 | 规则 |
|------|------|
| 创建设备 | 按equipmentType自动创建对应扩展表记录仅4种有扩展表的类型 |
| 更新设备类型 | 不允许修改equipmentType避免扩展表数据不一致 |
| 删除设备 | 级联删除对应扩展表记录 |
| 读取扩展表 | 通过 `GET /{id}/{type}` 获取不存在返回null |
| 更新扩展表 | 采用saveOrUpdate模式存在则更新不存在则新建 |
**扩展表服务接口模式**(以电梯为例):
```java
public interface EquipmentElevatorService {
Optional<EquipmentElevator> getByEquipmentId(UUID equipmentId);
EquipmentElevator saveOrUpdate(EquipmentElevator elevator);
}
```
### 4.3 归属管理
**4种归属类型**:
| 归属类型 | 说明 | 关联主体 | 维保责任方 |
|----------|------|----------|-----------|
| PROJECT | 项目自有 | 无需关联外部主体 | 项目物业团队 |
| COMPANY | 公司统筹 | 可关联 EntityType=COMPANY 的主体 | 公司指定维保商 |
| OWNER | 业主自置 | 可关联 EntityType=OWNER 的主体 | 业主自行负责或委托 |
| RENTAL | 租赁设备 | 可关联 EntityType=RENTAL_COMPANY 的主体 | 租赁合同约定 |
**归属主体与设备的关联**:
- Equipment 表同时存储 `owningEntityId``owningEntityName`,避免频繁关联查询
- 归属类型与主体类型存在对应关系PROJECT无需关联主体COMPANY对应公司主体OWNER对应业主主体RENTAL对应租赁公司主体
- 归属主体变更时需同步更新 `owningEntityName` 冗余字段
**维保责任划分**:
- PROJECT/COMPANY 归属的设备:由物业方统一安排维保
- OWNER 归属的设备:业主自行负责维保,物业方监督
- RENTAL 归属的设备:按租赁合同约定维保责任方
### 4.4 健康评分算法[Beta]
#### 评分公式
```
健康度 = 基础分(100) - 故障扣分 - 维保扣分 - 年龄扣分
```
即:
```
H = 100 - D_failure - D_maintenance - D_age
```
其中:
- `H` 为健康度评分,范围 [0, 100]
- `D_failure` 为故障扣分
- `D_maintenance` 为维保扣分
- `D_age` 为年龄扣分
#### 三维扣分算法
**1. 故障扣分D_failure**
```
D_failure = N_30d x P_failure
```
| 参数 | 值 | 说明 |
|------|-----|------|
| N_30d | 近30天故障次数 | 从 EquipmentFailureHistory 统计 |
| P_failure | 5 | 每次故障扣5分FAILURE_DEDUCTION_PER_COUNT |
| 上限 | 无 | 故障次数无上限扣分可超过100 |
**2. 维保扣分D_maintenance**
```
D_maintenance = (1 - R_completion) x F_maintenance
```
| 参数 | 值 | 说明 |
|------|-----|------|
| R_completion | 维保完成率 | 范围 [0, 1]当前固定为1.0TODO |
| F_maintenance | 20 | 维保扣分系数MAINTENANCE_DEDUCTION_FACTOR |
| 上限 | 20分 | 最大维保扣分 |
> 当前实现中维保完成率固定为1.0维保扣分始终为0标记为TODO待实现。
**3. 年龄扣分D_age**
```
D_age = min(Y_equipment x P_age, M_age)
```
| 参数 | 值 | 说明 |
|------|-----|------|
| Y_equipment | 设备年龄(年) | 计算方式见下方 |
| P_age | 2 | 每年扣2分AGE_DEDUCTION_PER_YEAR |
| M_age | 10 | 最大年龄扣分MAX_AGE_DEDUCTION |
**设备年龄计算**:
```
Y_equipment = years + months / 12
```
- 优先使用 `installationDate`(安装日期)
- 若无安装日期,使用 `createdAt` 的日期部分
- 均无则返回 0
**最终评分**:
```
H = max(0, 100 - D_failure - D_maintenance - D_age)
```
评分精度保留2位小数四舍五入。
#### MTBF计算平均故障间隔时间
```
MTBF = T_operating / N_failure
```
| 参数 | 说明 |
|------|------|
| T_operating | 运行时间(小时)= 最后故障时间 - 首次故障时间 |
| N_failure | 故障次数 |
**计算规则**:
- 计算周期默认30天可通过 `days` 参数自定义
- 若仅1次故障T_operating 使用 `days x 24` 小时
- 若 T_operating <= 0使用 `days x 24` 小时
- 无故障时返回 0
- 精度保留2位小数
#### MTTR计算平均修复时间
```
MTTR = T_repair_total / N_repair
```
| 参数 | 说明 |
|------|------|
| T_repair_total | 总修复时间(小时)= SUM(repairDurationHours) |
| N_repair | 修复次数 |
**计算规则**:
- 仅统计已完成修复的故障记录repairDurationHours 不为空)
- 无修复记录时返回 0
- 精度保留2位小数
#### 5级等级划分
```java
public static HealthLevel fromScore(BigDecimal score) {
if (score == null) return CRITICAL;
double s = score.doubleValue();
if (s >= 90 && s < 100) return EXCELLENT; // 优秀
if (s >= 75 && s < 90) return GOOD; // 良好
if (s >= 60 && s < 75) return FAIR; // 一般
if (s >= 40 && s < 60) return POOR; // 较差
return CRITICAL; // 危急 [0, 40)
}
```
> 注意score=100 时返回 CRITICAL因为所有区间都是左闭右开 [min, max)100 不在任何区间内。这是当前实现的已知问题。
### 4.5 故障等级体系
#### 4级故障等级
| 等级 | 中文 | 典型场景 | 建议响应时间 | 升级规则 |
|------|------|----------|-------------|---------|
| LOW | 轻微 | 指示灯故障、外观损伤 | 48小时内 | 超过48小时未处理升级为MEDIUM |
| MEDIUM | 一般 | 单个传感器故障、局部渗漏 | 24小时内 | 超过24小时未处理升级为HIGH |
| HIGH | 严重 | 主控制器故障、系统部分失效 | 4小时内 | 超过4小时未处理升级为CRITICAL |
| CRITICAL | 危急 | 电梯困人、消防系统瘫痪 | 30分钟内 | 立即通知项目经理 |
#### 故障记录自动计算
记录故障时自动计算以下字段:
```
repairDurationHours = (repairEndTime - repairStartTime) / 60 (分钟转小时)
downtimeHours = (repairStartTime - failureTime) / 60 (故障到开始修复的时间)
```
**计算条件**:
- repairDurationHours: 仅当 repairStartTime 和 repairEndTime 均不为空时计算
- downtimeHours: 仅当 repairStartTime > failureTime 时计算
### 4.6 特种设备管理
**特种设备识别规则**:
- Equipment 表中 `specialEquipmentType` 不为空时,该设备为特种设备
- 主要涉及:电梯(ELEVATOR)、消防(FIRE_PROTECTION)、压力容器等
**年检提醒机制**:
- `inspectionCycle`年检周期如12表示每年年检一次
- `nextInspectionDate`:下次年检日期
- `lastInspectionDate`:上次年检日期
- `lastInspectionResult`:上次年检结果
**证书管理**:
- `specialEquipmentCert`:特种设备证书编号
- 电梯扩展表:`inspectionCertificate`(检验证书)、`registrationNo`(注册登记号)
- 能源计量扩展表:`verificationCertificate`(检定证书)、`nextVerificationDate`(下次检定日期)
**法规合规**:
- 电梯:需按《特种设备安全法》定期检验,注册登记号唯一
- 消防:需按《消防法》定期巡检,联动系统需定期测试
- 能源计量:需按《计量法》定期检定,精度等级需符合标准
> 当前实现中无后端定时提醒功能,仅前端展示下次年检日期。
### 4.7 设备导入导出
**Excel导入校验规则**:
| 校验项 | 规则 | 错误码 |
|--------|------|--------|
| 文件为空 | file.isEmpty() = true | FILE_001 |
| 文件类型 | 仅支持 .xlsx / .xls | FILE_002 |
| Content-Type | application/vnd.openxmlformats-officedocument.spreadsheetml.sheet 或 application/vnd.ms-excel | FILE_002 |
| 文件扩展名 | .xlsx 或 .xls | FILE_002 |
| 文件大小 | 最大 10MB | FILE_003 |
| 行数限制 | 最大 1000 行 | FILE_004 |
| 文件解析 | Workbook可正常打开 | FILE_001 |
**Excel导出规则**:
- 按项目导出所有未删除设备
- 输出文件名:`设备列表.xlsx`
- Content-Type`application/octet-stream`
---
## 五、执行约束
### 5.1 设备编码唯一性
- `equipmentCode` 字段在数据库层设置 UNIQUE 约束
- 索引 `idx_equipment_code` 确保唯一性
- 创建设备时若编码已存在,数据库将抛出唯一约束异常
- 导入时编码重复将记入 failDetails
### 5.2 扩展表与主表1:1约束
- 扩展表的 `equipment_id` 字段设置 UNIQUE 约束
- 每个设备最多只能有一条对应类型的扩展表记录
- 更新扩展表采用 saveOrUpdate 模式:先查询是否存在,存在则更新,不存在则新建
- 扩展表类型必须与主表 equipmentType 匹配(如不能给电梯设备创建暖通扩展表)
### 5.3 健康评分范围约束
- healthScore 范围为 [0, 100]
- 计算结果低于0时强制设为0
- 精度DECIMAL(5,2)保留2位小数
- HealthLevel.fromScore(null) 返回 CRITICAL
### 5.4 故障时间约束
- `repairStartTime <= repairEndTime`:修复开始时间不能晚于修复结束时间
- `failureTime <= repairStartTime`:故障时间不能晚于修复开始时间
- 当时间约束不满足时对应自动计算字段repairDurationHours/downtimeHours不计算
---
## 六、权限控制
| API路径 | 操作 | 所需权限 | 说明 |
|---------|------|----------|------|
| POST /api/asset/equipment | 创建设备 | asset:equipment:create | 需项目级权限 |
| GET /api/asset/equipment/{id} | 查看设备 | asset:equipment:read | 需项目级权限 |
| PUT /api/asset/equipment/{id} | 更新设备 | asset:equipment:update | 需项目级权限 |
| DELETE /api/asset/equipment/{id} | 删除设备 | asset:equipment:delete | 需项目级权限 |
| POST /api/asset/equipment/batch-delete | 批量删除 | asset:equipment:delete | 需项目级权限 |
| POST /api/asset/equipment/import | 导入设备 | asset:equipment:import | 需项目级权限 |
| GET /api/asset/equipment/export | 导出设备 | asset:equipment:export | 需项目级权限 |
| PUT /api/asset/equipment/{id}/elevator | 更新电梯扩展 | asset:equipment:update | 同设备更新权限 |
| PUT /api/asset/equipment/{id}/hvac | 更新暖通扩展 | asset:equipment:update | 同设备更新权限 |
| PUT /api/asset/equipment/{id}/fire | 更新消防扩展 | asset:equipment:update | 同设备更新权限 |
| PUT /api/asset/equipment/{id}/energy | 更新能源扩展 | asset:equipment:update | 同设备更新权限 |
| POST /api/asset/equipment-health/calculate | 计算健康度 | asset:health:calculate | 需项目级权限 |
| POST /api/asset/equipment-health/failure-history | 记录故障 | asset:failure:create | 需项目级权限 |
| POST /api/asset/ownership-entity | 创建归属主体 | asset:ownership:create | 需系统级权限 |
| PUT /api/asset/ownership-entity/{id} | 更新归属主体 | asset:ownership:update | 需系统级权限 |
| DELETE /api/asset/ownership-entity/{id} | 删除归属主体 | asset:ownership:delete | 需系统级权限 |
> 当前实现中权限控制尚未集成Spring Security以上为设计预期权限矩阵。
---
## 七、例外情况处理
| 例外场景 | 触发条件 | 处理方式 | 错误码 |
|----------|----------|----------|--------|
| 设备编码已存在 | 创建/导入设备时equipmentCode重复 | 抛出数据库唯一约束异常导入时记入failDetails | DB约束 |
| 扩展表类型不匹配 | 给非电梯设备创建电梯扩展表 | 允许创建(当前无校验),建议增加类型匹配校验 | - |
| 健康评分计算数据不足 | 设备无故障历史记录 | MTBF/MTTR返回0维保完成率默认1.0 | - |
| 故障记录关联设备不存在 | equipmentId指向不存在的设备 | 抛出BusinessException("设备不存在") | 6001 |
| 无健康度记录 | 查询设备从未计算过健康度 | 抛出BusinessException("没有健康度记录") | 6003 |
| 导入文件格式错误 | 文件非xlsx/xls格式 | 抛出BusinessException("不支持的文件类型") | FILE_002 |
| 导入文件过大 | 文件超过10MB | 抛出BusinessException("文件大小不能超过10MB") | FILE_003 |
| 导入行数超限 | Excel行数超过1000 | 抛出BusinessException("Excel行数不能超过1000行") | FILE_004 |
| 归属主体不存在 | 更新/删除时ID不存在 | 抛出RuntimeException("归属主体不存在") | - |
| 设备不存在 | 操作的设备ID不存在或已删除 | 抛出BusinessException("设备不存在") | 6001 |
| 导入文件解析失败 | Excel文件损坏 | 抛出BusinessException("文件解析失败") | FILE_001 |
---
**附录:已知代码问题**
| 问题 | 位置 | 影响 | 建议 |
|------|------|------|------|
| HealthLevel.fromScore(100) 返回 CRITICAL | EquipmentHealthScore.HealthLevel | 评分100分的设备被判定为危急 | 修改区间为 [90, 100] 或添加 score==100 特判 |
| 维保完成率固定为1.0 | EquipmentHealthServiceImpl | 维保扣分始终为0 | 对接ops模块查询工单数据计算完成率 |
| OwnershipEntityController绕过Service层 | OwnershipEntityController | 不符合分层架构,缺少业务校验 | 重构为标准三层架构 |
| 前端SystemType与后端不一致 | equipment.ts vs SystemType枚举 | 前端FIRE_PROTECTION vs 后端FIRE | 统一前后端枚举值 |
| 查询接口无分页 | by-project/by-space等 | 数据量大时可能OOM | 改为分页查询 |