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
+
+
+
+
+
+```
+
+---
+
+## 工作流集成
+
+### 工作流定义
+- **流程代码**:`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