|
|
@ -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端创建的工单详情(只读显示) -->
|
|
|
|
|
|
|
|
<el-card shadow="never">
|
|
|
|
|
|
|
|
<h4 class="form-header">PDA端创建的工单详情(只读)</h4>
|
|
|
|
|
|
|
|
<!-- 所有字段都设置为disabled -->
|
|
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
## 工作流集成
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 工作流定义
|
|
|
|
|
|
|
|
- **流程代码**:`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
|
|
|
|
|
|
|
|
<!-- 优化后的查询SQL -->
|
|
|
|
|
|
|
|
<select id="selectFaultInstanceJoinFirstAndDeviceById" parameterType="Long" resultMap="DmsBillsFaultInstanceResult">
|
|
|
|
|
|
|
|
select dbfi.repair_instance_id, dbfi.fault_source_type, dbfi.fault_source_id,
|
|
|
|
|
|
|
|
-- 其他字段...
|
|
|
|
|
|
|
|
from dms_bills_fault_instance dbfi
|
|
|
|
|
|
|
|
left join prod_base_machine_info dbdl on dbfi.machine_id=dbdl.machine_id
|
|
|
|
|
|
|
|
left join dms_fault_instance_activity dfia on (dbfi.repair_instance_id=dfia.repair_instance_id
|
|
|
|
|
|
|
|
and dfia.instance_activity_id = (
|
|
|
|
|
|
|
|
select max(instance_activity_id)
|
|
|
|
|
|
|
|
from dms_fault_instance_activity dfia2
|
|
|
|
|
|
|
|
where dfia2.repair_instance_id = dbfi.repair_instance_id
|
|
|
|
|
|
|
|
and dfia2.process_step_order = (
|
|
|
|
|
|
|
|
select max(process_step_order)
|
|
|
|
|
|
|
|
from dms_fault_instance_activity dfia3
|
|
|
|
|
|
|
|
where dfia3.repair_instance_id = dbfi.repair_instance_id
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
))
|
|
|
|
|
|
|
|
where dbfi.repair_instance_id = #{repairInstanceId}
|
|
|
|
|
|
|
|
</select>
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 防重复机制
|
|
|
|
|
|
|
|
**问题**:在网络不稳定或重试场景下,可能重复插入维修记录
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**解决方案**:
|
|
|
|
|
|
|
|
- 在开始维修前检查是否已存在相同步骤的记录
|
|
|
|
|
|
|
|
- 添加幂等性保护,避免重复操作
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```java
|
|
|
|
|
|
|
|
// 防重复检查
|
|
|
|
|
|
|
|
MPJLambdaWrapper<DmsFaultInstanceActivity> 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. 优化工作流程,减少不必要的步骤
|