# 转运任务状态变更记录同步到旧系统功能说明 ## 一、功能概述 本功能实现了在转运任务状态发生变更时,自动将状态变更记录同步到SQL Server旧系统的 `DispatchOrd_Running` 表中。该功能通过Spring事件监听机制实现,确保状态变更的完整记录和追踪。 ## 二、核心组件 ### 1. 数据库表结构 **旧系统表:DispatchOrd_Running**(SQL Server) ```sql create table DispatchOrd_Running( id int comment "自增主键", DispatchOrdIDDt bigint comment '调度单ID', DispatchOrdState int comment '状态', DispatchOrdStartDate datetime comment '状态时间', DispatchOrdStartOA int comment '操作状态的OA用户ID', OA_latitude float comment '更新状态时的纬度', OA_longitude float comment '更新状态时的经度', OA_address nvarchar(400) comment '更新状态时的地址' ) ``` ### 2. Mapper接口 **LegacyTransferSyncMapper.java** 新增方法: ```java /** * 插入调度单状态变更记录到 DispatchOrd_Running 表 * * @param dispatchOrdID 调度单ID * @param dispatchOrdState 状态码 * @param dispatchOrdStartDate 状态时间 * @param dispatchOrdStartOA 操作状态的OA用户ID * @param oaLatitude 更新状态时的纬度 * @param oaLongitude 更新状态时的经度 * @param oaAddress 更新状态时的地址 * @return 影响行数 */ int insertDispatchOrdRunning( @Param("dispatchOrdID") Long dispatchOrdID, @Param("dispatchOrdState") Integer dispatchOrdState, @Param("dispatchOrdStartDate") java.util.Date dispatchOrdStartDate, @Param("dispatchOrdStartOA") Long dispatchOrdStartOA, @Param("oaLatitude") Double oaLatitude, @Param("oaLongitude") Double oaLongitude, @Param("oaAddress") String oaAddress ); ``` ### 3. Mapper XML配置 **LegacyTransferSyncMapper.xml** ```xml INSERT INTO DispatchOrd_Running ( DispatchOrdIDDt, DispatchOrdState, DispatchOrdStartDate, DispatchOrdStartOA, OA_latitude, OA_longitude, OA_address ) VALUES ( #{dispatchOrdID}, #{dispatchOrdState}, #{dispatchOrdStartDate}, #{dispatchOrdStartOA}, #{oaLatitude}, #{oaLongitude}, #{oaAddress} ) ``` ### 4. 事件监听器 **DispatchOrdRunningListener.java** - **位置**: `ruoyi-system/src/main/java/com/ruoyi/system/listener/` - **功能**: 监听任务状态变更事件(TaskStatusChangedEvent),自动同步状态变更记录到旧系统 - **特性**: - ✅ **异步处理**: 使用 `@Async` 注解,不阻塞主业务流程 - ✅ **事件监听**: 使用 `@EventListener` 注解监听状态变更事件 - ✅ **智能过滤**: 只处理急救转运任务且已同步到旧系统的任务 - ✅ **状态转换**: 自动将新系统状态转换为旧系统状态码 - ✅ **GPS记录**: 记录状态变更时的GPS位置和地址信息 - ✅ **容错处理**: 异常不影响主业务流程 ## 三、工作流程 ```mermaid graph TB A[转运任务状态变更] --> B[SysTaskServiceImpl.changeTaskStatus] B --> C[发布TaskStatusChangedEvent事件] C --> D[DispatchOrdRunningListener监听] D --> E{是否启用旧系统同步?} E -->|否| F[跳过同步] E -->|是| G{是否急救转运任务?} G -->|否| F G -->|是| H{调度单是否已同步?} H -->|否| F H -->|是| I[转换状态码] I --> J{状态需要同步?} J -->|否| F J -->|是| K[插入DispatchOrd_Running表] K --> L[记录日志] ``` ## 四、状态映射关系 新系统状态 → 旧系统状态码映射: | 新系统状态 | TaskStatus枚举 | 旧系统状态码 | 旧系统状态描述 | |-----------|---------------|-------------|---------------| | 出发中 | DEPARTING | 4 | 已出车(去接患者途中) | | 任务中 | IN_PROGRESS | 6 | 已出车(服务中) | | 返程中 | RETURNING | 7 | 已送达(回程中) | | 已完成 | COMPLETED | 8 | 已返回 | | 已取消 | CANCELLED | 10 | 取消 | | 待处理 | PENDING | - | 不同步 | | 已到达 | ARRIVED | - | 不同步 | ## 五、同步条件 满足以下**所有条件**时才会同步状态变更记录: 1. ✅ 旧系统同步功能已启用(`legacy.system.enabled=true`) 2. ✅ 任务类型为急救转运(`EMERGENCY_TRANSFER`) 3. ✅ 任务已同步到旧系统(`legacy_dispatch_ord_id` 不为空) 4. ✅ 新状态需要同步到旧系统(参见状态映射表) ## 六、使用示例 ### 1. 自动触发(推荐) 当转运任务状态发生变更时,系统会自动触发同步: ```java // 在SysTaskServiceImpl中变更状态 sysTaskService.changeTaskStatus(taskId, TaskStatus.DEPARTING, "司机已出发"); // 系统自动: // 1. 发布TaskStatusChangedEvent事件 // 2. DispatchOrdRunningListener监听并处理 // 3. 插入记录到DispatchOrd_Running表 ``` ### 2. 日志示例 **成功同步的日志**: ``` 2025-12-05 14:30:15 INFO DispatchOrdRunningListener - 收到任务状态变更事件,准备同步到DispatchOrd_Running,任务ID:1001,旧状态:PENDING,新状态:DEPARTING 2025-12-05 14:30:15 INFO DispatchOrdRunningListener - 开始同步状态变更记录到DispatchOrd_Running,DispatchOrdID: 12345, 状态码: 4, 状态描述: 已出车(去接患者途中) 2025-12-05 14:30:15 INFO DispatchOrdRunningListener - 状态变更记录已同步到DispatchOrd_Running,DispatchOrdID: 12345, 状态码: 4 (已出车(去接患者途中)), GPS: [113.264385, 23.12911], 地址: 广州市越秀区XX路XX号 ``` **跳过同步的日志**: ``` 2025-12-05 14:30:15 DEBUG DispatchOrdRunningListener - 调度单未同步到旧系统,跳过DispatchOrd_Running同步,任务ID: 1001 ``` ## 七、数据记录内容 每次状态变更会记录以下信息: | 字段 | 说明 | 数据来源 | |-----|------|---------| | DispatchOrdIDDt | 调度单ID | sys_task_emergency.legacy_dispatch_ord_id | | DispatchOrdState | 状态码 | 从新系统TaskStatus转换而来 | | DispatchOrdStartDate | 状态时间 | 当前时间 | | DispatchOrdStartOA | 操作人ID | TaskStatusChangedEvent.creatorId | | OA_latitude | 纬度 | TaskStatusChangedEvent.latitude | | OA_longitude | 经度 | TaskStatusChangedEvent.longitude | | OA_address | 地址 | TaskStatusChangedEvent.address | ## 八、监控和调试 ### 1. 查看状态变更记录 ```sql -- SQL Server中查询最近的状态变更记录 SELECT TOP 20 DispatchOrdIDDt, DispatchOrdState, DispatchOrdStartDate, DispatchOrdStartOA, OA_latitude, OA_longitude, OA_address FROM DispatchOrd_Running ORDER BY DispatchOrdStartDate DESC ``` ### 2. 查询特定调度单的状态变更历史 ```sql -- 查询某个调度单的所有状态变更记录 SELECT DispatchOrdState, DispatchOrdStartDate, OA_latitude, OA_longitude, OA_address FROM DispatchOrd_Running WHERE DispatchOrdIDDt = 12345 ORDER BY DispatchOrdStartDate DESC ``` ### 3. 统计今日状态变更次数 ```sql -- 统计今日各状态的变更次数 SELECT DispatchOrdState, CASE DispatchOrdState WHEN 4 THEN '已出车(去接患者途中)' WHEN 6 THEN '已出车(服务中)' WHEN 7 THEN '已送达(回程中)' WHEN 8 THEN '已返回' WHEN 10 THEN '取消' ELSE '其他' END AS StateName, COUNT(*) AS ChangeCount FROM DispatchOrd_Running WHERE CONVERT(DATE, DispatchOrdStartDate) = CONVERT(DATE, GETDATE()) GROUP BY DispatchOrdState ORDER BY DispatchOrdState ``` ## 九、架构优势 ### 1. 完全解耦 - 业务逻辑与同步逻辑分离 - 状态变更不依赖旧系统同步结果 - 可独立测试和维护 ### 2. 异步处理 - 不阻塞主业务流程 - 提高系统响应速度 - 容错能力强 ### 3. 自动化 - 无需手动触发 - 实时同步状态变更 - 减少人工操作 ### 4. 可追溯性 - 完整记录每次状态变更 - 包含GPS位置信息 - 便于问题排查和审计 ## 十、注意事项 ### 1. 数据源配置 确保 `LegacyTransferSyncMapper` 使用SQL Server数据源: ```java @DataSource(DataSourceType.SQLSERVER) public interface LegacyTransferSyncMapper { // ... } ``` ### 2. 异步线程池 异步处理依赖线程池配置(AsyncConfig.java): ```java @Configuration @EnableAsync public class AsyncConfig { @Bean(name = "taskExecutor") public Executor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); // ... } } ``` ### 3. 异常处理 监听器中的异常不会影响主业务: - 记录详细日志 - 不抛出异常 - 不影响状态变更操作 ### 4. 性能优化 - 使用 `@Async` 异步处理 - 只同步必要的状态变更 - 智能过滤不需要同步的任务 ## 十一、测试验证 ### 1. 测试步骤 **步骤1:创建并同步转运任务** ```java // 创建急救转运任务 Long taskId = sysTaskService.insertSysTask(createVO); // 确保任务已同步到旧系统 legacySystemSyncService.syncDispatchOrderToLegacy(taskId); ``` **步骤2:变更任务状态** ```java // 变更状态为"出发中" sysTaskService.changeTaskStatus(taskId, TaskStatus.DEPARTING, "司机已出发"); ``` **步骤3:验证SQL Server记录** ```sql -- 查询DispatchOrd_Running表 SELECT * FROM DispatchOrd_Running WHERE DispatchOrdIDDt = ( SELECT legacy_dispatch_ord_id FROM sys_task_emergency WHERE task_id = ? ) ORDER BY DispatchOrdStartDate DESC ``` ### 2. 预期结果 | 测试场景 | 预期结果 | |---------|---------| | 急救转运任务状态变更 | 插入记录到DispatchOrd_Running | | 非急救转运任务状态变更 | 不插入记录 | | 未同步的任务状态变更 | 不插入记录 | | 不需要同步的状态(PENDING) | 不插入记录 | | 旧系统同步已禁用 | 不插入记录 | ## 十二、相关文件清单 ### 新增文件 - `DispatchOrdRunningListener.java` - 状态变更监听器 ### 修改文件 - `LegacyTransferSyncMapper.java` - 添加insertDispatchOrdRunning方法 - `LegacyTransferSyncMapper.xml` - 添加插入SQL ### 依赖文件(无需修改) - `SysTaskServiceImpl.java` - 发布状态变更事件 - `TaskStatusChangedEvent.java` - 状态变更事件 - `TaskStatusPushConverter.java` - 状态转换工具 - `DispatchRunning.sql` - 数据库表结构定义 ## 十三、故障排查 ### 问题1:状态变更没有同步到旧系统 **排查步骤**: 1. 检查旧系统同步是否启用:`legacy.system.enabled=true` 2. 检查任务是否为急救转运任务 3. 检查调度单是否已同步:`legacy_dispatch_ord_id` 不为空 4. 查看日志确认是否有异常 5. 检查状态是否需要同步(参考状态映射表) ### 问题2:日志中出现异常 **常见原因**: - SQL Server连接失败 - 数据源配置错误 - 字段类型不匹配 **解决方法**: - 检查数据源配置 - 验证SQL Server连接 - 查看详细错误日志 ### 问题3:性能问题 **优化建议**: - 调整线程池配置 - 检查SQL Server性能 - 优化数据库索引 ## 十四、总结 本功能通过Spring事件驱动机制,实现了转运任务状态变更记录到旧系统的自动同步,具有以下特点: - ✅ **自动化**:状态变更自动同步,无需手动操作 - ✅ **解耦**:业务逻辑与同步逻辑完全分离 - ✅ **异步**:不影响主业务性能 - ✅ **完整**:记录GPS位置等详细信息 - ✅ **可靠**:容错处理,异常不影响主流程 - ✅ **可追溯**:完整的状态变更历史记录