1462 lines
41 KiB
Markdown
1462 lines
41 KiB
Markdown
# 设施设备管理增强功能开发计划
|
||
|
||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||
|
||
**Goal:** 实现非居物业设施设备管理增强功能(M02-13~18),包括设备技术参数扩展、预防性维护引擎、能耗监控、备件库存、故障预测、点检标准库
|
||
|
||
**Architecture:** 基于现有 ether-pms 单体架构,在 module-mdm 模块新增设备管理相关实体和服务,前端新增设备管理页面。能耗监控和故障预测作为独立功能模块开发。
|
||
|
||
**Tech Stack:** Spring Boot 3.x + JPA + PostgreSQL + Vue3 + TypeScript + Ant Design Vue
|
||
|
||
---
|
||
|
||
## 开发阶段总览
|
||
|
||
```
|
||
阶段一(M02-13):设备技术参数扩展 - 约3天
|
||
阶段二(M02-14):预防性维护引擎 - 约5天
|
||
阶段三(M02-15):能耗监控管理 - 约4天
|
||
阶段四(M02-16):备件库存管理 - 约4天
|
||
阶段五(M02-17):设备故障预测 - 约3天
|
||
阶段六(M02-18):设备点检标准库 - 约3天
|
||
─────────────────────────────────────────
|
||
总计 约22天
|
||
```
|
||
|
||
---
|
||
|
||
## 阶段一:M02-13 设备技术参数扩展
|
||
|
||
### 数据库迁移
|
||
|
||
**文件:** `ether-pms/src/main/resources/db/migration/V10__add_equipment_extension_fields.sql`
|
||
|
||
```sql
|
||
-- 添加设备扩展字段到 mdm_space_node 表(设备关联空间节点)
|
||
ALTER TABLE mdm_space_node ADD COLUMN design_life_years INTEGER;
|
||
ALTER TABLE mdm_space_node ADD COLUMN rated_power DECIMAL(10,2);
|
||
ALTER TABLE mdm_space_node ADD COLUMN rated_voltage VARCHAR(20);
|
||
ALTER TABLE mdm_space_node ADD COLUMN rated_current DECIMAL(10,2);
|
||
ALTER TABLE mdm_space_node ADD COLUMN maintenance_vendor VARCHAR(100);
|
||
ALTER TABLE mdm_space_node ADD COLUMN maintenance_vendor_contact VARCHAR(50);
|
||
ALTER TABLE mdm_space_node ADD COLUMN maintenance_vendor_phone VARCHAR(20);
|
||
ALTER TABLE mdm_space_node ADD COLUMN maintenance_contract_no VARCHAR(50);
|
||
ALTER TABLE mdm_space_node ADD COLUMN maintenance_contract_start DATE;
|
||
ALTER TABLE mdm_space_node ADD COLUMN maintenance_contract_end DATE;
|
||
ALTER TABLE mdm_space_node ADD COLUMN special_equipment_type VARCHAR(50);
|
||
ALTER TABLE mdm_space_node ADD COLUMN special_equipment_cert VARCHAR(100);
|
||
ALTER TABLE mdm_space_node ADD COLUMN inspection_cycle INTEGER;
|
||
ALTER TABLE mdm_space_node ADD COLUMN next_inspection_date DATE;
|
||
ALTER TABLE mdm_space_node ADD COLUMN last_inspection_date DATE;
|
||
ALTER TABLE mdm_space_node ADD COLUMN last_inspection_result VARCHAR(20);
|
||
ALTER TABLE mdm_space_node ADD COLUMN common_spare_parts JSONB;
|
||
ALTER TABLE mdm_space_node ADD COLUMN energy_consumption_standard DECIMAL(12,2);
|
||
ALTER TABLE mdm_space_node ADD COLUMN installation_environment VARCHAR(50);
|
||
ALTER TABLE mdm_space_node ADD COLUMN protection_level VARCHAR(20);
|
||
```
|
||
|
||
---
|
||
|
||
### Task 1.1: 创建设备分类枚举
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/enums/EquipmentCategory.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.enums;
|
||
|
||
public enum EquipmentCategory {
|
||
HVAC("暖通空调"),
|
||
ELECTRICAL("电气设备"),
|
||
FIRE("消防设备"),
|
||
ELEVATOR("电梯设备"),
|
||
SECURITY("安防设备"),
|
||
给排水("给排水设备"),
|
||
LIGHTING("照明设备"),
|
||
SPECIAL("特种设备");
|
||
|
||
private final String desc;
|
||
EquipmentCategory(String desc) { this.desc = desc; }
|
||
public String getDesc() { return desc; }
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建枚举类
|
||
**Step 2:** 验证编译通过
|
||
**Step 3:** Commit: `feat: add equipment category enum`
|
||
|
||
---
|
||
|
||
### Task 1.2: 创建设备类型枚举
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/enums/EquipmentType.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.enums;
|
||
|
||
public enum EquipmentType {
|
||
CENTRAL_AC("中央空调", EquipmentCategory.HVAC),
|
||
AIR_CONDITIONER("分体空调", EquipmentCategory.HVAC),
|
||
AIR_HANDLING_UNIT("空气处理机组", EquipmentCategory.HVAC),
|
||
FAN_COIL("风机盘管", EquipmentCategory.HVAC),
|
||
LOW_VOLTAGE_CABINET("低压配电柜", EquipmentCategory.ELECTRICAL),
|
||
TRANSFORMER("变压器", EquipmentCategory.ELECTRICAL),
|
||
GENERATOR("发电机", EquipmentCategory.ELECTRICAL),
|
||
UPS("不间断电源", EquipmentCategory.ELECTRICAL),
|
||
FIRE_PUMP("消防泵", EquipmentCategory.FIRE),
|
||
SPRINKLER("喷淋系统", EquipmentCategory.FIRE),
|
||
FIRE_ALARM("火灾报警系统", EquipmentCategory.FIRE),
|
||
ELEVATOR("电梯", EquipmentCategory.ELEVATOR),
|
||
CCTV("监控系统", EquipmentCategory.SECURITY),
|
||
ACCESS_CONTROL("门禁系统", EquipmentCategory.SECURITY),
|
||
WATER_PUMP("给水泵", EquipmentCategory.WATER_DRAINAGE),
|
||
DRAINAGE_PUMP("排水泵", EquipmentCategory.WATER_DRAINAGE),
|
||
LED_LIGHT("LED灯具", EquipmentCategory.LIGHTING),
|
||
HIGH_BAY_LIGHT("工矿灯", EquipmentCategory.LIGHTING);
|
||
|
||
private final String desc;
|
||
private final EquipmentCategory category;
|
||
EquipmentType(String desc, EquipmentCategory category) {
|
||
this.desc = desc;
|
||
this.category = category;
|
||
}
|
||
public String getDesc() { return desc; }
|
||
public EquipmentCategory getCategory() { return category; }
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建枚举类
|
||
**Step 2:** 验证编译通过
|
||
**Step 3:** Commit: `feat: add equipment type enum`
|
||
|
||
---
|
||
|
||
### Task 1.3: 更新SpaceNode实体
|
||
|
||
**Files:**
|
||
- Modify: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/SpaceNode.java`
|
||
|
||
在现有实体末尾添加扩展字段:
|
||
|
||
```java
|
||
// ========== 设备扩展字段 ==========
|
||
@Column(name = "is_equipment")
|
||
private Boolean isEquipment = false;
|
||
|
||
@Column(name = "design_life_years")
|
||
private Integer designLifeYears;
|
||
|
||
@Column(name = "rated_power", precision = 10, scale = 2)
|
||
private BigDecimal ratedPower;
|
||
|
||
@Column(name = "rated_voltage", length = 20)
|
||
private String ratedVoltage;
|
||
|
||
@Column(name = "rated_current", precision = 10, scale = 2)
|
||
private BigDecimal ratedCurrent;
|
||
|
||
@Column(name = "maintenance_vendor", length = 100)
|
||
private String maintenanceVendor;
|
||
|
||
@Column(name = "maintenance_vendor_contact", length = 50)
|
||
private String maintenanceVendorContact;
|
||
|
||
@Column(name = "maintenance_vendor_phone", length = 20)
|
||
private String maintenanceVendorPhone;
|
||
|
||
@Column(name = "maintenance_contract_no", length = 50)
|
||
private String maintenanceContractNo;
|
||
|
||
@Column(name = "maintenance_contract_start")
|
||
private LocalDate maintenanceContractStart;
|
||
|
||
@Column(name = "maintenance_contract_end")
|
||
private LocalDate maintenanceContractEnd;
|
||
|
||
@Column(name = "special_equipment_type", length = 50)
|
||
private String specialEquipmentType;
|
||
|
||
@Column(name = "special_equipment_cert", length = 100)
|
||
private String specialEquipmentCert;
|
||
|
||
@Column(name = "inspection_cycle")
|
||
private Integer inspectionCycle;
|
||
|
||
@Column(name = "next_inspection_date")
|
||
private LocalDate nextInspectionDate;
|
||
|
||
@Column(name = "last_inspection_date")
|
||
private LocalDate lastInspectionDate;
|
||
|
||
@Column(name = "last_inspection_result", length = 20)
|
||
private String lastInspectionResult;
|
||
|
||
@Column(name = "common_spare_parts", columnDefinition = "TEXT")
|
||
private String commonSpareParts;
|
||
|
||
@Column(name = "energy_consumption_standard", precision = 12, scale = 2)
|
||
private BigDecimal energyConsumptionStandard;
|
||
|
||
@Column(name = "installation_environment", length = 50)
|
||
private String installationEnvironment;
|
||
|
||
@Column(name = "protection_level", length = 20)
|
||
private String protectionLevel;
|
||
// ========== 设备扩展字段结束 ==========
|
||
```
|
||
|
||
**Step 1:** 添加扩展字段到 SpaceNode 实体
|
||
**Step 2:** 运行 `cd ether-pms && mvn compile` 验证
|
||
**Step 3:** Commit: `feat: add equipment extension fields to SpaceNode`
|
||
|
||
---
|
||
|
||
### Task 1.4: 创建SpaceNode DTO
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/dto/SpaceNodeEquipmentDTO.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.dto;
|
||
|
||
import lombok.Data;
|
||
import lombok.EqualsAndHashCode;
|
||
import java.math.BigDecimal;
|
||
import java.time.LocalDate;
|
||
import java.util.List;
|
||
|
||
@Data
|
||
@EqualsAndHashCode(callSuper = true)
|
||
public class SpaceNodeEquipmentDTO extends SpaceNodeDTO {
|
||
|
||
private Boolean isEquipment;
|
||
private Integer designLifeYears;
|
||
private BigDecimal ratedPower;
|
||
private String ratedVoltage;
|
||
private BigDecimal ratedCurrent;
|
||
private String maintenanceVendor;
|
||
private String maintenanceVendorContact;
|
||
private String maintenanceVendorPhone;
|
||
private String maintenanceContractNo;
|
||
private LocalDate maintenanceContractStart;
|
||
private LocalDate maintenanceContractEnd;
|
||
private String specialEquipmentType;
|
||
private String specialEquipmentCert;
|
||
private Integer inspectionCycle;
|
||
private LocalDate nextInspectionDate;
|
||
private LocalDate lastInspectionDate;
|
||
private String lastInspectionResult;
|
||
private List<SparePartInfo> commonSpareParts;
|
||
private BigDecimal energyConsumptionStandard;
|
||
private String installationEnvironment;
|
||
private String protectionLevel;
|
||
|
||
@Data
|
||
public static class SparePartInfo {
|
||
private String name;
|
||
private String model;
|
||
private Integer quantity;
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建 DTO 类
|
||
**Step 2:** 运行 `cd ether-pms && mvn compile` 验证
|
||
**Step 3:** Commit: `feat: add SpaceNodeEquipmentDTO`
|
||
|
||
---
|
||
|
||
### Task 1.5: 更新SpaceNodeService
|
||
|
||
**Files:**
|
||
- Modify: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/SpaceNodeService.java`
|
||
|
||
添加设备相关方法:
|
||
|
||
```java
|
||
public SpaceNodeEquipmentDTO getEquipmentById(UUID id) {
|
||
SpaceNode node = spaceNodeRepository.findById(id)
|
||
.orElseThrow(() -> new BusinessException("EQUIPMENT_NOT_FOUND"));
|
||
return convertToEquipmentDTO(node);
|
||
}
|
||
|
||
public List<SpaceNodeEquipmentDTO> getSpecialEquipmentList(UUID projectId) {
|
||
List<SpaceNode> list = spaceNodeRepository.findByProjectIdAndIsEquipmentAndSpecialEquipmentTypeIsNotNull(
|
||
projectId, true);
|
||
return list.stream().map(this::convertToEquipmentDTO).collect(Collectors.toList());
|
||
}
|
||
|
||
public List<SpaceNodeEquipmentDTO> getExpiringInspectionEquipment(UUID projectId, Integer daysAhead) {
|
||
LocalDate threshold = LocalDate.now().plusDays(daysAhead);
|
||
List<SpaceNode> list = spaceNodeRepository
|
||
.findByProjectIdAndIsEquipmentAndNextInspectionDateBefore(projectId, true, threshold);
|
||
return list.stream().map(this::convertToEquipmentDTO).collect(Collectors.toList());
|
||
}
|
||
```
|
||
|
||
**Step 1:** 添加服务方法
|
||
**Step 2:** 添加单元测试
|
||
**Step 3:** 运行测试验证
|
||
**Step 4:** Commit: `feat: add equipment service methods`
|
||
|
||
---
|
||
|
||
### Task 1.6: 更新SpaceNodeController
|
||
|
||
**Files:**
|
||
- Modify: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/controller/SpaceNodeController.java`
|
||
|
||
添加设备相关API:
|
||
|
||
```java
|
||
@GetMapping("/{id}/equipment")
|
||
public ApiResponse<SpaceNodeEquipmentDTO> getEquipment(@PathVariable UUID id) {
|
||
return ApiResponse.success(spaceNodeService.getEquipmentById(id));
|
||
}
|
||
|
||
@GetMapping("/special-equipment")
|
||
public ApiResponse<List<SpaceNodeEquipmentDTO>> getSpecialEquipment(
|
||
@RequestParam UUID projectId) {
|
||
return ApiResponse.success(spaceNodeService.getSpecialEquipmentList(projectId));
|
||
}
|
||
|
||
@GetMapping("/expiring-inspection")
|
||
public ApiResponse<List<SpaceNodeEquipmentDTO>> getExpiringInspection(
|
||
@RequestParam UUID projectId,
|
||
@RequestParam(defaultValue = "90") Integer daysAhead) {
|
||
return ApiResponse.success(spaceNodeService.getExpiringInspectionEquipment(projectId, daysAhead));
|
||
}
|
||
```
|
||
|
||
**Step 1:** 添加控制器端点
|
||
**Step 2:** 使用 curl 测试端点
|
||
**Step 3:** Commit: `feat: add equipment API endpoints`
|
||
|
||
---
|
||
|
||
### Task 1.7: 前端 - 创建设备管理页面
|
||
|
||
**Files:**
|
||
- Create: `ether-admin/src/views/equipment/EquipmentList.vue`
|
||
- Create: `ether-admin/src/views/equipment/EquipmentDetail.vue`
|
||
- Create: `ether-admin/src/api/equipment.ts`
|
||
|
||
**Step 1:** 创建 API 模块 `ether-admin/src/api/equipment.ts`
|
||
|
||
```typescript
|
||
import request from '@/utils/request'
|
||
|
||
export interface EquipmentForm {
|
||
id?: string
|
||
code: string
|
||
name: string
|
||
nodeType: string
|
||
locationDesc?: string
|
||
designLifeYears?: number
|
||
ratedPower?: number
|
||
ratedVoltage?: string
|
||
maintenanceVendor?: string
|
||
maintenanceVendorPhone?: string
|
||
specialEquipmentType?: string
|
||
inspectionCycle?: number
|
||
nextInspectionDate?: string
|
||
[key: string]: any
|
||
}
|
||
|
||
export function getEquipmentList(params: any) {
|
||
return request({
|
||
url: '/api/v1/mdm/space-nodes/equipment',
|
||
method: 'get',
|
||
params
|
||
})
|
||
}
|
||
|
||
export function getEquipmentDetail(id: string) {
|
||
return request({
|
||
url: `/api/v1/mdm/space-nodes/${id}/equipment`,
|
||
method: 'get'
|
||
})
|
||
}
|
||
|
||
export function getSpecialEquipment(projectId: string) {
|
||
return request({
|
||
url: '/api/v1/mdm/space-nodes/special-equipment',
|
||
method: 'get',
|
||
params: { projectId }
|
||
})
|
||
}
|
||
|
||
export function getExpiringInspection(projectId: string, daysAhead?: number) {
|
||
return request({
|
||
url: '/api/v1/mdm/space-nodes/expiring-inspection',
|
||
method: 'get',
|
||
params: { projectId, daysAhead }
|
||
})
|
||
}
|
||
```
|
||
|
||
**Step 2:** 创建设备列表页面 `EquipmentList.vue`
|
||
|
||
**Step 3:** 创建设备详情页面 `EquipmentDetail.vue`
|
||
|
||
**Step 4:** 运行 `npm run build` 验证前端编译
|
||
|
||
**Step 5:** Commit: `feat: add equipment management pages`
|
||
|
||
---
|
||
|
||
## 阶段二:M02-14 预防性维护引擎
|
||
|
||
### Task 2.1: 创建维保计划实体
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/MaintenancePlan.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.entity;
|
||
|
||
import jakarta.persistence.*;
|
||
import lombok.Data;
|
||
import java.time.LocalDateTime;
|
||
import java.util.UUID;
|
||
|
||
@Entity
|
||
@Table(name = "ops_maintenance_plan")
|
||
@Data
|
||
public class MaintenancePlan {
|
||
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "project_id", nullable = false)
|
||
private UUID projectId;
|
||
|
||
@Column(name = "plan_code", nullable = false, unique = true)
|
||
private String planCode;
|
||
|
||
@Column(name = "plan_name", nullable = false)
|
||
private String planName;
|
||
|
||
@Column(name = "equipment_type")
|
||
private String equipmentType;
|
||
|
||
@Column(name = "trigger_type", nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private TriggerType triggerType;
|
||
|
||
public enum TriggerType {
|
||
TIME_BASED, // 时间触发
|
||
HOURS_BASED, // 运行小时触发
|
||
CYCLES_BASED, // 次数触发
|
||
CONDITION_BASED // 条件触发
|
||
}
|
||
|
||
@Column(name = "trigger_value")
|
||
private Integer triggerValue;
|
||
|
||
@Column(name = "trigger_unit")
|
||
private String triggerUnit;
|
||
|
||
@Column(name = "maintenance_items", columnDefinition = "TEXT")
|
||
private String maintenanceItems;
|
||
|
||
@Column(name = "estimated_duration")
|
||
private Integer estimatedDuration;
|
||
|
||
@Column(name = "assigned_to")
|
||
private UUID assignedTo;
|
||
|
||
@Column(name = "sla_response_hours")
|
||
private Integer slaResponseHours;
|
||
|
||
@Column(name = "sla_complete_hours")
|
||
private Integer slaCompleteHours;
|
||
|
||
@Column(nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private Status status = Status.ACTIVE;
|
||
|
||
public enum Status {
|
||
ACTIVE, INACTIVE
|
||
}
|
||
|
||
@Column(name = "created_at")
|
||
private LocalDateTime createdAt;
|
||
|
||
@Column(name = "updated_at")
|
||
private LocalDateTime updatedAt;
|
||
|
||
@PrePersist
|
||
public void prePersist() {
|
||
createdAt = LocalDateTime.now();
|
||
updatedAt = LocalDateTime.now();
|
||
}
|
||
|
||
@PreUpdate
|
||
public void preUpdate() {
|
||
updatedAt = LocalDateTime.now();
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建实体类
|
||
**Step 2:** 运行 `mvn compile` 验证
|
||
**Step 3:** Commit: `feat: add MaintenancePlan entity`
|
||
|
||
---
|
||
|
||
### Task 2.2: 创建维保任务实体
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/MaintenanceTask.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.entity;
|
||
|
||
import jakarta.persistence.*;
|
||
import lombok.Data;
|
||
import java.math.BigDecimal;
|
||
import java.time.LocalDateTime;
|
||
import java.util.UUID;
|
||
|
||
@Entity
|
||
@Table(name = "ops_maintenance_task")
|
||
@Data
|
||
public class MaintenanceTask {
|
||
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "project_id", nullable = false)
|
||
private UUID projectId;
|
||
|
||
@Column(name = "task_code", nullable = false, unique = true)
|
||
private String taskCode;
|
||
|
||
@Column(name = "plan_id")
|
||
private UUID planId;
|
||
|
||
@Column(name = "equipment_id")
|
||
private UUID equipmentId;
|
||
|
||
@Column(name = "task_type")
|
||
@Enumerated(EnumType.STRING)
|
||
private TaskType taskType = TaskType.PREVENTIVE;
|
||
|
||
public enum TaskType {
|
||
PREVENTIVE, // 预防性维护
|
||
CORRECTIVE // 纠正性维护
|
||
}
|
||
|
||
@Column(name = "trigger_type")
|
||
@Enumerated(EnumType.STRING)
|
||
private MaintenancePlan.TriggerType triggerType;
|
||
|
||
@Column(name = "maintenance_items", columnDefinition = "TEXT")
|
||
private String maintenanceItems;
|
||
|
||
@Column(nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private Status status = Status.PENDING;
|
||
|
||
public enum Status {
|
||
PENDING, // 待接受
|
||
ACCEPTED, // 已接受
|
||
IN_PROGRESS, // 执行中
|
||
COMPLETED, // 已完成
|
||
CANCELLED // 已取消
|
||
}
|
||
|
||
@Column(name = "assigned_to")
|
||
private UUID assignedTo;
|
||
|
||
@Column(name = "scheduled_date")
|
||
private LocalDateTime scheduledDate;
|
||
|
||
@Column(name = "actual_start_date")
|
||
private LocalDateTime actualStartDate;
|
||
|
||
@Column(name = "actual_end_date")
|
||
private LocalDateTime actualEndDate;
|
||
|
||
@Column(name = "labor_hours", precision = 10, scale = 2)
|
||
private BigDecimal laborHours;
|
||
|
||
@Column(name = "materials_cost", precision = 12, scale = 2)
|
||
private BigDecimal materialsCost;
|
||
|
||
@Column(columnDefinition = "TEXT")
|
||
private String remarks;
|
||
|
||
@Column(name = "created_at")
|
||
private LocalDateTime createdAt;
|
||
|
||
@Column(name = "updated_at")
|
||
private LocalDateTime updatedAt;
|
||
|
||
@PrePersist
|
||
public void prePersist() {
|
||
createdAt = LocalDateTime.now();
|
||
updatedAt = LocalDateTime.now();
|
||
}
|
||
|
||
@PreUpdate
|
||
public void preUpdate() {
|
||
updatedAt = LocalDateTime.now();
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建实体类
|
||
**Step 2:** 运行 `mvn compile` 验证
|
||
**Step 3:** Commit: `feat: add MaintenanceTask entity`
|
||
|
||
---
|
||
|
||
### Task 2.3: 创建维保Repository
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/repository/MaintenancePlanRepository.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/repository/MaintenanceTaskRepository.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.repository;
|
||
|
||
public interface MaintenancePlanRepository extends JpaRepository<MaintenancePlan, UUID> {
|
||
List<MaintenancePlan> findByProjectIdAndStatus(UUID projectId, MaintenancePlan.Status status);
|
||
Optional<MaintenancePlan> findByPlanCode(String planCode);
|
||
}
|
||
|
||
public interface MaintenanceTaskRepository extends JpaRepository<MaintenanceTask, UUID> {
|
||
List<MaintenanceTask> findByProjectIdAndStatus(UUID projectId, MaintenanceTask.Status status);
|
||
List<MaintenanceTask> findByAssignedToAndStatus(UUID assignedTo, MaintenanceTask.Status status);
|
||
List<MaintenanceTask> findByEquipmentIdAndStatusNot(UUID equipmentId, MaintenanceTask.Status status);
|
||
Optional<MaintenanceTask> findByTaskCode(String taskCode);
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建 Repository
|
||
**Step 2:** 添加查询方法单元测试
|
||
**Step 3:** Commit: `feat: add maintenance repositories`
|
||
|
||
---
|
||
|
||
### Task 2.4: 创建维保Service
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/MaintenancePlanService.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/MaintenanceTaskService.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/impl/MaintenancePlanServiceImpl.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/impl/MaintenanceTaskServiceImpl.java`
|
||
|
||
**Service核心方法:**
|
||
|
||
```java
|
||
// MaintenancePlanService
|
||
UUID createPlan(MaintenancePlan plan);
|
||
List<MaintenancePlan> getActivePlansByProject(UUID projectId);
|
||
void updatePlan(UUID id, MaintenancePlan plan);
|
||
void deactivatePlan(UUID id);
|
||
|
||
// MaintenanceTaskService
|
||
List<MaintenanceTask> getTasksByAssignee(UUID assignee, String status);
|
||
void acceptTask(UUID taskId, UUID userId);
|
||
void startTask(UUID taskId);
|
||
void completeTask(UUID taskId, BigDecimal laborHours, BigDecimal materialsCost, String remarks);
|
||
List<MaintenanceTask> getOverdueTasks();
|
||
```
|
||
|
||
**Step 1:** 创建 Service 接口和实现
|
||
**Step 2:** 添加单元测试
|
||
**Step 3:** 运行测试验证
|
||
**Step 4:** Commit: `feat: add maintenance service`
|
||
|
||
---
|
||
|
||
### Task 2.5: 创建维保Controller
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/controller/MaintenancePlanController.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/controller/MaintenanceTaskController.java`
|
||
|
||
**API 设计:**
|
||
|
||
| 方法 | 路径 | 描述 |
|
||
|------|------|------|
|
||
| POST | /api/v1/ops/maintenance-plans | 创建维保计划 |
|
||
| GET | /api/v1/ops/maintenance-plans | 获取维保计划列表 |
|
||
| PUT | /api/v1/ops/maintenance-plans/{id} | 更新维保计划 |
|
||
| DELETE | /api/v1/ops/maintenance-plans/{id} | 删除维保计划 |
|
||
| GET | /api/v1/ops/maintenance-tasks | 获取维保任务列表 |
|
||
| POST | /api/v1/ops/maintenance-tasks/{id}/accept | 接受任务 |
|
||
| POST | /api/v1/ops/maintenance-tasks/{id}/start | 开始执行 |
|
||
| POST | /api/v1/ops/maintenance-tasks/{id}/complete | 完成维保 |
|
||
|
||
**Step 1:** 创建 Controller
|
||
**Step 2:** 使用 curl 测试 API
|
||
**Step 3:** Commit: `feat: add maintenance controllers`
|
||
|
||
---
|
||
|
||
### Task 2.6: 创建定时任务 - 维保触发检查
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/scheduler/MaintenanceScheduler.java`
|
||
|
||
```java
|
||
package com.ether.pms.mdm.scheduler;
|
||
|
||
@Component
|
||
@RequiredArgsConstructor
|
||
public class MaintenanceScheduler {
|
||
|
||
private final MaintenancePlanService planService;
|
||
private final MaintenanceTaskService taskService;
|
||
|
||
@Scheduled(cron = "0 0 1 * * ?") // 每天凌晨1点
|
||
public void checkTimeBasedMaintenance() {
|
||
log.info("检查时间触发的维保计划...");
|
||
List<MaintenancePlan> plans = planService.getTimeBasedActivePlans();
|
||
plans.forEach(plan -> taskService.generateTasksFromPlan(plan));
|
||
}
|
||
|
||
@Scheduled(cron = "0 0 * * * ?") // 每小时
|
||
public void checkHourlyMaintenance() {
|
||
log.info("检查运行小时触发的维保计划...");
|
||
// 检查运行小时触发的计划
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建定时任务类
|
||
**Step 2:** 在 PmsApplication 添加 `@EnableScheduling`
|
||
**Step 3:** 测试定时任务执行
|
||
**Step 4:** Commit: `feat: add maintenance scheduler`
|
||
|
||
---
|
||
|
||
## 阶段三:M02-15 能耗监控管理
|
||
|
||
### Task 3.1: 创建能耗相关实体
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/EnergyMeter.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/EnergyConsumption.java`
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_energy_meter")
|
||
@Data
|
||
public class EnergyMeter {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "project_id", nullable = false)
|
||
private UUID projectId;
|
||
|
||
@Column(name = "meter_code", nullable = false, unique = true)
|
||
private String meterCode;
|
||
|
||
@Column(name = "meter_name", nullable = false)
|
||
private String meterName;
|
||
|
||
@Column(name = "energy_type", nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private EnergyType energyType;
|
||
|
||
public enum EnergyType {
|
||
LIGHTING, // 照明插座用电
|
||
HVAC, // 空调用电
|
||
POWER, // 动力用电
|
||
SPECIAL, // 特殊用电
|
||
WATER, // 给排水
|
||
GAS // 燃气
|
||
}
|
||
|
||
@Column(name = "space_node_id")
|
||
private UUID spaceNodeId;
|
||
|
||
@Column(name = "installation_location")
|
||
private String installationLocation;
|
||
|
||
@Column(name = "unit_price", precision = 10, scale = 4)
|
||
private BigDecimal unitPrice;
|
||
|
||
@Column(nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private Status status = Status.ACTIVE;
|
||
|
||
public enum Status { ACTIVE, INACTIVE }
|
||
}
|
||
|
||
@Entity
|
||
@Table(name = "ops_energy_consumption")
|
||
@Data
|
||
public class EnergyConsumption {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "project_id", nullable = false)
|
||
private UUID projectId;
|
||
|
||
@Column(name = "meter_id", nullable = false)
|
||
private UUID meterId;
|
||
|
||
@Column(name = "consumption_date", nullable = false)
|
||
private LocalDate consumptionDate;
|
||
|
||
@Column(name = "previous_reading", precision = 12, scale = 2)
|
||
private BigDecimal previousReading;
|
||
|
||
@Column(name = "current_reading", precision = 12, scale = 2)
|
||
private BigDecimal currentReading;
|
||
|
||
@Column(nullable = false, precision = 12, scale = 2)
|
||
private BigDecimal consumption;
|
||
|
||
@Column(precision = 10, scale = 2)
|
||
private BigDecimal amount;
|
||
|
||
@Column(name = "recorded_by")
|
||
private UUID recordedBy;
|
||
|
||
@Column(name = "record_method")
|
||
@Enumerated(EnumType.STRING)
|
||
private RecordMethod recordMethod = RecordMethod.MANUAL;
|
||
|
||
public enum RecordMethod { MANUAL, IOT }
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建实体
|
||
**Step 2:** 运行编译验证
|
||
**Step 3:** Commit: `feat: add energy management entities`
|
||
|
||
---
|
||
|
||
### Task 3.2: 创建能耗Service
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/EnergyMeterService.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/EnergyConsumptionService.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/EnergyStatisticsService.java`
|
||
|
||
```java
|
||
// EnergyConsumptionService
|
||
void recordConsumption(UUID meterId, BigDecimal currentReading, UUID recordedBy);
|
||
List<EnergyConsumption> getConsumptionByMeter(UUID meterId, LocalDate startDate, LocalDate endDate);
|
||
|
||
// EnergyStatisticsService
|
||
Map<EnergyType, BigDecimal> getConsumptionByType(UUID projectId, LocalDate month);
|
||
BigDecimal getUnitConsumption(UUID projectId, LocalDate month); // kWh/m²
|
||
Map<String, BigDecimal> getConsumptionTrend(UUID projectId, Integer months);
|
||
List<EnergyAlert> getAlerts(UUID projectId);
|
||
```
|
||
|
||
**Step 1:** 创建 Service
|
||
**Step 2:** 添加单元测试
|
||
**Step 3:** Commit: `feat: add energy service`
|
||
|
||
---
|
||
|
||
### Task 3.3: 创建能耗Controller
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/controller/EnergyController.java`
|
||
|
||
**API 设计:**
|
||
|
||
| 方法 | 路径 | 描述 |
|
||
|------|------|------|
|
||
| GET | /api/v1/ops/energy-meters | 获取计量点列表 |
|
||
| POST | /api/v1/ops/energy-meters | 创建计量点 |
|
||
| POST | /api/v1/ops/energy-consumption | 录入能耗数据 |
|
||
| GET | /api/v1/ops/energy-statistics/by-type | 按分项统计 |
|
||
| GET | /api/v1/ops/energy-statistics/unit-consumption | 单方能耗统计 |
|
||
| GET | /api/v1/ops/energy-statistics/trend | 能耗趋势 |
|
||
|
||
**Step 1:** 创建 Controller
|
||
**Step 2:** 测试 API
|
||
**Step 3:** Commit: `feat: add energy controller`
|
||
|
||
---
|
||
|
||
## 阶段四:M02-16 备件库存管理
|
||
|
||
### Task 4.1: 创建备件实体
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/SparePart.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/SparePartRecord.java`
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_spare_part")
|
||
@Data
|
||
public class SparePart {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "project_id", nullable = false)
|
||
private UUID projectId;
|
||
|
||
@Column(name = "spare_part_code", nullable = false, unique = true)
|
||
private String sparePartCode;
|
||
|
||
@Column(name = "spare_part_name", nullable = false)
|
||
private String sparePartName;
|
||
|
||
@Column(name = "category_id")
|
||
private UUID categoryId;
|
||
|
||
@Column
|
||
private String specification;
|
||
|
||
@Column(nullable = false)
|
||
private String unit;
|
||
|
||
@Column(name = "safe_stock")
|
||
private Integer safeStock;
|
||
|
||
@Column(name = "current_stock")
|
||
private Integer currentStock;
|
||
|
||
@Column(name = "unit_price", precision = 10, scale = 2)
|
||
private BigDecimal unitPrice;
|
||
|
||
@Column
|
||
private String supplier;
|
||
|
||
@Column(name = "location")
|
||
private String location;
|
||
|
||
@Column
|
||
@Enumerated(EnumType.STRING)
|
||
private Status status = Status.ACTIVE;
|
||
}
|
||
|
||
@Entity
|
||
@Table(name = "ops_spare_part_record")
|
||
@Data
|
||
public class SparePartRecord {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "record_code", nullable = false, unique = true)
|
||
private String recordCode;
|
||
|
||
@Column(name = "record_type", nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private RecordType recordType;
|
||
|
||
public enum RecordType {
|
||
IN, // 入库
|
||
OUT, // 出库
|
||
CHECK, // 盘点
|
||
ADJUST // 调整
|
||
}
|
||
|
||
@Column(name = "spare_part_id", nullable = false)
|
||
private UUID sparePartId;
|
||
|
||
@Column(nullable = false)
|
||
private Integer quantity;
|
||
|
||
@Column(nullable = false)
|
||
private Integer balance;
|
||
|
||
@Column(name = "related_order_id")
|
||
private UUID relatedOrderId;
|
||
|
||
@Column(name = "recorded_by")
|
||
private UUID recordedBy;
|
||
|
||
@Column(name = "record_date")
|
||
private LocalDateTime recordDate;
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建实体
|
||
**Step 2:** 编译验证
|
||
**Step 3:** Commit: `feat: add spare part entities`
|
||
|
||
---
|
||
|
||
### Task 4.2: 创建备件Service
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/SparePartService.java`
|
||
|
||
```java
|
||
public interface SparePartService {
|
||
SparePart create(SparePart sparePart);
|
||
void updateStock(UUID sparePartId, Integer quantity, SparePartRecord.RecordType type, UUID relatedOrderId);
|
||
List<SparePart> getLowStockParts(UUID projectId);
|
||
List<SparePartRecord> getRecordsByPart(UUID sparePartId);
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建 Service
|
||
**Step 2:** 添加库存扣减逻辑(事务处理)
|
||
**Step 3:** 添加单元测试
|
||
**Step 4:** Commit: `feat: add spare part service`
|
||
|
||
---
|
||
|
||
### Task 4.3: 创建备件Controller
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/controller/SparePartController.java`
|
||
|
||
**API 设计:**
|
||
|
||
| 方法 | 路径 | 描述 |
|
||
|------|------|------|
|
||
| GET | /api/v1/ops/spare-parts | 获取备件列表 |
|
||
| POST | /api/v1/ops/spare-parts | 创建备件 |
|
||
| GET | /api/v1/ops/spare-parts/{id} | 获取备件详情 |
|
||
| GET | /api/v1/ops/spare-parts/low-stock | 获取低库存备件 |
|
||
| POST | /api/v1/ops/spare-part-records | 创建备件记录 |
|
||
| GET | /api/v1/ops/spare-part-records/{sparePartId} | 获取备件记录 |
|
||
|
||
**Step 1:** 创建 Controller
|
||
**Step 2:** 测试 API
|
||
**Step 3:** Commit: `feat: add spare part controller`
|
||
|
||
---
|
||
|
||
## 阶段五:M02-17 设备故障预测
|
||
|
||
### Task 5.1: 创建故障历史实体
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/EquipmentFailureHistory.java`
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/EquipmentHealthScore.java`
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_equipment_failure_history")
|
||
@Data
|
||
public class EquipmentFailureHistory {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "equipment_id", nullable = false)
|
||
private UUID equipmentId;
|
||
|
||
@Column(name = "failure_date", nullable = false)
|
||
private LocalDateTime failureDate;
|
||
|
||
@Column(name = "failure_type")
|
||
private String failureType;
|
||
|
||
@Column(name = "failure_cause")
|
||
private String failureCause;
|
||
|
||
@Column(name = "failure_description", columnDefinition = "TEXT")
|
||
private String failureDescription;
|
||
|
||
@Column(name = "repair_start_time")
|
||
private LocalDateTime repairStartTime;
|
||
|
||
@Column(name = "repair_end_time")
|
||
private LocalDateTime repairEndTime;
|
||
|
||
@Column(name = "repair_duration", precision = 10, scale = 2)
|
||
private BigDecimal repairDuration;
|
||
|
||
@Column(name = "repair_cost", precision = 12, scale = 2)
|
||
private BigDecimal repairCost;
|
||
|
||
@Column(name = "spare_parts_used", columnDefinition = "TEXT")
|
||
private String sparePartsUsed;
|
||
|
||
@Column(name = "work_order_id")
|
||
private UUID workOrderId;
|
||
}
|
||
|
||
@Entity
|
||
@Table(name = "ops_equipment_health_score")
|
||
@Data
|
||
public class EquipmentHealthScore {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "equipment_id", nullable = false)
|
||
private UUID equipmentId;
|
||
|
||
@Column(name = "score_date", nullable = false)
|
||
private LocalDate scoreDate;
|
||
|
||
@Column(name = "health_score", precision = 5, scale = 2)
|
||
private BigDecimal healthScore;
|
||
|
||
@Column(precision = 10, scale = 2)
|
||
private BigDecimal mtbf;
|
||
|
||
@Column(precision = 10, scale = 2)
|
||
private BigDecimal mttr;
|
||
|
||
@Column(name = "failure_count")
|
||
private Integer failureCount;
|
||
|
||
@Column(name = "maintenance_completion_rate", precision = 5, scale = 2)
|
||
private BigDecimal maintenanceCompletionRate;
|
||
|
||
@Column(name = "alert_level")
|
||
@Enumerated(EnumType.STRING)
|
||
private AlertLevel alertLevel;
|
||
|
||
public enum AlertLevel { NORMAL, WARNING, CRITICAL }
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建实体
|
||
**Step 2:** 编译验证
|
||
**Step 3:** Commit: `feat: add equipment health entities`
|
||
|
||
---
|
||
|
||
### Task 5.2: 创建故障预测Service
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/EquipmentHealthService.java`
|
||
|
||
```java
|
||
public interface EquipmentHealthService {
|
||
|
||
// 计算设备健康度
|
||
EquipmentHealthScore calculateHealthScore(UUID equipmentId);
|
||
|
||
// 获取设备MTBF
|
||
BigDecimal calculateMTBF(UUID equipmentId, Integer days);
|
||
|
||
// 获取设备MTTR
|
||
BigDecimal calculateMTTR(UUID equipmentId, Integer days);
|
||
|
||
// 获取设备健康度历史
|
||
List<EquipmentHealthScore> getHealthHistory(UUID equipmentId);
|
||
|
||
// 获取预警设备列表
|
||
List<UUID> getAlertEquipmentIds(UUID projectId, AlertLevel level);
|
||
|
||
// 记录故障
|
||
void recordFailure(EquipmentFailureHistory failure);
|
||
}
|
||
```
|
||
|
||
**健康度算法实现:**
|
||
```java
|
||
public EquipmentHealthScore calculateHealthScore(UUID equipmentId) {
|
||
// 基础分 = 100
|
||
BigDecimal baseScore = new BigDecimal("100");
|
||
|
||
// 故障率扣分 = 故障次数 × 5(近30天)
|
||
int failureCount = failureHistoryRepository.countByEquipmentIdAndFailureDateAfter(
|
||
equipmentId, LocalDateTime.now().minusDays(30));
|
||
BigDecimal failureDeduction = new BigDecimal(failureCount * 5);
|
||
|
||
// 维保扣分 = (1 - 维保完成率) × 20
|
||
BigDecimal maintenanceRate = maintenanceTaskService.getCompletionRate(equipmentId);
|
||
BigDecimal maintenanceDeduction = new BigDecimal("1").subtract(maintenanceRate)
|
||
.multiply(new BigDecimal("20"));
|
||
|
||
// 年龄扣分 = 投入使用年限 × 2(最高扣10分)
|
||
SpaceNode equipment = spaceNodeRepository.findById(equipmentId).orElseThrow();
|
||
int yearsInService = calculateYearsInService(equipment.getCreatedAt());
|
||
BigDecimal ageDeduction = new BigDecimal(Math.min(yearsInService * 2, 10));
|
||
|
||
BigDecimal healthScore = baseScore
|
||
.subtract(failureDeduction)
|
||
.subtract(maintenanceDeduction)
|
||
.subtract(ageDeduction);
|
||
|
||
return healthScore;
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建 Service 接口
|
||
**Step 2:** 实现计算逻辑
|
||
**Step 3:** 添加单元测试
|
||
**Step 4:** Commit: `feat: add equipment health service`
|
||
|
||
---
|
||
|
||
## 阶段六:M02-18 设备点检标准库
|
||
|
||
### Task 6.1: 创建点检模板实体
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/entity/InspectionTemplate.java`
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_inspection_template")
|
||
@Data
|
||
public class InspectionTemplate {
|
||
@Id
|
||
@GeneratedValue(strategy = GenerationType.UUID)
|
||
private UUID id;
|
||
|
||
@Column(name = "project_id", nullable = false)
|
||
private UUID projectId;
|
||
|
||
@Column(name = "template_code", nullable = false, unique = true)
|
||
private String templateCode;
|
||
|
||
@Column(name = "template_name", nullable = false)
|
||
private String templateName;
|
||
|
||
@Column(name = "equipment_type")
|
||
private String equipmentType;
|
||
|
||
@Column(name = "inspection_items", columnDefinition = "TEXT")
|
||
private String inspectionItems;
|
||
|
||
@Column(name = "estimated_duration")
|
||
private Integer estimatedDuration;
|
||
|
||
@Column(nullable = false)
|
||
@Enumerated(EnumType.STRING)
|
||
private Status status = Status.ACTIVE;
|
||
|
||
public enum Status { ACTIVE, INACTIVE }
|
||
|
||
@Column
|
||
private Integer version;
|
||
|
||
@Column(name = "created_by")
|
||
private UUID createdBy;
|
||
|
||
@Column(name = "created_at")
|
||
private LocalDateTime createdAt;
|
||
|
||
@PrePersist
|
||
public void prePersist() {
|
||
createdAt = LocalDateTime.now();
|
||
if (version == null) version = 1;
|
||
}
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建实体
|
||
**Step 2:** 编译验证
|
||
**Step 3:** Commit: `feat: add inspection template entity`
|
||
|
||
---
|
||
|
||
### Task 6.2: 创建点检Service
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/service/InspectionTemplateService.java`
|
||
|
||
```java
|
||
public interface InspectionTemplateService {
|
||
InspectionTemplate create(InspectionTemplate template);
|
||
InspectionTemplate copyTemplate(UUID templateId, String newName);
|
||
List<InspectionTemplate> getTemplatesByType(String equipmentType);
|
||
void updateTemplate(UUID id, InspectionTemplate template);
|
||
}
|
||
```
|
||
|
||
**点检项目JSON结构:**
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"itemCode": "I001",
|
||
"itemName": "电机温度检查",
|
||
"inspectionPoint": "电机外壳",
|
||
"inspectionMethod": "HAND_FEEL",
|
||
"standard": "温度正常,无明显过热",
|
||
"normalValue": "≤60°C",
|
||
"abnormalValue": ">70°C",
|
||
"handlingMethod": "停机检查,联系维修",
|
||
"isRequired": true
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
**Step 1:** 创建 Service
|
||
**Step 2:** 添加 JSON 解析/存储逻辑
|
||
**Step 3:** Commit: `feat: add inspection template service`
|
||
|
||
---
|
||
|
||
### Task 6.3: 创建点检Controller
|
||
|
||
**Files:**
|
||
- Create: `ether-pms/module-mdm/src/main/java/com/ether/pms/mdm/controller/InspectionTemplateController.java`
|
||
|
||
**API 设计:**
|
||
|
||
| 方法 | 路径 | 描述 |
|
||
|------|------|------|
|
||
| GET | /api/v1/ops/inspection-templates | 获取点检模板列表 |
|
||
| POST | /api/v1/ops/inspection-templates | 创建点检模板 |
|
||
| GET | /api/v1/ops/inspection-templates/{id} | 获取模板详情 |
|
||
| PUT | /api/v1/ops/inspection-templates/{id} | 更新模板 |
|
||
| POST | /api/v1/ops/inspection-templates/{id}/copy | 复制模板 |
|
||
| GET | /api/v1/ops/inspection-templates/by-type/{equipmentType} | 按设备类型获取 |
|
||
|
||
**Step 1:** 创建 Controller
|
||
**Step 2:** 测试 API
|
||
**Step 3:** Commit: `feat: add inspection template controller`
|
||
|
||
---
|
||
|
||
## 前端页面开发(统一在最后)
|
||
|
||
### Task F.1: 设备管理页面
|
||
|
||
**Files:**
|
||
- Create: `ether-admin/src/views/equipment/EquipmentList.vue`
|
||
- Create: `ether-admin/src/views/equipment/EquipmentDetail.vue`
|
||
- Create: `ether-admin/src/views/equipment/EquipmentForm.vue`
|
||
- Modify: `ether-admin/src/views/Layout.vue` - 添加设备管理菜单
|
||
|
||
**Step 1:** 创建设备列表页面
|
||
**Step 2:** 创建设备详情页面
|
||
**Step 3:** 添加设备表单组件
|
||
**Step 4:** 更新 Layout 添加菜单
|
||
**Step 5:** 运行 `npm run build` 验证
|
||
**Step 6:** Commit: `feat: add equipment management frontend`
|
||
|
||
---
|
||
|
||
### Task F.2: 维保管理页面
|
||
|
||
**Files:**
|
||
- Create: `ether-admin/src/views/maintenance/PlanList.vue`
|
||
- Create: `ether-admin/src/views/maintenance/TaskList.vue`
|
||
|
||
**Step 1:** 创建维保计划列表
|
||
**Step 2:** 创建维保任务列表
|
||
**Step 3:** 编译验证
|
||
**Step 4:** Commit: `feat: add maintenance management frontend`
|
||
|
||
---
|
||
|
||
### Task F.3: 能耗监控页面
|
||
|
||
**Files:**
|
||
- Create: `ether-admin/src/views/energy/EnergyMeterList.vue`
|
||
- Create: `ether-admin/src/views/energy/EnergyStatistics.vue`
|
||
|
||
**Step 1:** 创建计量点管理页面
|
||
**Step 2:** 创建能耗统计页面
|
||
**Step 3:** 编译验证
|
||
**Step 4:** Commit: `feat: add energy monitoring frontend`
|
||
|
||
---
|
||
|
||
### Task F.4: 备件管理页面
|
||
|
||
**Files:**
|
||
- Create: `ether-admin/src/views/sparepart/SparePartList.vue`
|
||
- Create: `ether-admin/src/views/sparepart/SparePartRecord.vue`
|
||
|
||
**Step 1:** 创建备件列表页面
|
||
**Step 2:** 创建备件记录页面
|
||
**Step 3:** 编译验证
|
||
**Step 4:** Commit: `feat: add spare part management frontend`
|
||
|
||
---
|
||
|
||
## 测试验证
|
||
|
||
### Task T.1: 后端单元测试
|
||
|
||
为每个 Service 创建单元测试:
|
||
- `SpaceNodeServiceTest`
|
||
- `MaintenancePlanServiceTest`
|
||
- `MaintenanceTaskServiceTest`
|
||
- `EnergyConsumptionServiceTest`
|
||
- `SparePartServiceTest`
|
||
- `EquipmentHealthServiceTest`
|
||
|
||
```bash
|
||
cd ether-pms && mvn test -Dtest=*ServiceTest
|
||
```
|
||
|
||
---
|
||
|
||
### Task T.2: 后端集成测试
|
||
|
||
```bash
|
||
# 使用 H2 内存数据库进行集成测试
|
||
cd ether-pms && mvn verify
|
||
```
|
||
|
||
---
|
||
|
||
### Task T.3: 前端构建验证
|
||
|
||
```bash
|
||
cd ether-admin && npm run build
|
||
```
|
||
|
||
---
|
||
|
||
### Task T.4: E2E 测试
|
||
|
||
使用 Playwright 进行 E2E 测试:
|
||
|
||
```bash
|
||
# 设备管理 E2E
|
||
npx playwright test tests/equipment.spec.ts
|
||
|
||
# 维保管理 E2E
|
||
npx playwright test tests/maintenance.spec.ts
|
||
```
|
||
|
||
---
|
||
|
||
## 数据库迁移脚本汇总
|
||
|
||
**文件列表:**
|
||
1. `V10__add_equipment_extension_fields.sql` - 设备扩展字段
|
||
2. `V11__create_maintenance_tables.sql` - 维保计划和任务表
|
||
3. `V12__create_energy_tables.sql` - 能耗表
|
||
4. `V13__create_spare_part_tables.sql` - 备件表
|
||
5. `V14__create_equipment_health_tables.sql` - 设备健康表
|
||
6. `V15__create_inspection_template_table.sql` - 点检模板表
|
||
|
||
---
|
||
|
||
## 部署检查清单
|
||
|
||
- [ ] 数据库迁移脚本执行
|
||
- [ ] 后端编译通过
|
||
- [ ] 后端单元测试通过
|
||
- [ ] 前端编译通过
|
||
- [ ] API 端点验证
|
||
- [ ] E2E 测试通过
|
||
- [ ] 文档更新
|
||
|
||
---
|
||
|
||
## 风险与缓解
|
||
|
||
| 风险 | 影响 | 缓解措施 |
|
||
|------|------|----------|
|
||
| 定时任务性能 | 维保检查任务执行慢 | 使用 @Async 或分布式任务 |
|
||
| 能耗数据量大 | 查询性能问题 | 添加索引,分区表 |
|
||
| IoT 数据接入 | 协议兼容问题 | 预留适配器接口 |
|
||
| 历史数据不足 | 故障预测不准 | 初期使用规则判断 |
|
||
|
||
---
|
||
|
||
*计划版本: v1.0*
|
||
*最后更新: 2026-03-23*
|