diff --git a/src/api/dms/dmsRecordShutDown/types.ts b/src/api/dms/dmsRecordShutDown/types.ts index e28ddc6..dd12612 100644 --- a/src/api/dms/dmsRecordShutDown/types.ts +++ b/src/api/dms/dmsRecordShutDown/types.ts @@ -64,6 +64,11 @@ export interface DmsRecordShutDownVO { */ shutTypeName: string; + /** + * 停机原因(联表查询) + */ + shutReasonName: string; + } export interface DmsRecordShutDownForm extends BaseEntity { @@ -132,6 +137,11 @@ export interface DmsRecordShutDownForm extends BaseEntity { */ shutTypeName?: string; + /** + * 停机原因(联表查询) + */ + shutReasonName?: string; + } export interface DmsRecordShutDownQuery extends PageQuery { @@ -200,6 +210,12 @@ export interface DmsRecordShutDownQuery extends PageQuery { * 停机类型 */ shutTypeName?: string; + + /** + * 停机原因(联表查询) + */ + shutReasonName?: string; + } diff --git a/src/views/dms/dmsFaultInstanceActivity/维修工单业务流程优化文档.md b/src/views/dms/dmsFaultInstanceActivity/维修工单业务流程优化文档.md new file mode 100644 index 0000000..cb014cd --- /dev/null +++ b/src/views/dms/dmsFaultInstanceActivity/维修工单业务流程优化文档.md @@ -0,0 +1,561 @@ +# 维修工单业务流程优化文档 + +## 目录 +1. [概述](#概述) +2. [修改内容总结](#修改内容总结) +3. [业务流程梳理](#业务流程梳理) +4. [工作流集成](#工作流集成) +5. [状态流转逻辑](#状态流转逻辑) +6. [外协ID字段映射问题解决](#外协id字段映射问题解决) +7. [Web端功能简化](#web端功能简化) +8. [接口文档](#接口文档) +9. [数据表结构](#数据表结构) + +--- + +## 概述 + +本次优化基于原有故障维修工单系统,完善了审批流程、PDA端状态检查、主管确认等关键业务功能,并与Warm-flow工作流框架深度集成,实现了完整的维修工单生命周期管理。 + +### 核心改进 +- **完善审批机制**:增加工单审批环节,确保维修申请的合规性 +- **状态流转优化**:明确各阶段状态转换规则,防止非法操作 +- **工作流集成**:与Warm-flow框架深度整合,实现标准化流程管控 +- **PDA端适配**:保持PDA代码不变的前提下,完善后端状态检查逻辑 +- **外协ID映射修复**:解决PDA端outsrcId与后端outsourcingId的字段映射问题 +- **Web端功能简化**:Web端专注于审批功能,避免重复信息录入 +- **查询逻辑优化**:修复多条记录查询异常问题 + +--- + +## 修改内容总结 + +### ✅ 已完成功能 +1. **完整的审批流程** - Web端审批,PDA端状态检查 +2. **状态流转控制** - 严格的状态检查和转换逻辑 +3. **工作流集成** - 与Warm-flow框架深度整合 +4. **主管确认机制** - 维修质量的最终把关 +5. **循环维修机制** - 确认不通过自动返回维修环节 +6. **质量控制闭环** - 从申请到确认的完整质量管控体系 +7. **PDA端适配** - 保持原有PDA代码不变 +8. **代码质量保障** - 通过全面审核,确保与PDA标准完全一致 +9. **外协ID映射修复** - 解决PDA端outsrcId与后端outsourcingId的字段映射问题 +10. **Web端功能简化** - Web端专注审批,PDA端负责工单创建和维修,避免重复录入 +11. **查询逻辑优化** - 使用instance_activity_id确保获取最新活动记录 + +### 🔄 业务流程 +PDA创建工单 → Web审批 → PDA维修 → Web确认 → 工单完成 + +### 📊 技术特点 +- **代码复用性高** - 模块化设计,便于扩展 +- **状态管理严格** - 防止非法操作和数据不一致 +- **工作流标准化** - 符合企业流程管控要求 +- **接口设计清晰** - 前后端分离,易于维护 +- **PDA标准兼容** - 完全符合原有PDA客户端要求 +- **字段映射完善** - 解决不同端字段类型差异问题 +- **职责分离明确** - 各端专注自身核心功能,提高效率 + +--- + +## 业务流程梳理 + +### 整体流程图 +``` +PDA端创建工单 → 工作流启动 → Web端审批 → PDA端维修 → Web端主管确认 → 工单完成 + ↓ ↓ ↓ ↓ ↓ + 申请阶段 待审批状态 审批通过 维修完成 确认完成 +``` + +### 各端操作详情 + +#### PDA端操作 +1. **创建工单** (`insertFaultInstsanceActivity`) + - 选择设备 + - 填写故障信息(故障类型、描述、涉及操作) + - 选择维修类型(内部维修/外协维修) + - 如果选择外协,选择外协单位(传递outsrcId) + - 上传故障图片 + - 提交后自动启动工作流并生成DmsFaultInstanceActivity记录 + +2. **获取工单** (`getBillsFaultInstance4Repair`) + - 查询待维修工单列表 + - 检查审批状态 + +3. **开始维修** (`startRepair`) + - 检查审批状态(必须为"2"通过) + - 更新工单状态为"1"维修中 + - 记录维修开始时间 + +4. **完成维修** (`completeRepair`) + - 填写维修内容、措施、维修人员 + - 上传维修后图片 + - 更新工单状态为"2"维修完成 + - 设置确认状态为"0"待确认 + +#### Web端操作 +1. **审批处理** (`/dmsFaultInstanceActivity?type=approval`) + - 通过我的待办跳转到审批页面 + - 查看PDA端创建的工单详细信息(只读) + - 使用submitVerify组件完成审批 + - **注意**:Web端不创建工单,不编辑工单信息,专注于审批功能 + +2. **主管确认** (`/confirm`) + - 查看PDA端完成的维修结果 + - 确认维修质量 + - 选择确认结果: + - **确认通过**:工单完成,流程结束 + - **确认不通过**:工单返回维修环节,形成循环 + +### 业务流程简化原则 + +1. **职责分离**: + - **PDA端**:工单创建、维修执行、信息录入 + - **Web端**:审批决策、质量确认 + +2. **避免重复录入**: + - 工单信息只在PDA端录入一次 + - Web端只读显示,不允许编辑 + +3. **按创建时间倒序显示**: + - 工单实例信息按创建时间倒序排列 + - 确保最新的维修记录优先显示 + +--- + +## 外协ID字段映射问题解决 + +### 问题描述 +1. **字段类型不匹配**:PDA端使用 `outsrcId`(int类型),后端期望 `outsourcingId`(Long类型) +2. **数据表结构差异**:`dms_bills_fault_instance` 表没有 `outsourcingId` 字段,该字段在 `dms_fault_instance_activity` 表中 +3. **查询逻辑问题**:查询最新活动记录时使用了错误的字段排序,导致返回多条记录 + +### 解决方案 + +#### 1. 字段转换处理 +```java +// 在DmsBillsFaultInstanceServiceImpl.insertByBo()中添加转换逻辑 +if (bo.getOutsrcId() != null && bo.getOutsrcId() > 0) { + bo.setOutsourcingId(Long.valueOf(bo.getOutsrcId())); +} +``` + +#### 2. Bo类字段扩展 +```java +// 在DmsBillsFaultInstanceBo中添加字段 +/** + * 外协ID(PDA端传递的int类型,需要转换为outsourcingId) + */ +private Integer outsrcId; +``` + +#### 3. 查询逻辑修复 +```sql +-- 修复前:可能返回多条相同 process_step_order 的记录 +and dfia.process_step_order = (select max(process_step_order) ...) + +-- 修复后:确保返回唯一的最新记录 +and dfia.instance_activity_id = (select max(instance_activity_id) ...) +``` + +#### 4. PDA端兼容性处理 +```java +// 在DmsMobileController中处理字段转换 +if (voInstance.getOutsourcingId() != null) { + try { + mobileInstance.setOutsrcId(Math.toIntExact(voInstance.getOutsourcingId())); + } catch (ArithmeticException e) { + log.warn("外协单位ID转换失败,值过大: {}", voInstance.getOutsourcingId()); + mobileInstance.setOutsrcId(0); // 设置为0作为默认值 + } +} else { + mobileInstance.setOutsrcId(0); // 当outsourcingId为null时,明确设置为0 +} +``` + +--- + +## Web端功能简化 + +### 简化原则 +1. **移除创建功能**:Web端不再提供工单创建功能 +2. **移除编辑功能**:Web端不再提供工单信息编辑功能 +3. **专注审批**:Web端只负责审批和主管确认 +4. **只读显示**:所有工单信息以只读方式显示 + +### 具体修改 + +#### 1. 页面结构简化 +- 移除"提交"和"暂存"按钮 +- 移除分步骤的表单编辑界面 +- 改为统一的只读信息展示 + +#### 2. 表单验证简化 +```javascript +// 只保留审批相关的验证规则 +const rules = reactive({ + approveStatus: [{ required: false, message: '审批状态不能为空', trigger: 'change' }], + processHandleResolution: [{ required: false, message: '处理意见不能为空', trigger: 'blur' }] +}); +``` + +#### 3. 业务逻辑简化 +- 移除工单创建逻辑 +- 移除工单编辑逻辑 +- 保留审批和确认逻辑 + +#### 4. 界面展示优化 +```vue + + +

PDA端创建的工单详情(只读)

+ +
+``` + +--- + +## 工作流集成 + +### 工作流定义 +- **流程代码**:`Fault01` +- **节点配置**: + 1. 故障申请(PDA端) + 2. 工单审批(Web端) + 3. 维修处理(PDA端) + 4. 主管确认(Web端) + +### 状态映射关系 +| 工作流状态 | 工单状态 | 审批状态 | 确认状态 | 说明 | +|-----------|---------|---------|---------|------| +| 故障申请 | 0(待维修) | 1(待审批) | null | PDA端创建工单后 | +| 工单审批 | 0(待维修) | 2(审批通过)/3(审批拒绝) | null | Web端审批后 | +| 维修处理 | 1(维修中)/2(维修完成) | 2(审批通过) | 0(待确认) | PDA端维修过程 | +| 主管确认 | 2(维修完成) | 2(审批通过) | 1(确认完成)/2(确认不通过) | Web端确认 | + +--- + +## 状态流转逻辑 + +### 状态检查规则 +1. **开始维修前检查**: + - 审批状态必须为"2"(审批通过) + - 工单状态必须为"0"(待维修) + +2. **完成维修后状态**: + - 工单状态更新为"2"(维修完成) + - 确认状态设置为"0"(待确认) + +3. **主管确认规则**: + - 确认通过:工单完成,流程结束 + - 确认不通过:返回维修环节,形成循环 + +### 循环维修机制 +- 主管确认不通过时,工单状态回到"0"(待维修) +- PDA端可以重新开始维修 +- 系统创建新的活动记录,保持历史记录完整性 + +--- + +## 接口文档 + +### PDA端接口 + +#### 1. 创建故障工单 +- **接口**:`POST /dms/mobile/insertFaultInstsanceActivity` +- **参数**: + ```json + { + "deviceId": 20033, + "outsrcId": 1, // PDA端传递的外协ID + "faultType": "1", + "faultDescription": "设备故障描述", + "repairType": "2" + } + ``` + +#### 2. 获取工单详情 +- **接口**:`GET /dms/mobile/getBillsFaultInstance4Repair/{repairInstanceId}` +- **返回**:包含转换后的outsrcId字段 + +#### 3. 开始维修 +- **接口**:`POST /dms/mobile/startRepair` +- **状态检查**:审批状态必须为"2" + +#### 4. 完成维修 +- **接口**:`POST /dms/mobile/completeRepair` +- **状态更新**:工单状态→"2",确认状态→"0" + +### Web端接口 + +#### 1. 审批工单 +- **接口**:`POST /dms/dmsBillsFaultInstance/approve` +- **参数**: + ```json + { + "repairInstanceId": "工单ID", + "approveStatus": "2", // 2-通过,3-拒绝 + "message": "审批意见" + } + ``` + +#### 2. 主管确认 +- **接口**:`POST /dms/dmsBillsFaultInstance/confirm` +- **参数**: + ```json + { + "repairInstanceId": "工单ID", + "confirmResult": "1", // 1-确认通过,2-确认不通过 + "confirmUser": "确认人" + } + ``` + +--- + +## 数据表结构 + +### 主要表结构 + +#### 1. dms_bills_fault_instance(故障工单主表) +- `repair_instance_id`:工单主键 +- `bills_status`:工单状态(0待维修,1维修中,2维修完成) +- `approve_status`:审批状态(1待审批,2审批通过,3审批拒绝) +- `repair_confirm`:确认状态(0待确认,1确认完成,2确认不通过) + +#### 2. dms_fault_instance_activity(故障工单活动表) +- `instance_activity_id`:活动主键(自增ID) +- `repair_instance_id`:关联工单主键 +- `outsourcing_id`:外协单位ID(Long类型) +- `process_step_order`:流程步骤顺序 + +### 字段映射关系 +| PDA端字段 | 后端字段 | 数据类型转换 | 说明 | +|----------|---------|-------------|------| +| outsrcId | outsourcingId | int → Long | 外协单位ID | +| deviceId | machineId | int → Long | 设备ID | +| repairInstanceId | repairInstanceId | String → Long | 工单ID | + +--- + +## 🚀 后续优化建议 +1. 添加工单超时预警机制 +2. 完善维修知识库集成 +3. 增加维修效率统计分析 +4. 支持批量操作功能 +5. 前端常量统一管理(避免硬编码) +6. 添加外协单位管理功能 +7. 完善维修历史记录查询和统计分析 +8. 优化查询性能,添加适当索引 +9. 完善异常处理和日志记录 +10. 添加数据备份和恢复机制 + +## 问题背景 +在维修工单系统的使用过程中,发现了以下问题: +1. PDA端显示的工单数量与数据库实际记录不符 +2. 点击工单时出现SQL查询异常:`Expected one result (or null) to be returned by selectOne(), but found: 2` +3. 外协ID字段映射问题:PDA端传递`outsrcId`(int),后端期望`outsourcingId`(Long) +4. Web端和PDA端功能重复,用户需要在两个端重复录入信息 + +## 根本原因分析 +1. **查询逻辑问题**:使用`MAX(process_step_order)`查询最新记录时,在循环维修场景下会返回多条相同最大值的记录 +2. **字段映射不匹配**:PDA端使用`outsrcId`(int),后端使用`outsourcingId`(Long) +3. **业务流程设计问题**:Web端和PDA端都在创建和编辑工单信息 +4. **数据库异常处理**:在某些边界情况下,查询可能返回多条记录导致系统异常 + +## 解决方案 + +### 1. 数据库查询优化 +**问题**:`selectFaultInstanceJoinFirstAndDeviceById`查询可能返回多条记录 + +**解决方案**: +- 修改SQL查询逻辑,使用更精确的条件确保返回唯一记录 +- 添加备用查询方案,当主查询失败时自动切换 + +```xml + + +``` + +### 2. 防重复机制 +**问题**:在网络不稳定或重试场景下,可能重复插入维修记录 + +**解决方案**: +- 在开始维修前检查是否已存在相同步骤的记录 +- 添加幂等性保护,避免重复操作 + +```java +// 防重复检查 +MPJLambdaWrapper checkWrapper = JoinWrappers.lambda(DmsFaultInstanceActivity.class) + .eq(DmsFaultInstanceActivity::getRepairInstanceId, repairInstanceId) + .eq(DmsFaultInstanceActivity::getProcessStepOrder, 2L); +Long existingCount = dmsFaultInstanceActivityMapper.selectCount(checkWrapper); +if (existingCount > 0) { + log.warn("工单已经开始维修,无需重复操作,repairInstanceId: {}", repairInstanceId); + return 1; // 返回成功,避免重复操作 +} +``` + +### 3. 异常处理机制 +**问题**:当查询返回多条记录时,系统直接抛出异常 + +**解决方案**: +- 添加异常捕获和备用查询方案 +- 提供降级处理机制 + +```java +try { + // 主查询方案 + DmsBillsFaultInstanceVo dmsBillsFaultInstance = baseMapper.selectFaultInstanceJoinFirstAndDeviceById(repairInstanceId); + return dmsBillsFaultInstance; +} catch (Exception e) { + if (e.getMessage() != null && e.getMessage().contains("Expected one result")) { + log.warn("检测到查询返回多条记录异常,尝试备用查询方案,repairInstanceId: {}", repairInstanceId); + + // 备用方案:分别查询工单基本信息和最新活动记录 + DmsBillsFaultInstanceVo workOrder = baseMapper.selectVoById(repairInstanceId); + // 查询最新的活动记录并合并数据 + // ... + return workOrder; + } + throw new ServiceException("查询工单详情失败:" + e.getMessage()); +} +``` + +### 4. 数据清理建议 +如果数据库中已经存在重复或异常数据,建议执行以下清理操作: + +```sql +-- 1. 查找重复的活动记录 +SELECT repair_instance_id, process_step_order, COUNT(*) as count +FROM dms_fault_instance_activity +GROUP BY repair_instance_id, process_step_order +HAVING COUNT(*) > 1; + +-- 2. 保留最新的记录,删除重复记录(谨慎操作,建议先备份) +-- 这里需要根据具体情况制定清理策略 +``` + +### 5. 外协ID字段映射修复 +**问题**:PDA端传递`outsrcId`(int),后端期望`outsourcingId`(Long) + +**解决方案**: +1. 在`DmsBillsFaultInstanceBo`中添加`outsrcId`字段用于接收PDA端数据 +2. 在`insertByBo`方法中实现字段转换 +3. 在返回数据时进行反向转换,确保PDA端兼容性 + +```java +// 在DmsBillsFaultInstanceBo中添加字段 +private Integer outsrcId; // PDA端传递的外协ID + +// 在insertByBo方法中转换 +if (bo.getOutsrcId() != null && bo.getOutsrcId() > 0) { + bo.setOutsourcingId(Long.valueOf(bo.getOutsrcId())); +} +``` + +### 6. Web端功能简化 +**问题**:Web端和PDA端功能重复,造成用户困惑 + +**解决方案**: +1. **PDA端职责**:工单创建、维修执行、信息录入 +2. **Web端职责**:审批决策、质量确认 +3. **简化流程**:PDA创建工单 → Web审批 → PDA维修 → Web确认 → 工单完成 + +#### Web端修改内容: +- 移除工单创建和编辑功能 +- 所有工单信息设为只读显示 +- 专注于审批和确认功能 + +### 7. 业务流程重新设计 + +#### 优化后的流程: +``` +1. PDA端创建工单 + ├── 录入故障信息 + ├── 上传故障图片 + └── 提交审批 + +2. Web端审批 + ├── 查看工单详情(只读) + ├── 审批决策(通过/拒绝) + └── 推送通知 + +3. PDA端维修执行 + ├── 接收审批通知 + ├── 开始维修 + ├── 记录维修过程 + ├── 更换零部件记录 + ├── 上传维修图片 + └── 完成维修 + +4. Web端质量确认 + ├── 查看维修结果(只读) + ├── 确认维修质量 + └── 工单完成 +``` + +## 技术实现细节 + +### 字段映射关系 +| PDA端字段 | 后端字段 | 数据类型转换 | 说明 | +|----------|---------|-------------|------| +| outsrcId | outsourcingId | int → Long | 外协单位ID | +| deviceId | machineId | int → Long | 设备ID | + +### 关键代码修改点 +1. **DmsBillsFaultInstanceServiceImpl.java**: + - 添加outsrcId到outsourcingId转换逻辑 + - 增加防重复检查机制 + - 添加异常处理和备用查询方案 + +2. **DmsBillsFaultInstanceMapper.xml**: + - 优化查询逻辑,确保返回唯一记录 + +3. **Web端Vue页面**: + - 简化功能,移除创建编辑逻辑 + - 改为只读显示模式 + +### 监控和日志 +- 添加详细的调试日志,跟踪outsourcingId的传递过程 +- 记录查询异常和备用方案的使用情况 +- 监控重复操作的发生频率 + +## 预期效果 +1. ✅ 解决SQL查询返回多条记录的异常 +2. ✅ 修复外协ID字段映射问题 +3. ✅ 简化Web端功能,避免重复录入 +4. ✅ 明确各端职责分工 +5. ✅ 保持PDA代码完全不变 +6. ✅ 提高系统稳定性和用户体验 +7. ✅ 增强异常处理能力 +8. ✅ 提供数据清理和恢复机制 + +## 风险控制 +1. **数据安全**:所有数据库操作都在事务中执行 +2. **向下兼容**:保持PDA端接口不变 +3. **降级处理**:提供备用查询方案 +4. **监控告警**:记录异常情况便于排查 +5. **回滚机制**:保留原有逻辑作为备用方案 + +## 后续优化建议 +1. 考虑添加数据库索引优化查询性能 +2. 实现自动数据清理机制 +3. 添加更完善的监控和告警系统 +4. 考虑引入分布式锁防止并发问题 +5. 优化工作流程,减少不必要的步骤 \ No newline at end of file