786 lines
23 KiB
Markdown
786 lines
23 KiB
Markdown
# 运营调度领域技术方案
|
||
|
||
**领域编号**: 4.2
|
||
**微服务**: ether-ops
|
||
**最后更新**: 2026-02-10
|
||
|
||
---
|
||
|
||
## 一、领域概述
|
||
|
||
### 1.1 领域职责
|
||
|
||
运营调度领域是 Ether 平台的核心业务领域,负责管理:
|
||
- 综合工单管理(创建、分配、处理、关闭)
|
||
- 工单流转记录与状态机
|
||
- 消息通知系统(模板、规则、渠道)
|
||
- 工单统计与分析
|
||
|
||
### 1.2 核心概念
|
||
|
||
| 概念 | 说明 | 对应实体 |
|
||
|------|------|----------|
|
||
| **工单** | 综合业务单据,支持多种类型 | WorkOrder |
|
||
| **工单流转** | 工单状态变更记录 | WorkOrderFlow |
|
||
| **通知渠道** | 消息发送通道 | NotificationChannel |
|
||
| **通知模板** | 消息内容模板 | NotificationTemplate |
|
||
| **通知规则** | 触发条件和发送策略 | NotificationRule |
|
||
| **通知历史** | 已发送消息记录 | NotificationHistory |
|
||
|
||
---
|
||
|
||
## 二、领域模型
|
||
|
||
### 2.1 聚合根设计
|
||
|
||
#### WorkOrder(综合工单)
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_work_order")
|
||
@Data
|
||
public class WorkOrder {
|
||
@Id
|
||
private UUID id;
|
||
private UUID projectId;
|
||
|
||
private String orderNo; // 工单编号: WO2024021000001
|
||
|
||
// 工单类型
|
||
private WorkOrderType orderType; // REPAIR/COMPLAINT/CLEANING/SECURITY/OTHER
|
||
private WorkOrderStatus status; // 状态机
|
||
private WorkOrderPriority priority; // URGENT/HIGH/MEDIUM/LOW
|
||
private WorkOrderSource source; // APP/PHONE/INSPECTION/IOT/SYSTEM
|
||
|
||
// 基本信息
|
||
private String title;
|
||
private String description;
|
||
|
||
// 报修人信息
|
||
private UUID reporterId;
|
||
private String reporterName;
|
||
private String reporterPhone;
|
||
private String reporterAddress;
|
||
|
||
// 关联信息
|
||
private UUID spaceNodeId; // 关联空间
|
||
private UUID equipmentId; // 关联设备
|
||
|
||
// 处理人信息
|
||
private UUID assigneeId;
|
||
private String assigneeName;
|
||
private LocalDateTime assignedAt;
|
||
private LocalDateTime acceptedAt;
|
||
private LocalDateTime startedAt;
|
||
private LocalDateTime completedAt;
|
||
private LocalDateTime closedAt;
|
||
|
||
// 费用
|
||
private BigDecimal actualCost;
|
||
private BigDecimal materialCost;
|
||
private BigDecimal laborCost;
|
||
|
||
// 结果
|
||
private String resultDescription;
|
||
private Integer satisfactionScore;
|
||
private String satisfactionComment;
|
||
|
||
// 附件
|
||
private String images;
|
||
private String attachments;
|
||
|
||
// 扩展属性
|
||
private String attributes;
|
||
|
||
// 审计字段
|
||
private LocalDateTime createdAt;
|
||
private LocalDateTime updatedAt;
|
||
private UUID createdBy;
|
||
}
|
||
```
|
||
|
||
**业务规则**:
|
||
- orderNo 自动生成,格式: WO + yyyyMMdd + 5位序号
|
||
- 状态流转必须通过合法的业务操作
|
||
- 关闭工单时必须填写处理结果
|
||
|
||
#### WorkOrderFlow(工单流转记录)
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_work_order_flow")
|
||
@Data
|
||
public class WorkOrderFlow {
|
||
@Id
|
||
private UUID id;
|
||
private UUID workOrderId;
|
||
|
||
// 流转信息
|
||
private WorkOrderStatus fromStatus;
|
||
private WorkOrderStatus toStatus;
|
||
private String action; // 操作: ASSIGN/ACCEPT/START/COMPLETE/CLOSE
|
||
|
||
// 操作人
|
||
private UUID operatorId;
|
||
private String operatorName;
|
||
private LocalDateTime operateTime;
|
||
|
||
// 备注
|
||
private String remark;
|
||
|
||
// 附件
|
||
private String images;
|
||
}
|
||
```
|
||
|
||
### 2.2 状态机设计
|
||
|
||
```
|
||
┌─────────────┐
|
||
│ CREATED │ ← 创建工单
|
||
│ (已创建) │
|
||
└──────┬──────┘
|
||
│ 分配
|
||
▼
|
||
┌─────────────┐
|
||
│ ASSIGNED │ ← 分配给处理人
|
||
│ (已分配) │
|
||
└──────┬──────┘
|
||
│ 接单
|
||
▼
|
||
┌─────────────┐
|
||
│ ACCEPTED │ ← 处理人接单
|
||
│ (已接单) │
|
||
└──────┬──────┘
|
||
│ 开始处理
|
||
▼
|
||
┌─────────────┐
|
||
│ IN_PROGRESS │ ← 开始处理
|
||
│ (处理中) │
|
||
└──────┬──────┘
|
||
│ 完成
|
||
▼
|
||
┌─────────────┐
|
||
│ COMPLETED │ ← 处理完成
|
||
│ (已完成) │
|
||
└──────┬──────┘
|
||
│ 关闭
|
||
▼
|
||
┌─────────────┐
|
||
│ CLOSED │ ← 工单关闭
|
||
│ (已关闭) │
|
||
└─────────────┘
|
||
|
||
特殊状态:
|
||
- SUSPENDED (已挂起): 任意状态可转入,可恢复
|
||
- RETURNED (已退回): ASSIGNED状态可转入,需重新分配
|
||
```
|
||
|
||
**状态流转规则**:
|
||
|
||
| 当前状态 | 允许操作 | 下一状态 | 权限 |
|
||
|---------|---------|---------|------|
|
||
| CREATED | 分配 | ASSIGNED | 管理员/调度员 |
|
||
| ASSIGNED | 接单 | ACCEPTED | 被指派人 |
|
||
| ASSIGNED | 退回 | RETURNED | 被指派人 |
|
||
| ACCEPTED | 开始 | IN_PROGRESS | 被指派人 |
|
||
| IN_PROGRESS | 完成 | COMPLETED | 被指派人 |
|
||
| COMPLETED | 关闭 | CLOSED | 管理员/创建人 |
|
||
| * | 挂起 | SUSPENDED | 管理员 |
|
||
| SUSPENDED | 恢复 | 原状态 | 管理员 |
|
||
|
||
---
|
||
|
||
## 三、消息通知系统
|
||
|
||
### 3.1 聚合根设计
|
||
|
||
#### NotificationChannel(通知渠道)
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_notification_channel")
|
||
@Data
|
||
public class NotificationChannel {
|
||
@Id
|
||
private UUID id;
|
||
private UUID projectId;
|
||
|
||
private String name;
|
||
private ChannelType type; // SITE_MESSAGE/SMS/EMAIL/PUSH/WECHAT_WORK
|
||
|
||
// 配置(JSONB)
|
||
private String config; // 渠道配置参数
|
||
// SITE_MESSAGE: {}
|
||
// SMS: {provider, apiKey, apiSecret, templateCode}
|
||
// EMAIL: {host, port, username, password}
|
||
// PUSH: {appKey, appSecret}
|
||
// WECHAT_WORK: {corpId, agentId, secret}
|
||
|
||
private Boolean enabled;
|
||
private Integer priority; // 优先级,数字越小优先级越高
|
||
private Integer dailyLimit; // 日发送限制
|
||
private Integer sentToday; // 今日已发送
|
||
|
||
// 审计字段
|
||
private LocalDateTime createdAt;
|
||
private LocalDateTime updatedAt;
|
||
}
|
||
```
|
||
|
||
#### NotificationTemplate(消息模板)
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_notification_template")
|
||
@Data
|
||
public class NotificationTemplate {
|
||
@Id
|
||
private UUID id;
|
||
private UUID projectId;
|
||
|
||
private String name;
|
||
private String code; // 模板编码,唯一
|
||
|
||
// 模板内容
|
||
private String titleTemplate;
|
||
private String contentTemplate;
|
||
|
||
// 变量定义
|
||
private String variables; // ["orderNo", "title", "assigneeName"]
|
||
|
||
// 适用渠道
|
||
private String channels; // ["SITE_MESSAGE", "SMS"]
|
||
|
||
// 示例
|
||
private String example; // 渲染后的示例
|
||
|
||
// 审计字段
|
||
private LocalDateTime createdAt;
|
||
private LocalDateTime updatedAt;
|
||
}
|
||
|
||
// 模板示例:
|
||
// titleTemplate: "新工单通知: {{title}}"
|
||
// contentTemplate: "您有一个新的{{orderType}}工单待处理,工单号: {{orderNo}},请尽快处理。"
|
||
```
|
||
|
||
#### NotificationRule(通知规则)
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_notification_rule")
|
||
@Data
|
||
public class NotificationRule {
|
||
@Id
|
||
private UUID id;
|
||
private UUID projectId;
|
||
|
||
private String name;
|
||
private String eventType; // 事件类型: WORK_ORDER_CREATED/ASSIGNED/COMPLETED
|
||
|
||
// 触发条件(JSONB)
|
||
private String conditions; // {"orderType": "REPAIR", "priority": "HIGH"}
|
||
|
||
// 延迟发送
|
||
private Integer delayMinutes; // 延迟分钟数,0为立即发送
|
||
|
||
// 通知配置
|
||
private String templateCode; // 关联模板
|
||
private String receivers; // 接收人: ["CREATOR", "ASSIGNEE", "MANAGER"]
|
||
private String channels; // 通知渠道优先级: ["SITE_MESSAGE", "SMS"]
|
||
|
||
// 免打扰
|
||
private String quietHours; // 免打扰时段: "22:00-08:00"
|
||
private Boolean enabled;
|
||
|
||
// 审计字段
|
||
private LocalDateTime createdAt;
|
||
private LocalDateTime updatedAt;
|
||
}
|
||
```
|
||
|
||
#### NotificationHistory(通知历史)
|
||
|
||
```java
|
||
@Entity
|
||
@Table(name = "ops_notification_history")
|
||
@Data
|
||
public class NotificationHistory {
|
||
@Id
|
||
private UUID id;
|
||
private UUID projectId;
|
||
|
||
// 通知内容
|
||
private String title;
|
||
private String content;
|
||
private String eventType;
|
||
|
||
// 接收人
|
||
private UUID receiverId;
|
||
private String receiverName;
|
||
private String receiverPhone;
|
||
private String receiverEmail;
|
||
|
||
// 渠道信息
|
||
private ChannelType channel;
|
||
private String channelMsgId; // 渠道消息ID
|
||
|
||
// 状态
|
||
private NotificationStatus status; // PENDING/SENT/FAILED/READ
|
||
private String failReason; // 失败原因
|
||
|
||
private LocalDateTime sendTime;
|
||
private LocalDateTime readTime;
|
||
|
||
// 关联业务
|
||
private String businessType; // WORK_ORDER/INSPECTION/FEE
|
||
private String businessId;
|
||
|
||
// 审计字段
|
||
private LocalDateTime createdAt;
|
||
}
|
||
```
|
||
|
||
### 3.2 通知事件类型
|
||
|
||
| 事件类型 | 触发时机 | 默认接收人 | 默认渠道 |
|
||
|---------|---------|-----------|---------|
|
||
| WORK_ORDER_CREATED | 工单创建 | 创建人 | 站内信 |
|
||
| WORK_ORDER_ASSIGNED | 工单分配 | 处理人 | 站内信+推送 |
|
||
| WORK_ORDER_ACCEPTED | 工单接单 | 创建人 | 站内信 |
|
||
| WORK_ORDER_COMPLETED | 工单完成 | 创建人 | 站内信+推送 |
|
||
| WORK_ORDER_CLOSED | 工单关闭 | - | - |
|
||
| INSPECTION_TODAY | 当天巡检提醒 | 巡检人 | 站内信+推送 |
|
||
| INSPECTION_OVERDUE | 巡检逾期 | 巡检人+管理员 | 站内信+短信 |
|
||
| FEE_UPCOMING_DUE | 费用即将到期 | 业主 | 站内信+推送 |
|
||
| FEE_OVERDUE | 费用逾期 | 业主 | 站内信+短信 |
|
||
|
||
### 3.3 通知流程
|
||
|
||
```
|
||
1. 业务事件触发
|
||
↓
|
||
2. 查询匹配的通知规则
|
||
↓
|
||
3. 渲染消息模板
|
||
↓
|
||
4. 确定接收人列表
|
||
↓
|
||
5. 选择通知渠道
|
||
↓
|
||
6. 检查免打扰设置
|
||
↓
|
||
7. 发送消息
|
||
↓
|
||
8. 记录发送历史
|
||
↓
|
||
9. 更新站内信未读数
|
||
```
|
||
|
||
---
|
||
|
||
## 四、工单统计
|
||
|
||
### 4.1 统计维度
|
||
|
||
```java
|
||
// 工单统计服务
|
||
@Service
|
||
public class WorkOrderStatisticsService {
|
||
|
||
// 概览统计
|
||
public WorkOrderOverviewVO getOverview(UUID projectId, LocalDate startDate, LocalDate endDate) {
|
||
// 工单总数
|
||
// 待处理数
|
||
// 今日新增
|
||
// 今日完成
|
||
// 平均处理时长
|
||
// 满意度评分
|
||
}
|
||
|
||
// 趋势统计
|
||
public List<TrendVO> getTrend(UUID projectId, StatisticsType type, LocalDate startDate, LocalDate endDate) {
|
||
// 按日/周/月统计工单量
|
||
// 创建趋势
|
||
// 完成趋势
|
||
}
|
||
|
||
// 类型分布
|
||
public List<DistributionVO> getTypeDistribution(UUID projectId, LocalDate startDate, LocalDate endDate) {
|
||
// 按工单类型统计
|
||
}
|
||
|
||
// 处理人排行
|
||
public List<RankingVO> getAssigneeRanking(UUID projectId, LocalDate startDate, LocalDate endDate) {
|
||
// 处理人工作量排行
|
||
// 处理人满意度排行
|
||
}
|
||
|
||
// 超时分析
|
||
public List<OvertimeVO> getOvertimeAnalysis(UUID projectId, LocalDate startDate, LocalDate endDate) {
|
||
// 超时工单列表
|
||
// 超时原因分析
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 统计指标
|
||
|
||
| 指标 | 说明 | 计算方式 |
|
||
|------|------|---------|
|
||
| 工单总数 | 指定时间范围内的工单总数 | COUNT(*) |
|
||
| 待处理数 | 状态为CREATED/ASSIGNED/ACCEPTED/IN_PROGRESS的工单数 | COUNT(*) WHERE status IN (...) |
|
||
| 今日新增 | 今日创建的工单数 | COUNT(*) WHERE created_at >= today |
|
||
| 今日完成 | 今日完成的工单数 | COUNT(*) WHERE completed_at >= today |
|
||
| 平均处理时长 | 从创建到完成的平均时间 | AVG(completed_at - created_at) |
|
||
| 按时完成率 | 在SLA时间内完成的工单比例 | COUNT(on_time) / COUNT(completed) |
|
||
| 满意度评分 | 业主评价的平均分 | AVG(satisfaction_score) |
|
||
|
||
---
|
||
|
||
## 五、API 接口
|
||
|
||
### 5.1 WorkOrder API
|
||
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/api/v1/ops/work-orders")
|
||
@Tag(name = "工单管理")
|
||
public class WorkOrderController {
|
||
|
||
@PostMapping
|
||
@Operation(summary = "创建工单")
|
||
public Result<WorkOrderVO> create(@RequestBody @Valid WorkOrderCreateRequest request);
|
||
|
||
@GetMapping("/{id}")
|
||
@Operation(summary = "获取工单详情")
|
||
public Result<WorkOrderVO> getById(@PathVariable UUID id);
|
||
|
||
@GetMapping
|
||
@Operation(summary = "分页查询工单")
|
||
public Result<Page<WorkOrderVO>> page(WorkOrderQueryRequest request);
|
||
|
||
@PutMapping("/{id}")
|
||
@Operation(summary = "更新工单")
|
||
public Result<WorkOrderVO> update(@PathVariable UUID id,
|
||
@RequestBody @Valid WorkOrderUpdateRequest request);
|
||
|
||
@DeleteMapping("/{id}")
|
||
@Operation(summary = "删除工单")
|
||
public Result<Void> delete(@PathVariable UUID id);
|
||
|
||
// 业务操作
|
||
@PostMapping("/{id}/assign")
|
||
@Operation(summary = "分配工单")
|
||
public Result<WorkOrderVO> assign(@PathVariable UUID id,
|
||
@RequestBody @Valid WorkOrderAssignRequest request);
|
||
|
||
@PostMapping("/{id}/accept")
|
||
@Operation(summary = "接单")
|
||
public Result<WorkOrderVO> accept(@PathVariable UUID id);
|
||
|
||
@PostMapping("/{id}/start")
|
||
@Operation(summary = "开始处理")
|
||
public Result<WorkOrderVO> start(@PathVariable UUID id);
|
||
|
||
@PostMapping("/{id}/complete")
|
||
@Operation(summary = "完成工单")
|
||
public Result<WorkOrderVO> complete(@PathVariable UUID id,
|
||
@RequestBody @Valid WorkOrderCompleteRequest request);
|
||
|
||
@PostMapping("/{id}/close")
|
||
@Operation(summary = "关闭工单")
|
||
public Result<WorkOrderVO> close(@PathVariable UUID id,
|
||
@RequestBody @Valid WorkOrderCloseRequest request);
|
||
|
||
@PostMapping("/{id}/suspend")
|
||
@Operation(summary = "挂起工单")
|
||
public Result<WorkOrderVO> suspend(@PathVariable UUID id,
|
||
@RequestBody WorkOrderSuspendRequest request);
|
||
|
||
@PostMapping("/{id}/resume")
|
||
@Operation(summary = "恢复工单")
|
||
public Result<WorkOrderVO> resume(@PathVariable UUID id);
|
||
|
||
// 流转记录
|
||
@GetMapping("/{id}/flows")
|
||
@Operation(summary = "获取流转记录")
|
||
public Result<List<WorkOrderFlowVO>> getFlows(@PathVariable UUID id);
|
||
}
|
||
```
|
||
|
||
### 5.2 Notification API
|
||
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/api/v1/ops/notifications")
|
||
@Tag(name = "消息通知")
|
||
public class NotificationController {
|
||
|
||
// 渠道管理
|
||
@PostMapping("/channels")
|
||
@Operation(summary = "创建通知渠道")
|
||
public Result<NotificationChannelVO> createChannel(@RequestBody @Valid ChannelCreateRequest request);
|
||
|
||
@GetMapping("/channels")
|
||
@Operation(summary = "查询渠道列表")
|
||
public Result<List<NotificationChannelVO>> listChannels();
|
||
|
||
// 模板管理
|
||
@PostMapping("/templates")
|
||
@Operation(summary = "创建消息模板")
|
||
public Result<NotificationTemplateVO> createTemplate(@RequestBody @Valid TemplateCreateRequest request);
|
||
|
||
@GetMapping("/templates")
|
||
@Operation(summary = "查询模板列表")
|
||
public Result<List<NotificationTemplateVO>> listTemplates();
|
||
|
||
// 规则管理
|
||
@PostMapping("/rules")
|
||
@Operation(summary = "创建通知规则")
|
||
public Result<NotificationRuleVO> createRule(@RequestBody @Valid RuleCreateRequest request);
|
||
|
||
@GetMapping("/rules")
|
||
@Operation(summary = "查询规则列表")
|
||
public Result<List<NotificationRuleVO>> listRules();
|
||
|
||
// 消息历史
|
||
@GetMapping("/history")
|
||
@Operation(summary = "分页查询消息历史")
|
||
public Result<Page<NotificationHistoryVO>> pageHistory(NotificationHistoryQueryRequest request);
|
||
|
||
// 个人消息
|
||
@GetMapping("/my")
|
||
@Operation(summary = "获取我的消息列表")
|
||
public Result<Page<NotificationVO>> getMyNotifications(@RequestParam(required = false) Boolean unread);
|
||
|
||
@GetMapping("/my/unread-count")
|
||
@Operation(summary = "获取未读消息数量")
|
||
public Result<Long> getUnreadCount();
|
||
|
||
@PostMapping("/{id}/read")
|
||
@Operation(summary = "标记已读")
|
||
public Result<Void> markAsRead(@PathVariable UUID id);
|
||
|
||
@PostMapping("/read-all")
|
||
@Operation(summary = "全部已读")
|
||
public Result<Void> markAllAsRead();
|
||
}
|
||
```
|
||
|
||
### 5.3 Statistics API
|
||
|
||
```java
|
||
@RestController
|
||
@RequestMapping("/api/v1/ops/statistics")
|
||
@Tag(name = "工单统计")
|
||
public class WorkOrderStatisticsController {
|
||
|
||
@GetMapping("/overview")
|
||
@Operation(summary = "概览统计")
|
||
public Result<WorkOrderOverviewVO> getOverview(
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate);
|
||
|
||
@GetMapping("/trend")
|
||
@Operation(summary = "趋势统计")
|
||
public Result<List<TrendVO>> getTrend(
|
||
@RequestParam StatisticsType type,
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate);
|
||
|
||
@GetMapping("/type-distribution")
|
||
@Operation(summary = "类型分布")
|
||
public Result<List<DistributionVO>> getTypeDistribution(
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate);
|
||
|
||
@GetMapping("/assignee-ranking")
|
||
@Operation(summary = "处理人排行")
|
||
public Result<List<RankingVO>> getAssigneeRanking(
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
|
||
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 六、实现状态与差异
|
||
|
||
### 6.1 实现状态
|
||
|
||
| 功能模块 | 实现状态 | 备注 |
|
||
|---------|---------|------|
|
||
| WorkOrder | 🟢 已实现 | 完整状态机、CRUD |
|
||
| WorkOrderFlow | 🟢 已实现 | 自动记录流转 |
|
||
| NotificationChannel | 🟢 已实现 | 基础CRUD |
|
||
| NotificationTemplate | 🟢 已实现 | 基础CRUD |
|
||
| NotificationRule | 🟢 已实现 | 基础CRUD |
|
||
| NotificationHistory | 🟢 已实现 | 基础CRUD |
|
||
| 工单与通知集成 | 🟢 已实现 | 事件驱动 |
|
||
| 工单统计 | 🟢 已实现 | 多维度统计 |
|
||
| SLA监控 | 🔴 未实现 | 超时预警 |
|
||
| 智能派单 | 🔴 未实现 | 自动分配 |
|
||
|
||
### 6.2 与设计方案的差异
|
||
|
||
| 设计项 | 设计方案 | 现有实现 | 差异分析 |
|
||
|--------|----------|----------|----------|
|
||
| **工单状态机** | 完整状态流转 | 已实现所有状态 | ✅ 符合设计 |
|
||
| **通知渠道** | 多渠道支持 | 仅站内信实现 | ⚠️ 其他渠道待扩展 |
|
||
| **工单统计** | 多维度分析 | 基本实现 | 🟡 可扩展更多维度 |
|
||
| **巡检归属** | ether-ops | ether-mdm | 🟡 领域边界模糊 |
|
||
|
||
### 6.3 待改进项
|
||
|
||
| 优先级 | 改进项 | 说明 |
|
||
|--------|--------|------|
|
||
| P2 | 实现SLA监控 | 工单超时预警和自动升级 |
|
||
| P2 | 扩展通知渠道 | 短信、邮件、推送渠道 |
|
||
| P3 | 智能派单算法 | 基于负载、技能、位置的自动分配 |
|
||
| P3 | 添加工单满意度 | 业主评价机制 |
|
||
|
||
---
|
||
|
||
## 七、数据库表结构
|
||
|
||
```sql
|
||
-- 工单表
|
||
CREATE TABLE ops_work_order (
|
||
id UUID PRIMARY KEY,
|
||
project_id UUID NOT NULL,
|
||
order_no VARCHAR(32) NOT NULL,
|
||
order_type VARCHAR(20) NOT NULL,
|
||
status VARCHAR(20) NOT NULL DEFAULT 'CREATED',
|
||
priority VARCHAR(20) NOT NULL DEFAULT 'MEDIUM',
|
||
source VARCHAR(20) NOT NULL,
|
||
title VARCHAR(200) NOT NULL,
|
||
description TEXT,
|
||
reporter_id UUID,
|
||
reporter_name VARCHAR(100),
|
||
reporter_phone VARCHAR(20),
|
||
reporter_address VARCHAR(255),
|
||
space_node_id UUID,
|
||
equipment_id UUID,
|
||
assignee_id UUID,
|
||
assignee_name VARCHAR(100),
|
||
assigned_at TIMESTAMP,
|
||
accepted_at TIMESTAMP,
|
||
started_at TIMESTAMP,
|
||
completed_at TIMESTAMP,
|
||
closed_at TIMESTAMP,
|
||
actual_cost NUMERIC(12,2),
|
||
material_cost NUMERIC(12,2),
|
||
labor_cost NUMERIC(12,2),
|
||
result_description TEXT,
|
||
satisfaction_score INTEGER,
|
||
satisfaction_comment VARCHAR(500),
|
||
images TEXT,
|
||
attachments TEXT,
|
||
attributes JSONB,
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
created_by UUID,
|
||
updated_by UUID,
|
||
UNIQUE(project_id, order_no)
|
||
);
|
||
|
||
-- 工单流转表
|
||
CREATE TABLE ops_work_order_flow (
|
||
id UUID PRIMARY KEY,
|
||
work_order_id UUID NOT NULL,
|
||
from_status VARCHAR(20),
|
||
to_status VARCHAR(20) NOT NULL,
|
||
action VARCHAR(50) NOT NULL,
|
||
operator_id UUID,
|
||
operator_name VARCHAR(100),
|
||
operate_time TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
remark VARCHAR(500),
|
||
images TEXT
|
||
);
|
||
|
||
-- 通知渠道表
|
||
CREATE TABLE ops_notification_channel (
|
||
id UUID PRIMARY KEY,
|
||
project_id UUID NOT NULL,
|
||
name VARCHAR(100) NOT NULL,
|
||
type VARCHAR(20) NOT NULL,
|
||
config JSONB,
|
||
enabled BOOLEAN DEFAULT TRUE,
|
||
priority INTEGER DEFAULT 0,
|
||
daily_limit INTEGER,
|
||
sent_today INTEGER DEFAULT 0,
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
-- 消息模板表
|
||
CREATE TABLE ops_notification_template (
|
||
id UUID PRIMARY KEY,
|
||
project_id UUID NOT NULL,
|
||
name VARCHAR(100) NOT NULL,
|
||
code VARCHAR(50) NOT NULL,
|
||
title_template VARCHAR(200),
|
||
content_template TEXT NOT NULL,
|
||
variables JSONB,
|
||
channels JSONB,
|
||
example TEXT,
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
UNIQUE(project_id, code)
|
||
);
|
||
|
||
-- 通知规则表
|
||
CREATE TABLE ops_notification_rule (
|
||
id UUID PRIMARY KEY,
|
||
project_id UUID NOT NULL,
|
||
name VARCHAR(100) NOT NULL,
|
||
event_type VARCHAR(50) NOT NULL,
|
||
conditions JSONB,
|
||
delay_minutes INTEGER DEFAULT 0,
|
||
template_code VARCHAR(50) NOT NULL,
|
||
receivers JSONB,
|
||
channels JSONB,
|
||
quiet_hours VARCHAR(20),
|
||
enabled BOOLEAN DEFAULT TRUE,
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
-- 通知历史表
|
||
CREATE TABLE ops_notification_history (
|
||
id UUID PRIMARY KEY,
|
||
project_id UUID NOT NULL,
|
||
title VARCHAR(200),
|
||
content TEXT,
|
||
event_type VARCHAR(50),
|
||
receiver_id UUID,
|
||
receiver_name VARCHAR(100),
|
||
receiver_phone VARCHAR(20),
|
||
receiver_email VARCHAR(100),
|
||
channel VARCHAR(20) NOT NULL,
|
||
channel_msg_id VARCHAR(100),
|
||
status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
|
||
fail_reason VARCHAR(500),
|
||
send_time TIMESTAMP,
|
||
read_time TIMESTAMP,
|
||
business_type VARCHAR(50),
|
||
business_id VARCHAR(50),
|
||
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
-- 创建索引
|
||
CREATE INDEX idx_work_order_project ON ops_work_order(project_id);
|
||
CREATE INDEX idx_work_order_status ON ops_work_order(status);
|
||
CREATE INDEX idx_work_order_assignee ON ops_work_order(assignee_id);
|
||
CREATE INDEX idx_work_order_created ON ops_work_order(created_at);
|
||
CREATE INDEX idx_work_order_flow_order ON ops_work_order_flow(work_order_id);
|
||
CREATE INDEX idx_notification_history_receiver ON ops_notification_history(receiver_id);
|
||
CREATE INDEX idx_notification_history_status ON ops_notification_history(status);
|
||
```
|
||
|
||
---
|
||
|
||
**文档维护**: 本领域技术方案由 ether-ops 服务负责人维护
|