17 KiB
Part 2: 架构演进史
本文档记录 Ops 业务运营模块从零开始到当前的完整演进历程,包括每个阶段的目标、成果、经验教训和技术债务。
2.1 阶段1:基础数据层(2025.12)
2.1.1 实施时间
2025年12月 - 2026年1月初
2.1.2 阶段目标
搭建工单管理系统的数据基础,创建所有必要的数据模型。
2.1.3 核心成果
枚举类(10个):
| 枚举类 | 说明 |
|---|---|
WorkOrderTypeEnum |
工单类型(CLEAN、REPAIR、SECURITY、SERVICE) |
WorkOrderStatusEnum |
工单状态(PENDING、ASSIGNED、ARRIVED、PAUSED、COMPLETED、CANCELLED) |
PriorityEnum |
优先级(P0、P1、P2) |
CleanerStatusEnum |
保洁员状态(IDLE、BUSY、PAUSED、OFFLINE) |
DispatchModeEnum |
派单模式(AUTO、MANUAL) |
OperatorTypeEnum |
操作人类型(SYSTEM、ADMIN、CLEANER、INSPECTOR) |
BadgeDeviceTypeEnum |
设备类型(BADGE、BEACON) |
AreaTypeEnum |
区域类型(PARK、BUILDING、FLOOR、FUNCTION) |
FunctionTypeEnum |
功能类型(LOBBY、ELEVATOR、CORRIDOR、RESTROOM) |
EventDomainEnum |
事件领域(DISPATCH、QUALITY、SYSTEM) |
DO 实体类(10个):
| 实体类 | 说明 |
|---|---|
OpsOrderDO |
工单主表 |
OpsOrderCleanExtDO |
保洁工单扩展表 |
OpsOrderEventDO |
工单事件记录表 |
OpsOrderDispatchDO |
派单决策记录表 |
OpsOrderQueueDO |
工单队列表 |
CleanerStatusDO |
保洁员状态表 |
CleanerPerformanceMonthlyDO |
月度绩效汇总表 |
BadgeDeviceDO |
工牌设备表 |
CleanEventLogDO |
保洁事件日志表 |
BusAreaDO |
业务区域表 |
Mapper 接口(10个):
OpsOrderMapperOpsOrderEventMapperCleanerStatusMapperBadgeDeviceMapperOpsOrderCleanExtMapperOpsOrderDispatchMapperOpsOrderQueueMapperCleanerPerformanceMonthlyMapperCleanEventLogMapperBusAreaMapper
SQL 表结构:
- 文件:
sql/mysql/aiot_ops_work_order.sql - 创建了所有工单相关的数据库表
2.1.4 遗留问题
- 无业务逻辑实现
- 无服务层和 Controller
- 无单元测试
2.2 阶段2:工单引擎(2026.01)
2.2.1 实施时间
2026年1月 - 2026年1月中旬
2.2.2 阶段目标
实现工单管理系统的核心业务逻辑,包括状态机、事件溯源、REST API。
2.2.3 核心成果
DTO 数据传输对象(11个)
工单基础 DTO(ops-biz 模块):
OpsOrderCreateReqDTO- 创建工单请求OpsOrderUpdateReqDTO- 更新工单请求OpsOrderPageReqDTO- 分页查询请求OpsOrderAssignReqDTO- 分配工单请求OpsOrderCompleteReqDTO- 完成工单请求OpsOrderRespDTO- 工单基本信息响应OpsOrderDetailRespDTO- 工单详细信息响应OpsOrderEventRespDTO- 工单事件记录响应
保洁业务 DTO(environment-biz 模块):
CleanOrderAutoCreateReqDTO- 保洁工单自动创建请求CleanOrderPauseReqDTO- 保洁工单暂停请求CleanOrderResumeReqDTO- 保洁工单恢复请求
状态机核心实现
OrderStateMachine - 状态机引擎
@Service
public class OrderStateMachine {
// 状态转换规则
private static final Map<WorkOrderStatusEnum, Set<WorkOrderStatusEnum>> TRANSITIONS = Map.of(
PENDING, Set.of(ASSIGNED, CANCELLED),
ASSIGNED, Set.of(ARRIVED, CANCELLED),
ARRIVED, Set.of(PAUSED, COMPLETED),
PAUSED, Set.of(ARRIVED, CANCELLED),
COMPLETED, Collections.emptySet(),
CANCELLED, Collections.emptySet()
);
@Transactional
public void transition(OpsOrderDO order, WorkOrderStatusEnum newStatus,
OperatorTypeEnum operatorType, Long operatorId, String remark);
}
核心功能:
- ✅ 状态转换规则验证
- ✅ 自动记录事件到
ops_order_event表 - ✅ 通知所有注册的监听器
- ✅ 支持业务扩展(通过监听器模式)
状态流转图:
PENDING (待接单)
↓
ASSIGNED (已分配)
↓
ARRIVED (已到岗)
↓ ↘
PAUSED (已暂停) COMPLETED (已完成) [终态]
↓
ARRIVED (已恢复)
任何状态 → CANCELLED (已取消) [终态]
事件与监听器
OrderStateChangedEvent - 状态变更事件
@Data
@AllArgsConstructor
public class OrderStateChangedEvent {
private OpsOrderDO order;
private WorkOrderStatusEnum fromStatus;
private WorkOrderStatusEnum toStatus;
private OperatorTypeEnum operatorType;
private Long operatorId;
private String remark;
}
OrderStateChangeListener - 监听器接口
@FunctionalInterface
public interface OrderStateChangeListener {
void onStateChanged(OrderStateChangedEvent event);
}
工单服务层
OpsOrderService 接口 - 10个核心方法
| 方法 | 说明 |
|---|---|
createOrder() |
创建工单 |
updateOrder() |
更新工单 |
deleteOrder() |
删除工单 |
getOrder() |
获取工单详情 |
getOrderPage() |
分页查询工单 |
assignOrder() |
分配工单给执行人 |
acceptOrder() |
执行人接单 |
completeOrder() |
完成工单 |
pauseOrder() |
暂停工单 |
resumeOrder() |
恢复工单 |
cancelOrder() |
取消工单 |
REST API(11个)
| HTTP方法 | 路径 | 功能 | 权限 |
|---|---|---|---|
| POST | /ops/order/create |
创建工单 | ops:order:create |
| PUT | /ops/order/update |
更新工单 | ops:order:update |
| DELETE | /ops/order/delete |
删除工单 | ops:order:delete |
| GET | /ops/order/get |
获取工单详情 | ops:order:query |
| GET | /ops/order/page |
分页查询工单 | ops:order:query |
| POST | /ops/order/assign |
分配工单 | ops:order:assign |
| POST | /ops/order/accept |
接单 | ops:order:accept |
| POST | /ops/order/complete |
完成工单 | ops:order:complete |
| POST | /ops/order/pause |
暂停工单 | ops:order:pause |
| POST | /ops/order/resume |
恢复工单 | ops:order:resume |
| POST | /ops/order/cancel |
取消工单 | ops:order:cancel |
单元测试(26个)
OrderStateMachineTest - 10个测试用例
- 状态转换测试
- 非法转换测试
- 终态测试
OpsOrderServiceTest - 16个测试用例
- CRUD 操作测试
- 业务规则测试
- 异常场景测试
测试结果:
Tests run: 26, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
测试覆盖率:
- 状态机核心逻辑:100%
- 工单服务业务规则:95%+
- 异常场景覆盖:完整
- 边界条件测试:完整
2.2.4 架构设计亮点
1. 模块化分层设计
viewsh-module-ops/
├── viewsh-module-ops-api/ # 契约层
├── viewsh-module-ops-biz/ # 核心业务层
│ ├── dal/ # 数据访问层
│ ├── service/ # 服务层
│ │ ├── order/ # 工单服务
│ │ ├── fsm/ # 状态机
│ │ └── event/ # 事件服务
├── viewsh-module-environment-biz/ # 保洁业务线
│ ├── service/
│ │ ├── cleanorder/ # 保洁工单服务
│ │ └── listener/ # 保洁状态监听器
└── viewsh-module-ops-server/ # 宿主层
└── controller/ # REST API
2. 状态机模式
- 集中管理状态转换规则
- 避免状态散落在各个业务方法
- 易于维护和扩展新状态
- 自动记录状态变更历史
3. 监听器模式
- 解耦核心引擎与业务逻辑
- 业务线可独立扩展
- 支持多监听器协同工作
- 符合开闭原则
4. 事件溯源
- 所有状态转换记录到
ops_order_event表 - 支持完整的审计追溯
- 可用于状态重建和数据分析
2.2.5 技术债务
| 优先级 | 问题 | 改进方案 | 预估工作量 |
|---|---|---|---|
| P0 | 分页查询未实现 | 实现 selectPage | 2小时 |
| P1 | 异常处理过于简单 | 定义业务异常类体系 | 4小时 |
| P1 | 缺少参数校验单元测试 | 增加参数校验测试用例 | 3小时 |
| P2 | 日志打印不够详细 | 增加关键操作日志 | 2小时 |
| P2 | 缺少性能监控 | 集成 Micrometer 统计 | 4小时 |
2.3 阶段3:智能调度系统(2026.01 - 规划中)
2.3.1 实施计划
2026年1月 - 2026年2月
2.3.2 阶段目标
实现自动派单、优先级队列、紧急插队功能。
2.3.3 核心功能
1. 保洁员状态管理
状态定义:
IDLE- 空闲(可接新单)BUSY- 忙碌(正在执行工单)PAUSED- 暂停(临时离开)OFFLINE- 离线(工牌离线)
核心方法:
updateStatus()- 更新状态handleHeartbeat()- 处理工牌心跳listAvailableCleaners()- 查询可接单的保洁员findNearbyCleaners()- 查询附近的保洁员
2. 优先级队列管理
Redis + MySQL 混合队列:
- Redis Sorted Set:实时队列(高性能)
- MySQL:持久化存储(数据不丢失)
队列状态:
WAITING- 等待中PROCESSING- 处理中PAUSED- 暂停中REMOVED- 已移除
核心方法:
enqueue()- 入队startExecution()- 开始执行(WAITING → PROCESSING)pauseTask()- 暂停任务(PROCESSING → PAUSED)resumeTask()- 恢复任务(PAUSED → PROCESSING)
3. 自动派单引擎
派单策略:
- 区域优先策略(就近分配)
- 负载均衡策略(考虑当前任务数)
- 技能匹配策略(维修工单需要相应技能)
核心方法:
recommendAssignee()- 推荐执行人员autoDispatch()- 自动派单urgentDispatch()- 紧急派单(可能打断)
4. P0 紧急任务打断
打断条件:
- 目标保洁员状态为 BUSY
- 新工单优先级为 P0
打断流程:
- 查找附近的保洁员
- 如果保洁员正在执行任务(BUSY)
- 暂停当前任务(工单状态 + 队列状态同步变更)
- 派发 P0 工单
- P0 完成后,自动恢复被中断的任务
5. IoT 设备集成
工牌设备集成:
- 订阅设备状态变更事件
- 接收设备心跳消息
- 发送语音播报指令
语音播报优化:
- 自动去重(同一工单不重复播报)
- P0 紧急任务:高分贝警报 + 震动
- 普通/P1 任务:普通语音 + 震动
2.3.4 实施进度
已完成 ✅:
- 队列状态管理(WAITING、PROCESSING、PAUSED、REMOVED)
- 派单引擎实现(DispatchEngine)
- 保洁员状态管理
- P0 紧急任务打断机制
- 语音播报去重服务
进行中 ⏳:
- 工牌通知服务集成
- 消息队列集成(MQ)
- 定时任务(自动生成工单、绩效计算)
待实施 📋:
- 绩效评价系统
- 单元测试(派单逻辑、队列管理、紧急插队)
2.4 架构重构历程(2026.01.06)
2.4.1 背景
在阶段2和阶段3的实施过程中,发现了一些架构问题,需要进行重构。
2.4.2 问题识别
问题1:DispatchEngine 职责不清晰
- 接口定义了 13 个方法,但很多返回 null
- 派单引擎与队列服务的职责边界模糊
autoDispatch()实际只是调用orderQueueService.startExecution()
问题2:通用方法抽离不彻底
OpsOrderService只有基础的 CRUD- 暂停/恢复逻辑直接调用状态机,没有与队列联动
- 打断逻辑只在保洁业务层实现,其他业务线无法复用
问题3:Listener 设计不明确
- 监听器注册是全局的,无法区分业务类型
- 监听器之间没有优先级定义
CleanOrderStateChangeListener直接依赖注入CleanOrderService,产生循环依赖风险
问题4:状态与队列状态同步问题
- 工单状态 (
WorkOrderStatusEnum) 和队列状态 (OrderQueueStatusEnum) 是两个独立的状态机 - 两者之间的同步需要业务层手动保证
2.4.3 重构方案设计
核心原则:
- 单一职责:每个组件只负责一个明确的职责
- 开闭原则:通过接口和策略模式支持扩展
- 依赖倒置:业务层依赖通用层的抽象接口
- 清晰分层:通用能力下沉,业务能力上浮
重新定义组件职责:
DispatchEngine(派单引擎)- 重新定位:
- 职责:只负责"决策",推荐最合适的执行人员
- 不负责:状态管理、设备通知、业务逻辑
OrderLifecycleManager(工单生命周期管理)- 新增:
- 职责:统一管理工单状态和队列状态的同步变更
- 核心方法:
pauseOrder(),resumeOrder(),interruptOrder(),completeOrder()
OrderStateMachine(状态机)- 优化:
- 职责:验证状态转换规则、记录事件
- 不触发:任何业务逻辑(移除监听器机制)
OrderEventPublisher(事件发布器)- 新增:
- 职责:发布工单状态变更事件
- 实现业务解耦
2.4.4 重构实施
Phase 1: 基础重构
| 任务 | 说明 | 状态 |
|---|---|---|
| 重构 DispatchEngine 接口和实现 | 纯决策层 | ✅ 完成 |
| 创建 OrderLifecycleManager | 生命周期管理 | ✅ 完成 |
| 重构 OrderStateMachine(移除监听器) | 纯状态管理 | ✅ 完成 |
| 创建 OrderEventPublisher | 事件发布器 | ✅ 完成 |
| 迁移暂停/恢复逻辑到 OrderLifecycleManager | 统一状态同步 | ✅ 完成 |
Phase 2: 业务层改造
| 任务 | 说明 | 状态 |
|---|---|---|
| 创建事件处理器替代监听器 | CleanOrderEventHandler | ✅ 完成 |
| 重构 CleanOrderService | 使用 OrderLifecycleManager | ✅ 完成 |
| 更新派单策略实现 | CleanerAreaPriorityStrategy | ✅ 完成 |
| 单元测试编写 | 测试用例 | 📋 待进行 |
Phase 3: 优化与验证
| 任务 | 说明 | 状态 |
|---|---|---|
| 性能优化 | - | ⏳ 待进行 |
| 集成测试 | - | ⏳ 待进行 |
| 文档更新 | - | ⏳ 待进行 |
2.4.5 收获与反思
成功经验:
-
职责分离带来清晰度
- DispatchEngine 专注于决策
- OrderLifecycleManager 统一管理状态同步
- 各组件职责清晰,易于理解和维护
-
事件驱动架构提升扩展性
- 业务方通过订阅事件处理自己的逻辑
- 新增业务类型只需实现事件处理器
- 核心引擎不需要修改
-
兼容性保证平滑迁移
- 保留旧实现作为兼容层
- 业务流程不中断
- 逐步迁移到新架构
踩坑记录:
-
循环依赖问题
- 问题:DispatchEngine 依赖 CleanOrderService,CleanOrderService 依赖 DispatchEngine
- 解决:使用
@Lazy延迟注入
-
状态同步复杂性
- 问题:工单状态和队列状态需要保持一致
- 解决:引入 OrderLifecycleManager 统一管理
-
监听器优先级
- 问题:监听器之间没有优先级定义
- 解决:改为事件驱动,由业务方决定处理顺序
改进建议:
-
从设计阶段就明确职责
- 在编码前充分讨论组件职责
- 使用 UML 图展示组件关系
- 定期 Review 架构设计
-
持续重构
- 不要等技术债务积累太多
- 定期(每季度)进行架构 Review
- 及时重构不合理的设计
-
完善测试
- 单元测试覆盖核心逻辑
- 集成测试覆盖端到端流程
- 性能测试验证优化效果
2.5 版本对比
2.5.1 v1.0(阶段2完成)
特点:
- 状态机 + 监听器模式
- 基础工单 CRUD
- REST API
- 单元测试
优点:
- 功能完整
- 测试覆盖率高
- 监听器模式支持扩展
缺点:
- DispatchEngine 职责不清晰
- 通用方法抽离不彻底
- 状态同步需要手动保证
2.5.2 v2.0(架构重构)
特点:
- 纯决策层的派单引擎
- 统一的声明周期管理
- 事件驱动架构
- 兼容层保证平滑迁移
优点:
- 职责清晰
- 易于扩展
- 易于测试
- 向后兼容
缺点:
- 组件数量增加
- 学习曲线稍陡
2.6 关键里程碑
| 日期 | 里程碑 | 说明 |
|---|---|---|
| 2025-12 | 阶段1完成 | 基础数据层 |
| 2026-01 | 阶段2完成 | 工单引擎、状态机、REST API |
| 2026-01-06 | 架构重构方案 | 重新定义组件职责 |
| 2026-01 | 阶段3规划 | 智能调度系统(部分完成) |
| 2026 Q2 | 安保条线 | 计划实施 |
| 2026 Q3 | 工程条线 | 计划实施 |
| 2026 Q4 | 客服条线 | 计划实施 |
下一章:Part 3: 核心架构设计