2173 lines
76 KiB
Markdown
2173 lines
76 KiB
Markdown
|
|
# 连续制造业改进方案
|
|||
|
|
|
|||
|
|
## 1. 核心思路(5分钟读懂)
|
|||
|
|
|
|||
|
|
### 1.1 改进目标
|
|||
|
|
在现有MES系统基础上,支持连续制造业(化工、钢铁、水泥等)的生产报工流程,实现按时间段/班次报工,兼容现有离散制造业模式。
|
|||
|
|
|
|||
|
|
### 1.2 核心设计:物料级别的类型标识
|
|||
|
|
|
|||
|
|
**关键点**:在 `md_material`(物料表)中新增2个字段作为"开关"
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
manufacture_type -- 制造类型: DISCRETE(离散) / CONTINUOUS(连续)
|
|||
|
|
report_mode -- 报工模式: PROCESS(按工序) / TIME(按时间) / SHIFT(按班次) / QUANTITY(按产量) / BATCH(按批次)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**报工模式说明**:
|
|||
|
|
|
|||
|
|
| 报工模式 | 适用场景 | 报工方式 | 示例 |
|
|||
|
|
|---------|---------|---------|------|
|
|||
|
|
| `PROCESS` | 离散制造业 | 按工序完成报工 | 工序1完成 → 报工1次 |
|
|||
|
|
| `TIME` | 连续制造业 | 按固定时间段报工 | 每小时报工一次 |
|
|||
|
|
| `SHIFT` | 连续制造业 | 按班次报工 | 每班次结束报工一次 |
|
|||
|
|
| `QUANTITY` | 连续制造业 | 按达到的产量报工 | 每生产100吨报工一次 |
|
|||
|
|
| `BATCH` | 连续制造业 | 按生产批次报工 | 每完成一个批次报工一次 |
|
|||
|
|
|
|||
|
|
**数据流转逻辑**:
|
|||
|
|
```
|
|||
|
|
物料表设置类型
|
|||
|
|
↓
|
|||
|
|
销售订单选择物料(继承物料的类型)
|
|||
|
|
↓
|
|||
|
|
生成工单时判断物料类型 → 决定工单生成方式
|
|||
|
|
↓
|
|||
|
|
报工时判断工单类型 → 决定报工方式
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 完整业务流程(核心)
|
|||
|
|
|
|||
|
|
### 2.1 流程对比
|
|||
|
|
|
|||
|
|
| 环节 | 离散制造业 | 连续-按时间 | 连续-按班次 | 连续-按产量 | 连续-按批次 |
|
|||
|
|
|------|-----------|-----------|-----------|-----------|-----------|
|
|||
|
|
| **1. 物料设置** | `DISCRETE`<br>`PROCESS` | `CONTINUOUS`<br>`TIME` | `CONTINUOUS`<br>`SHIFT` | `CONTINUOUS`<br>`QUANTITY` | `CONTINUOUS`<br>`BATCH` |
|
|||
|
|
| **2. 工单生成** | 按工序生成多个<br>`XS001-P01`, `P02` | 生成一个工单<br>`XS001` | 生成一个工单<br>`XS001` | 生成一个工单<br>`XS001` | 生成一个工单<br>`XS001` |
|
|||
|
|
| **3. 工单分录** | 创建(每个工序) | **不创建** | **不创建** | **不创建** | **不创建** |
|
|||
|
|
| **4. 报工方式** | 按工序完成 | 按时间段 | 按班次 | 按产量 | 按批次 |
|
|||
|
|
| **5. 报工示例** | 工序1完成 → 报工 | 08:00-09:00<br>09:00-10:00 | 早班<br>中班<br>晚班 | 累计100吨<br>累计200吨 | 批次1<br>批次2 |
|
|||
|
|
| **6. 报工频率** | 每个工序1次 | 每小时 | 每班次 | 达到产量 | 批次完成 |
|
|||
|
|
| **7. 时间段** | 无 | 固定(1小时) | 固定(8小时) | 不固定 | 不固定 |
|
|||
|
|
| **8. 班次字段** | 不使用 | 可选填写 | **必填** | 可选填写 | 可选填写 |
|
|||
|
|
| **9. 完成判断** | 所有工序完成 | 累计 ≥ 计划 | 累计 ≥ 计划 | 累计 ≥ 计划 | 累计 ≥ 计划 |
|
|||
|
|
|
|||
|
|
### 2.2 详细流程图
|
|||
|
|
|
|||
|
|
#### 流程A:离散制造业(现有逻辑,保持不变)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 物料管理
|
|||
|
|
└─ 设置物料:manufacture_type = 'DISCRETE', report_mode = 'PROCESS'
|
|||
|
|
└─ 关联工序路线(route_id)
|
|||
|
|
|
|||
|
|
2. 销售订单
|
|||
|
|
└─ 创建订单明细,选择物料
|
|||
|
|
└─ 查询物料信息(包含 manufacture_type, report_mode)
|
|||
|
|
|
|||
|
|
3. 生成工单(关键判断点)
|
|||
|
|
└─ 读取物料的 manufacture_type
|
|||
|
|
└─ if (manufacture_type == 'DISCRETE') {
|
|||
|
|
// 按工序路线生成多个工单
|
|||
|
|
for (每个工序) {
|
|||
|
|
创建工单:batch_number = "XS001-P01", "XS001-P02"...
|
|||
|
|
创建工单分录:关联工序信息
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
4. 报工
|
|||
|
|
└─ 选择工单分录(work_order_entry_id)
|
|||
|
|
└─ 提交报工:报工数量、合格数、不合格数
|
|||
|
|
└─ 更新工单分录状态
|
|||
|
|
└─ 检查:所有工序完成 → 工单完成
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 流程B:连续制造业(新增逻辑)
|
|||
|
|
|
|||
|
|
**共同点**:
|
|||
|
|
- 只生成一个工单(不按工序)
|
|||
|
|
- 不创建工单分录
|
|||
|
|
- 可以多次报工
|
|||
|
|
- 累计报工数量达到计划数量即完成
|
|||
|
|
|
|||
|
|
**差异点**:根据 `report_mode` 决定报工触发方式
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
##### B1:按时间报工(TIME)
|
|||
|
|
|
|||
|
|
**适用场景**:化工、钢铁等连续生产,按固定时间段统计产量
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 物料管理
|
|||
|
|
└─ 设置物料:manufacture_type = 'CONTINUOUS', report_mode = 'TIME'
|
|||
|
|
|
|||
|
|
2. 生成工单
|
|||
|
|
└─ 创建工单:batch_number = "XS001", report_mode = 'TIME'
|
|||
|
|
|
|||
|
|
3. 报工(按时间段)
|
|||
|
|
└─ 08:00-09:00 → 报工:100吨
|
|||
|
|
└─ 09:00-10:00 → 报工:120吨
|
|||
|
|
└─ 10:00-11:00 → 报工:110吨
|
|||
|
|
└─ 累计:330吨
|
|||
|
|
|
|||
|
|
4. 报工信息
|
|||
|
|
- report_period_start: 2025-01-11 08:00:00
|
|||
|
|
- report_period_end: 2025-01-11 09:00:00
|
|||
|
|
- shift_name: 早班
|
|||
|
|
- report_quantity: 100
|
|||
|
|
- equipment_id: 10
|
|||
|
|
- downtime_minutes: 10(停机10分钟)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
##### B2:按班次报工(SHIFT)
|
|||
|
|
|
|||
|
|
**适用场景**:三班倒生产,按班次统计产量
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 物料管理
|
|||
|
|
└─ 设置物料:manufacture_type = 'CONTINUOUS', report_mode = 'SHIFT'
|
|||
|
|
|
|||
|
|
2. 生成工单
|
|||
|
|
└─ 创建工单:batch_number = "XS001", report_mode = 'SHIFT'
|
|||
|
|
|
|||
|
|
3. 报工(按班次)
|
|||
|
|
└─ 早班(08:00-16:00)→ 报工:800吨
|
|||
|
|
└─ 中班(16:00-00:00)→ 报工:750吨
|
|||
|
|
└─ 晚班(00:00-08:00)→ 报工:700吨
|
|||
|
|
└─ 累计:2250吨
|
|||
|
|
|
|||
|
|
4. 报工信息
|
|||
|
|
- report_period_start: 2025-01-11 08:00:00(班次开始)
|
|||
|
|
- report_period_end: 2025-01-11 16:00:00(班次结束)
|
|||
|
|
- shift_name: 早班(必填)
|
|||
|
|
- report_quantity: 800(本班次产量)
|
|||
|
|
- equipment_id: 10
|
|||
|
|
- downtime_minutes: 30(本班次停机30分钟)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
##### B3:按产量报工(QUANTITY)
|
|||
|
|
|
|||
|
|
**适用场景**:水泥、食品等,按达到的产量节点报工
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 物料管理
|
|||
|
|
└─ 设置物料:manufacture_type = 'CONTINUOUS', report_mode = 'QUANTITY'
|
|||
|
|
|
|||
|
|
2. 生成工单
|
|||
|
|
└─ 创建工单:batch_number = "XS001", report_mode = 'QUANTITY'
|
|||
|
|
|
|||
|
|
3. 报工(按产量节点)
|
|||
|
|
└─ 累计达到100吨 → 报工1:100吨(08:00-09:30)
|
|||
|
|
└─ 累计达到200吨 → 报工2:100吨(09:30-11:00)
|
|||
|
|
└─ 累计达到300吨 → 报工3:100吨(11:00-12:20)
|
|||
|
|
└─ 累计:300吨
|
|||
|
|
|
|||
|
|
4. 报工信息
|
|||
|
|
- report_period_start: 2025-01-11 08:00:00(开始时间)
|
|||
|
|
- report_period_end: 2025-01-11 09:30:00(达到100吨的时间)
|
|||
|
|
- report_quantity: 100(本次报工数量)
|
|||
|
|
- shift_name: 早班(可选)
|
|||
|
|
- remark: 累计产量达到100吨
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
##### B4:按批次报工(BATCH)
|
|||
|
|
|
|||
|
|
**适用场景**:制药、精细化工等,按生产批次报工
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
1. 物料管理
|
|||
|
|
└─ 设置物料:manufacture_type = 'CONTINUOUS', report_mode = 'BATCH'
|
|||
|
|
|
|||
|
|
2. 生成工单
|
|||
|
|
└─ 创建工单:batch_number = "XS001", report_mode = 'BATCH'
|
|||
|
|
|
|||
|
|
3. 报工(按批次)
|
|||
|
|
└─ 批次1完成 → 报工1:50吨(批次号:20250111-001)
|
|||
|
|
└─ 批次2完成 → 报工2:48吨(批次号:20250111-002)
|
|||
|
|
└─ 批次3完成 → 报工3:52吨(批次号:20250111-003)
|
|||
|
|
└─ 累计:150吨
|
|||
|
|
|
|||
|
|
4. 报工信息
|
|||
|
|
- report_period_start: 2025-01-11 08:00:00(批次开始)
|
|||
|
|
- report_period_end: 2025-01-11 10:30:00(批次完成)
|
|||
|
|
- report_sequence: 1(第1个批次)
|
|||
|
|
- report_quantity: 50(本批次产量)
|
|||
|
|
- shift_name: 早班(可选)
|
|||
|
|
- remark: 批次号:20250111-001
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**四种模式对比**:
|
|||
|
|
|
|||
|
|
| 对比项 | 按时间(TIME) | 按班次(SHIFT) | 按产量(QUANTITY) | 按批次(BATCH) |
|
|||
|
|
|-------|--------------|---------------|-----------------|---------------|
|
|||
|
|
| 报工触发 | 固定时间到达 | 班次结束 | 产量达到节点 | 批次完成 |
|
|||
|
|
| 时间段 | 固定(如1小时) | 固定(如8小时) | 不固定 | 不固定 |
|
|||
|
|
| 产量 | 不固定 | 不固定 | 固定(如100吨) | 不固定 |
|
|||
|
|
| 班次字段 | 可选 | **必填** | 可选 | 可选 |
|
|||
|
|
| 适用场景 | 连续稳定生产 | 三班倒生产 | 产量为主要指标 | 批次管理严格 |
|
|||
|
|
| 报工频率 | 高(每小时) | 中(每班次) | 中(达到产量) | 低(批次完成) |
|
|||
|
|
| 典型行业 | 化工、钢铁 | 制造业三班倒 | 水泥、食品 | 制药、精细化工 |
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.3 关键判断点代码逻辑
|
|||
|
|
|
|||
|
|
#### 判断点1:生成工单时(ProWorkorderService.generateWorkOrder)
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 1. 查询销售订单明细
|
|||
|
|
SalOrderEntry entry = salOrderEntryMapper.selectById(entryId);
|
|||
|
|
|
|||
|
|
// 2. 查询物料信息(关键:获取 manufacture_type)
|
|||
|
|
Material material = materialMapper.selectById(entry.getMaterialId());
|
|||
|
|
|
|||
|
|
// 3. 根据制造类型分流
|
|||
|
|
if ("CONTINUOUS".equals(material.getManufactureType())) {
|
|||
|
|
// 连续制造业:生成一个工单
|
|||
|
|
return generateContinuousWorkOrder(entry, material);
|
|||
|
|
} else {
|
|||
|
|
// 离散制造业:按工序生成多个工单(现有逻辑)
|
|||
|
|
return generateDiscreteWorkOrders(entry, material);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 判断点2:报工时(ProReportService.submitReport)
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 1. 根据报工单获取工单信息
|
|||
|
|
Long workOrderId = report.getWorkOrderId() != null ?
|
|||
|
|
report.getWorkOrderId() :
|
|||
|
|
getWorkOrderIdByEntryId(report.getWorkOrderEntryId());
|
|||
|
|
|
|||
|
|
ProWorkorder workOrder = workorderMapper.selectById(workOrderId);
|
|||
|
|
|
|||
|
|
// 2. 根据工单的制造类型分流
|
|||
|
|
if ("CONTINUOUS".equals(workOrder.getManufactureType())) {
|
|||
|
|
// 连续制造业报工逻辑
|
|||
|
|
return submitContinuousReport(report, workOrder);
|
|||
|
|
} else {
|
|||
|
|
// 离散制造业报工逻辑(现有逻辑)
|
|||
|
|
return submitDiscreteReport(report, workOrder);
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.4 数据关联关系
|
|||
|
|
|
|||
|
|
#### 离散制造业(现有)
|
|||
|
|
```
|
|||
|
|
md_material (物料)
|
|||
|
|
↓ material_id
|
|||
|
|
sal_order_entry (订单明细)
|
|||
|
|
↓ 生成工单
|
|||
|
|
pro_workorder (工单1: P01)
|
|||
|
|
↓ workorder_id
|
|||
|
|
pro_workorder_entry (工单分录: 工序1)
|
|||
|
|
↓ work_order_entry_id
|
|||
|
|
pro_report (报工单)
|
|||
|
|
|
|||
|
|
pro_workorder (工单2: P02)
|
|||
|
|
↓ workorder_id
|
|||
|
|
pro_workorder_entry (工单分录: 工序2)
|
|||
|
|
↓ work_order_entry_id
|
|||
|
|
pro_report (报工单)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 连续制造业(新增)
|
|||
|
|
```
|
|||
|
|
md_material (物料)
|
|||
|
|
↓ material_id
|
|||
|
|
sal_order_entry (订单明细)
|
|||
|
|
↓ 生成工单
|
|||
|
|
pro_workorder (工单: XS001)
|
|||
|
|
↓ work_order_id (直接关联,跳过工单分录)
|
|||
|
|
pro_report (报工单1: 08:00-09:00)
|
|||
|
|
pro_report (报工单2: 09:00-10:00)
|
|||
|
|
pro_report (报工单3: 10:00-11:00)
|
|||
|
|
...
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 设计原则
|
|||
|
|
|
|||
|
|
1. **向后兼容**:不影响现有离散制造业流程
|
|||
|
|
2. **最小改动**:复用现有表结构,新增字段标识
|
|||
|
|
3. **简化逻辑**:连续制造业不使用工单分录,报工直接关联工单
|
|||
|
|
4. **物料驱动**:所有判断逻辑都基于物料的 `manufacture_type` 字段
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 数据库表分析与评估
|
|||
|
|
|
|||
|
|
### 3.1 现有相关表梳理
|
|||
|
|
|
|||
|
|
#### ✅ 已存在可复用的表
|
|||
|
|
|
|||
|
|
| 表名 | 用途 | 是否满足需求 |
|
|||
|
|
|------|------|------------|
|
|||
|
|
| `md_material` | 物料主数据 | ✅ 需新增字段 |
|
|||
|
|
| `md_workshop` | 车间管理 | ✅ 可直接使用 |
|
|||
|
|
| `md_station` | 工位管理 | ✅ 可直接使用 |
|
|||
|
|
| `dm_equipment` | 设备管理 | ✅ 可直接使用(已有完整设备表) |
|
|||
|
|
| `pro_workorder` | 生产工单 | ✅ 需新增字段 |
|
|||
|
|
| `pro_workorder_entry` | 工单分录 | ✅ 连续制造业不使用 |
|
|||
|
|
| `pro_report` | 报工单 | ✅ 需新增字段 |
|
|||
|
|
| `pro_process` | 工序定义 | ✅ 连续制造业不使用 |
|
|||
|
|
| `pro_route` | 工序路线 | ✅ 连续制造业不使用 |
|
|||
|
|
| `sal_order` | 销售订单 | ✅ 可直接使用 |
|
|||
|
|
| `sal_order_entry` | 订单明细 | ✅ 可直接使用 |
|
|||
|
|
|
|||
|
|
#### 📊 设备表详情(dm_equipment)
|
|||
|
|
|
|||
|
|
系统已有完整的设备管理表,包含以下字段:
|
|||
|
|
- `id`, `number`, `name` - 基础信息
|
|||
|
|
- `brand`, `specification`, `type` - 设备属性
|
|||
|
|
- `station_id`, `station_name` - 关联工位
|
|||
|
|
- `equipment_status` - 设备状态
|
|||
|
|
- `iot_sn` - 物联网序列号
|
|||
|
|
|
|||
|
|
**结论**:✅ 设备表完全满足需求,无需新建,直接使用 `dm_equipment`
|
|||
|
|
|
|||
|
|
### 3.2 需要新建的表评估
|
|||
|
|
|
|||
|
|
#### ❌ 不需要新建的表
|
|||
|
|
|
|||
|
|
| 表名 | 原因 |
|
|||
|
|
|------|------|
|
|||
|
|
| ~~设备表~~ | 已有 `dm_equipment` |
|
|||
|
|
| ~~班次表~~ | 第一版使用字符串字段 `shift_name` 即可 |
|
|||
|
|
| ~~停机记录表~~ | 停机信息直接记录在 `pro_report` 中 |
|
|||
|
|
| ~~产线表~~ | 可使用 `md_workshop`(车间)代替 |
|
|||
|
|
|
|||
|
|
#### ⚠️ 可选新建的表(后续版本)
|
|||
|
|
|
|||
|
|
**1. 班次管理表(md_shift)** - 优先级:P2
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE `md_shift` (
|
|||
|
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|||
|
|
`shift_code` varchar(32) NOT NULL COMMENT '班次编码',
|
|||
|
|
`shift_name` varchar(64) NOT NULL COMMENT '班次名称',
|
|||
|
|
`start_time` time NOT NULL COMMENT '开始时间',
|
|||
|
|
`end_time` time NOT NULL COMMENT '结束时间',
|
|||
|
|
`is_cross_day` tinyint(1) DEFAULT 0 COMMENT '是否跨天',
|
|||
|
|
`sort` int DEFAULT 0 COMMENT '排序',
|
|||
|
|
`status` varchar(2) DEFAULT '0' COMMENT '状态',
|
|||
|
|
`remark` varchar(255) COMMENT '备注',
|
|||
|
|
PRIMARY KEY (`id`),
|
|||
|
|
UNIQUE KEY `uk_shift_code` (`shift_code`)
|
|||
|
|
) COMMENT='班次管理表';
|
|||
|
|
```
|
|||
|
|
**说明**:第一版可以不建,使用字符串字段即可。后续如需班次时间管理再建。
|
|||
|
|
|
|||
|
|
**2. 停机记录表(pro_downtime_record)** - 优先级:P2
|
|||
|
|
```sql
|
|||
|
|
CREATE TABLE `pro_downtime_record` (
|
|||
|
|
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|||
|
|
`work_order_id` bigint NOT NULL COMMENT '工单ID',
|
|||
|
|
`equipment_id` bigint COMMENT '设备ID',
|
|||
|
|
`downtime_start` datetime NOT NULL COMMENT '停机开始时间',
|
|||
|
|
`downtime_end` datetime COMMENT '停机结束时间',
|
|||
|
|
`downtime_minutes` int COMMENT '停机时长(分钟)',
|
|||
|
|
`downtime_type` varchar(32) COMMENT '停机类型',
|
|||
|
|
`downtime_reason` varchar(500) COMMENT '停机原因',
|
|||
|
|
`handler` varchar(64) COMMENT '处理人',
|
|||
|
|
`remark` text COMMENT '备注',
|
|||
|
|
`create_time` datetime NOT NULL COMMENT '创建时间',
|
|||
|
|
PRIMARY KEY (`id`),
|
|||
|
|
KEY `idx_work_order_id` (`work_order_id`),
|
|||
|
|
KEY `idx_equipment_id` (`equipment_id`),
|
|||
|
|
KEY `idx_downtime_start` (`downtime_start`)
|
|||
|
|
) COMMENT='停机记录表';
|
|||
|
|
```
|
|||
|
|
**说明**:第一版停机信息记录在 `pro_report` 中即可。后续如需详细停机分析再建独立表。
|
|||
|
|
|
|||
|
|
### 3.3 结论
|
|||
|
|
|
|||
|
|
**第一版实施方案(最简化)**:
|
|||
|
|
- ✅ **只修改3张表**:`md_material`, `pro_workorder`, `pro_report`
|
|||
|
|
- ✅ **复用现有表**:`dm_equipment`(设备)、`md_workshop`(车间)
|
|||
|
|
- ✅ **不新建表**:班次、停机等信息用字段记录
|
|||
|
|
- ✅ **向后兼容**:所有新增字段都有默认值
|
|||
|
|
|
|||
|
|
**后续优化方向(P2)**:
|
|||
|
|
- 如需班次时间管理 → 建 `md_shift` 表
|
|||
|
|
- 如需停机详细分析 → 建 `pro_downtime_record` 表
|
|||
|
|
- 如需产线管理 → 扩展 `md_workshop` 或新建产线表
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 数据库改动(按执行顺序)
|
|||
|
|
|
|||
|
|
### 步骤1:物料表新增字段
|
|||
|
|
> 基于现有 `md_material` 表结构
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 标识物料的制造类型和报工配置
|
|||
|
|
ALTER TABLE md_material
|
|||
|
|
ADD COLUMN manufacture_type VARCHAR(20) DEFAULT 'DISCRETE' COMMENT '制造类型: DISCRETE-离散, CONTINUOUS-连续',
|
|||
|
|
ADD COLUMN report_mode VARCHAR(20) COMMENT '报工模式: PROCESS-按工序, TIME-按时间, SHIFT-按班次, QUANTITY-按产量, BATCH-按批次';
|
|||
|
|
|
|||
|
|
-- 创建索引
|
|||
|
|
CREATE INDEX idx_manufacture_type ON md_material(manufacture_type);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**说明**:
|
|||
|
|
- `route_id` 字段已存在,用于关联工序路线(离散制造业使用)
|
|||
|
|
- 连续制造业的物料可以不设置 `route_id`
|
|||
|
|
|
|||
|
|
### 步骤2:工单表新增字段
|
|||
|
|
> 基于现有 `pro_workorder` 表结构
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 支持连续制造业的工单管理
|
|||
|
|
ALTER TABLE pro_workorder
|
|||
|
|
ADD COLUMN manufacture_type VARCHAR(20) DEFAULT 'DISCRETE' COMMENT '制造类型: DISCRETE-离散, CONTINUOUS-连续',
|
|||
|
|
ADD COLUMN report_mode VARCHAR(20) DEFAULT 'PROCESS' COMMENT '报工模式: PROCESS-按工序, TIME-按时间',
|
|||
|
|
ADD COLUMN total_report_count INT DEFAULT 0 COMMENT '总报工次数',
|
|||
|
|
ADD COLUMN total_reported_quantity DECIMAL(10,3) DEFAULT 0.000 COMMENT '累计报工数量',
|
|||
|
|
ADD COLUMN equipment_id BIGINT COMMENT '关联设备ID',
|
|||
|
|
ADD COLUMN equipment_name VARCHAR(255) COMMENT '设备名称',
|
|||
|
|
ADD COLUMN actual_start_time DATETIME COMMENT '实际开始时间',
|
|||
|
|
ADD COLUMN actual_end_time DATETIME COMMENT '实际结束时间',
|
|||
|
|
ADD COLUMN downtime_minutes INT DEFAULT 0 COMMENT '累计停机时间(分钟)';
|
|||
|
|
|
|||
|
|
-- 创建索引
|
|||
|
|
CREATE INDEX idx_manufacture_type ON pro_workorder(manufacture_type);
|
|||
|
|
CREATE INDEX idx_equipment_id ON pro_workorder(equipment_id);
|
|||
|
|
CREATE INDEX idx_report_mode ON pro_workorder(report_mode);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**说明**:
|
|||
|
|
- `last_report_time` 字段已存在,无需新增
|
|||
|
|
- 数量字段使用 `DECIMAL(10,3)` 与现有字段保持一致
|
|||
|
|
|
|||
|
|
### 步骤3:报工单表新增字段
|
|||
|
|
> 基于现有 `pro_report` 表结构
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 支持连续制造业的报工记录
|
|||
|
|
ALTER TABLE pro_report
|
|||
|
|
ADD COLUMN work_order_id BIGINT COMMENT '工单ID(连续制造业直接关联工单)',
|
|||
|
|
ADD COLUMN report_period_start DATETIME COMMENT '报工时段开始',
|
|||
|
|
ADD COLUMN report_period_end DATETIME COMMENT '报工时段结束',
|
|||
|
|
ADD COLUMN report_sequence INT COMMENT '报工序号',
|
|||
|
|
ADD COLUMN shift_name VARCHAR(64) COMMENT '班次名称',
|
|||
|
|
ADD COLUMN equipment_id BIGINT COMMENT '设备ID',
|
|||
|
|
ADD COLUMN equipment_name VARCHAR(255) COMMENT '设备名称',
|
|||
|
|
ADD COLUMN downtime_minutes INT DEFAULT 0 COMMENT '该时段停机时间(分钟)',
|
|||
|
|
ADD COLUMN downtime_reason VARCHAR(500) COMMENT '停机原因';
|
|||
|
|
|
|||
|
|
-- 说明:报工人使用现有的 report_user_id 和 report_user_name 字段
|
|||
|
|
|
|||
|
|
-- 创建索引
|
|||
|
|
CREATE INDEX idx_work_order_id ON pro_report(work_order_id);
|
|||
|
|
CREATE INDEX idx_report_period ON pro_report(report_period_start, report_period_end);
|
|||
|
|
CREATE INDEX idx_shift_name ON pro_report(shift_name);
|
|||
|
|
CREATE INDEX idx_equipment_id ON pro_report(equipment_id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**说明**:
|
|||
|
|
- `remark` 字段已存在,无需新增
|
|||
|
|
- `qualified_quantity` 和 `unqualified_quantity` 字段已存在
|
|||
|
|
- `quality_status` 字段已存在
|
|||
|
|
|
|||
|
|
### 步骤4:销售订单明细表新增字段(可选)
|
|||
|
|
> 用于标识订单明细的生产状态
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 扩展销售订单明细的状态管理
|
|||
|
|
-- status字段已存在,可以使用以下状态值:
|
|||
|
|
-- A: 待生产
|
|||
|
|
-- B: 生产中
|
|||
|
|
-- C: 部分完成
|
|||
|
|
-- D: 已完成
|
|||
|
|
-- 无需新增字段,使用现有的status和extend_field即可
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 步骤5:数据迁移
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 为现有数据设置默认值(确保兼容性)
|
|||
|
|
UPDATE md_material SET manufacture_type = 'DISCRETE' WHERE manufacture_type IS NULL;
|
|||
|
|
UPDATE pro_workorder SET manufacture_type = 'DISCRETE' WHERE manufacture_type IS NULL;
|
|||
|
|
UPDATE pro_workorder SET report_mode = 'PROCESS' WHERE report_mode IS NULL;
|
|||
|
|
UPDATE pro_workorder SET total_report_count = 0 WHERE total_report_count IS NULL;
|
|||
|
|
UPDATE pro_workorder SET total_reported_quantity = 0.000 WHERE total_reported_quantity IS NULL;
|
|||
|
|
UPDATE pro_workorder SET downtime_minutes = 0 WHERE downtime_minutes IS NULL;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 代码改动清单(重点:XML改动)
|
|||
|
|
|
|||
|
|
### 4.1 实体类改动
|
|||
|
|
|
|||
|
|
#### Material.java
|
|||
|
|
**文件路径**:`com.yavii.domain.Material`
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 新增字段
|
|||
|
|
private String manufactureType; // 制造类型: DISCRETE/CONTINUOUS
|
|||
|
|
private String reportMode; // 报工模式: PROCESS/TIME
|
|||
|
|
private Integer reportInterval; // 报工间隔(分钟)
|
|||
|
|
|
|||
|
|
// getter/setter 略
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### ProWorkorder.java
|
|||
|
|
**文件路径**:`com.yavii.domain.ProWorkorder`
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 新增字段
|
|||
|
|
private String manufactureType; // 制造类型
|
|||
|
|
private String reportMode; // 报工模式
|
|||
|
|
private Integer totalReportCount; // 总报工次数
|
|||
|
|
private BigDecimal totalReportedQuantity; // 累计报工数量
|
|||
|
|
private Long equipmentId; // 设备ID
|
|||
|
|
private String equipmentName; // 设备名称
|
|||
|
|
private Date actualStartTime; // 实际开始时间
|
|||
|
|
private Date actualEndTime; // 实际结束时间
|
|||
|
|
private Integer downtimeMinutes; // 累计停机时间
|
|||
|
|
|
|||
|
|
// getter/setter 略
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### ProReport.java
|
|||
|
|
**文件路径**:`com.yavii.domain.ProReport`
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
// 新增字段
|
|||
|
|
private Long workOrderId; // 工单ID(连续制造业直接关联)
|
|||
|
|
private Date reportPeriodStart; // 报工时段开始
|
|||
|
|
private Date reportPeriodEnd; // 报工时段结束
|
|||
|
|
private Integer reportSequence; // 报工序号
|
|||
|
|
private String shiftName; // 班次名称
|
|||
|
|
private Long equipmentId; // 设备ID
|
|||
|
|
private String equipmentName; // 设备名称
|
|||
|
|
private Integer downtimeMinutes; // 停机时间(分钟)
|
|||
|
|
private String downtimeReason; // 停机原因
|
|||
|
|
|
|||
|
|
// 说明:报工人使用现有的 reportUserId 和 reportUserName 字段
|
|||
|
|
|
|||
|
|
// getter/setter 略
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.2 Mapper XML 改动(核心重点)
|
|||
|
|
|
|||
|
|
#### ✅ MaterialMapper.xml
|
|||
|
|
**文件路径**:`resources/mapper/MaterialMapper.xml`
|
|||
|
|
|
|||
|
|
**改动1:resultMap 增加字段映射**
|
|||
|
|
```xml
|
|||
|
|
<resultMap id="MaterialResult" type="Material">
|
|||
|
|
<id property="id" column="id"/>
|
|||
|
|
<result property="number" column="number"/>
|
|||
|
|
<result property="name" column="name"/>
|
|||
|
|
<result property="specification" column="specification"/>
|
|||
|
|
<result property="unitId" column="unit_id"/>
|
|||
|
|
<result property="classId" column="class_id"/>
|
|||
|
|
<result property="typeId" column="type_id"/>
|
|||
|
|
<result property="status" column="status"/>
|
|||
|
|
<result property="routeId" column="route_id"/>
|
|||
|
|
<!-- ========== 新增字段映射 ========== -->
|
|||
|
|
<result property="manufactureType" column="manufacture_type"/>
|
|||
|
|
<result property="reportMode" column="report_mode"/>
|
|||
|
|
<!-- ================================= -->
|
|||
|
|
<result property="remark" column="remark"/>
|
|||
|
|
<result property="createBy" column="create_by"/>
|
|||
|
|
<result property="createTime" column="create_time"/>
|
|||
|
|
<result property="updateBy" column="update_by"/>
|
|||
|
|
<result property="updateTime" column="update_time"/>
|
|||
|
|
</resultMap>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动2:查询SQL 增加字段**
|
|||
|
|
```xml
|
|||
|
|
<sql id="selectMaterialVo">
|
|||
|
|
select id, number, name, specification, unit_id, class_id, type_id,
|
|||
|
|
status, route_id,
|
|||
|
|
manufacture_type, report_mode, <!-- 新增 -->
|
|||
|
|
remark, create_by, create_time, update_by, update_time
|
|||
|
|
from md_material
|
|||
|
|
</sql>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动3:插入SQL 增加字段**
|
|||
|
|
```xml
|
|||
|
|
<insert id="insertMaterial" parameterType="Material">
|
|||
|
|
insert into md_material
|
|||
|
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
|||
|
|
<if test="number != null">number,</if>
|
|||
|
|
<if test="name != null">name,</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="manufactureType != null">manufacture_type,</if>
|
|||
|
|
<if test="reportMode != null">report_mode,</if>
|
|||
|
|
</trim>
|
|||
|
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
|||
|
|
<if test="number != null">#{number},</if>
|
|||
|
|
<if test="name != null">#{name},</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="manufactureType != null">#{manufactureType},</if>
|
|||
|
|
<if test="reportMode != null">#{reportMode},</if>
|
|||
|
|
</trim>
|
|||
|
|
</insert>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动4:更新SQL 增加字段**
|
|||
|
|
```xml
|
|||
|
|
<update id="updateMaterial" parameterType="Material">
|
|||
|
|
update md_material
|
|||
|
|
<trim prefix="SET" suffixOverrides=",">
|
|||
|
|
<if test="name != null">name = #{name},</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="manufactureType != null">manufacture_type = #{manufactureType},</if>
|
|||
|
|
<if test="reportMode != null">report_mode = #{reportMode},</if>
|
|||
|
|
</trim>
|
|||
|
|
where id = #{id}
|
|||
|
|
</update>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### ✅ ProWorkorderMapper.xml
|
|||
|
|
**文件路径**:`resources/mapper/ProWorkorderMapper.xml`
|
|||
|
|
|
|||
|
|
**改动1:resultMap 增加字段映射**
|
|||
|
|
```xml
|
|||
|
|
<resultMap id="ProWorkorderResult" type="ProWorkorder">
|
|||
|
|
<id property="id" column="id"/>
|
|||
|
|
<result property="number" column="number"/>
|
|||
|
|
<result property="batchNumber" column="batch_number"/>
|
|||
|
|
<result property="materialId" column="material_id"/>
|
|||
|
|
<result property="materialName" column="material_name"/>
|
|||
|
|
<result property="quantity" column="quantity"/>
|
|||
|
|
<result property="proStatus" column="pro_status"/>
|
|||
|
|
<result property="lastReportTime" column="last_report_time"/>
|
|||
|
|
<!-- ========== 新增字段映射 ========== -->
|
|||
|
|
<result property="manufactureType" column="manufacture_type"/>
|
|||
|
|
<result property="reportMode" column="report_mode"/>
|
|||
|
|
<result property="totalReportCount" column="total_report_count"/>
|
|||
|
|
<result property="totalReportedQuantity" column="total_reported_quantity"/>
|
|||
|
|
<result property="equipmentId" column="equipment_id"/>
|
|||
|
|
<result property="equipmentName" column="equipment_name"/>
|
|||
|
|
<result property="actualStartTime" column="actual_start_time"/>
|
|||
|
|
<result property="actualEndTime" column="actual_end_time"/>
|
|||
|
|
<result property="downtimeMinutes" column="downtime_minutes"/>
|
|||
|
|
<!-- ================================= -->
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
</resultMap>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动2:查询SQL 增加字段(关键:关联物料表)**
|
|||
|
|
```xml
|
|||
|
|
<sql id="selectProWorkorderVo">
|
|||
|
|
select w.id, w.number, w.batch_number, w.material_id, w.material_name,
|
|||
|
|
w.specification, w.material_unit_id, w.material_unit_name,
|
|||
|
|
w.quantity, w.begin_pro_date, w.plan_finish_date, w.real_finish_date,
|
|||
|
|
w.pro_status, w.current_process, w.last_report_time,
|
|||
|
|
w.route_id, w.source_info,
|
|||
|
|
<!-- ========== 新增字段 ========== -->
|
|||
|
|
w.manufacture_type, w.report_mode, w.total_report_count,
|
|||
|
|
w.total_reported_quantity, w.equipment_id, w.equipment_name,
|
|||
|
|
w.actual_start_time, w.actual_end_time, w.downtime_minutes,
|
|||
|
|
<!-- 关联物料表,获取物料的制造类型配置 -->
|
|||
|
|
m.manufacture_type as material_manufacture_type,
|
|||
|
|
m.report_mode as material_report_mode,
|
|||
|
|
<!-- ================================= -->
|
|||
|
|
w.remark, w.create_by, w.create_time, w.update_by, w.update_time
|
|||
|
|
from pro_workorder w
|
|||
|
|
left join md_material m on w.material_id = m.id
|
|||
|
|
</sql>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动3:插入SQL 增加字段**
|
|||
|
|
```xml
|
|||
|
|
<insert id="insertProWorkorder" parameterType="ProWorkorder" useGeneratedKeys="true" keyProperty="id">
|
|||
|
|
insert into pro_workorder
|
|||
|
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
|||
|
|
<if test="number != null">number,</if>
|
|||
|
|
<if test="batchNumber != null">batch_number,</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="manufactureType != null">manufacture_type,</if>
|
|||
|
|
<if test="reportMode != null">report_mode,</if>
|
|||
|
|
<if test="totalReportCount != null">total_report_count,</if>
|
|||
|
|
<if test="totalReportedQuantity != null">total_reported_quantity,</if>
|
|||
|
|
<if test="equipmentId != null">equipment_id,</if>
|
|||
|
|
<if test="equipmentName != null">equipment_name,</if>
|
|||
|
|
<if test="actualStartTime != null">actual_start_time,</if>
|
|||
|
|
<if test="actualEndTime != null">actual_end_time,</if>
|
|||
|
|
<if test="downtimeMinutes != null">downtime_minutes,</if>
|
|||
|
|
</trim>
|
|||
|
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
|||
|
|
<if test="number != null">#{number},</if>
|
|||
|
|
<if test="batchNumber != null">#{batchNumber},</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="manufactureType != null">#{manufactureType},</if>
|
|||
|
|
<if test="reportMode != null">#{reportMode},</if>
|
|||
|
|
<if test="totalReportCount != null">#{totalReportCount},</if>
|
|||
|
|
<if test="totalReportedQuantity != null">#{totalReportedQuantity},</if>
|
|||
|
|
<if test="equipmentId != null">#{equipmentId},</if>
|
|||
|
|
<if test="equipmentName != null">#{equipmentName},</if>
|
|||
|
|
<if test="actualStartTime != null">#{actualStartTime},</if>
|
|||
|
|
<if test="actualEndTime != null">#{actualEndTime},</if>
|
|||
|
|
<if test="downtimeMinutes != null">#{downtimeMinutes},</if>
|
|||
|
|
</trim>
|
|||
|
|
</insert>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动4:更新SQL 增加字段**
|
|||
|
|
```xml
|
|||
|
|
<update id="updateProWorkorder" parameterType="ProWorkorder">
|
|||
|
|
update pro_workorder
|
|||
|
|
<trim prefix="SET" suffixOverrides=",">
|
|||
|
|
<if test="proStatus != null">pro_status = #{proStatus},</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="manufactureType != null">manufacture_type = #{manufactureType},</if>
|
|||
|
|
<if test="reportMode != null">report_mode = #{reportMode},</if>
|
|||
|
|
<if test="totalReportCount != null">total_report_count = #{totalReportCount},</if>
|
|||
|
|
<if test="totalReportedQuantity != null">total_reported_quantity = #{totalReportedQuantity},</if>
|
|||
|
|
<if test="equipmentId != null">equipment_id = #{equipmentId},</if>
|
|||
|
|
<if test="equipmentName != null">equipment_name = #{equipmentName},</if>
|
|||
|
|
<if test="actualStartTime != null">actual_start_time = #{actualStartTime},</if>
|
|||
|
|
<if test="actualEndTime != null">actual_end_time = #{actualEndTime},</if>
|
|||
|
|
<if test="downtimeMinutes != null">downtime_minutes = #{downtimeMinutes},</if>
|
|||
|
|
<if test="lastReportTime != null">last_report_time = #{lastReportTime},</if>
|
|||
|
|
</trim>
|
|||
|
|
where id = #{id}
|
|||
|
|
</update>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动5:新增查询方法(查询连续制造业工单)**
|
|||
|
|
```xml
|
|||
|
|
<!-- 查询连续制造业工单列表 -->
|
|||
|
|
<select id="selectContinuousWorkOrders" resultMap="ProWorkorderResult">
|
|||
|
|
<include refid="selectProWorkorderVo"/>
|
|||
|
|
where w.manufacture_type = 'CONTINUOUS'
|
|||
|
|
<if test="proStatus != null and proStatus != ''">
|
|||
|
|
and w.pro_status = #{proStatus}
|
|||
|
|
</if>
|
|||
|
|
order by w.create_time desc
|
|||
|
|
</select>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### ✅ ProReportMapper.xml
|
|||
|
|
**文件路径**:`resources/mapper/ProReportMapper.xml`
|
|||
|
|
|
|||
|
|
**改动1:resultMap 增加字段映射**
|
|||
|
|
```xml
|
|||
|
|
<resultMap id="ProReportResult" type="ProReport">
|
|||
|
|
<id property="id" column="id"/>
|
|||
|
|
<result property="number" column="number"/>
|
|||
|
|
<result property="workOrderEntryId" column="work_order_entry_id"/>
|
|||
|
|
<result property="reportQuantity" column="report_quantity"/>
|
|||
|
|
<result property="qualifiedQuantity" column="qualified_quantity"/>
|
|||
|
|
<result property="unqualifiedQuantity" column="unqualified_quantity"/>
|
|||
|
|
<result property="reportTime" column="report_time"/>
|
|||
|
|
<result property="qualityStatus" column="quality_status"/>
|
|||
|
|
<!-- ========== 新增字段映射 ========== -->
|
|||
|
|
<result property="workOrderId" column="work_order_id"/>
|
|||
|
|
<result property="reportPeriodStart" column="report_period_start"/>
|
|||
|
|
<result property="reportPeriodEnd" column="report_period_end"/>
|
|||
|
|
<result property="reportSequence" column="report_sequence"/>
|
|||
|
|
<result property="shiftName" column="shift_name"/>
|
|||
|
|
<result property="equipmentId" column="equipment_id"/>
|
|||
|
|
<result property="equipmentName" column="equipment_name"/>
|
|||
|
|
<result property="downtimeMinutes" column="downtime_minutes"/>
|
|||
|
|
<result property="downtimeReason" column="downtime_reason"/>
|
|||
|
|
<!-- ================================= -->
|
|||
|
|
<result property="remark" column="remark"/>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
</resultMap>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动2:查询SQL 增加字段(关键:关联工单表判断制造类型)**
|
|||
|
|
```xml
|
|||
|
|
<sql id="selectProReportVo">
|
|||
|
|
select r.id, r.number, r.work_order_entry_id, r.report_user_id, r.report_user_name,
|
|||
|
|
r.report_time, r.report_quantity, r.qualified_quantity, r.unqualified_quantity,
|
|||
|
|
r.quality_status, r.workshop_id, r.workshop_name, r.station_id, r.station_name,
|
|||
|
|
<!-- ========== 新增字段 ========== -->
|
|||
|
|
r.work_order_id, r.report_period_start, r.report_period_end,
|
|||
|
|
r.report_sequence, r.shift_name,
|
|||
|
|
r.equipment_id, r.equipment_name, r.downtime_minutes, r.downtime_reason,
|
|||
|
|
<!-- 关联工单表,获取工单信息 -->
|
|||
|
|
w.number as workorder_number,
|
|||
|
|
w.manufacture_type as workorder_manufacture_type,
|
|||
|
|
w.material_name as workorder_material_name,
|
|||
|
|
<!-- ================================= -->
|
|||
|
|
r.remark, r.create_by, r.create_time
|
|||
|
|
from pro_report r
|
|||
|
|
<!-- 左关联工单(连续制造业直接关联) -->
|
|||
|
|
left join pro_workorder w on r.work_order_id = w.id
|
|||
|
|
<!-- 左关联工单分录(离散制造业通过分录关联) -->
|
|||
|
|
left join pro_workorder_entry e on r.work_order_entry_id = e.id
|
|||
|
|
left join pro_workorder w2 on e.workorder_id = w2.id
|
|||
|
|
</sql>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动3:插入SQL 增加字段**
|
|||
|
|
```xml
|
|||
|
|
<insert id="insertProReport" parameterType="ProReport" useGeneratedKeys="true" keyProperty="id">
|
|||
|
|
insert into pro_report
|
|||
|
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
|||
|
|
<if test="number != null">number,</if>
|
|||
|
|
<if test="workOrderEntryId != null">work_order_entry_id,</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="workOrderId != null">work_order_id,</if>
|
|||
|
|
<if test="reportPeriodStart != null">report_period_start,</if>
|
|||
|
|
<if test="reportPeriodEnd != null">report_period_end,</if>
|
|||
|
|
<if test="reportSequence != null">report_sequence,</if>
|
|||
|
|
<if test="shiftName != null">shift_name,</if>
|
|||
|
|
<if test="equipmentId != null">equipment_id,</if>
|
|||
|
|
<if test="equipmentName != null">equipment_name,</if>
|
|||
|
|
<if test="downtimeMinutes != null">downtime_minutes,</if>
|
|||
|
|
<if test="downtimeReason != null">downtime_reason,</if>
|
|||
|
|
</trim>
|
|||
|
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
|||
|
|
<if test="number != null">#{number},</if>
|
|||
|
|
<if test="workOrderEntryId != null">#{workOrderEntryId},</if>
|
|||
|
|
<!-- 其他现有字段... -->
|
|||
|
|
<if test="workOrderId != null">#{workOrderId},</if>
|
|||
|
|
<if test="reportPeriodStart != null">#{reportPeriodStart},</if>
|
|||
|
|
<if test="reportPeriodEnd != null">#{reportPeriodEnd},</if>
|
|||
|
|
<if test="reportSequence != null">#{reportSequence},</if>
|
|||
|
|
<if test="shiftName != null">#{shiftName},</if>
|
|||
|
|
<if test="equipmentId != null">#{equipmentId},</if>
|
|||
|
|
<if test="equipmentName != null">#{equipmentName},</if>
|
|||
|
|
<if test="downtimeMinutes != null">#{downtimeMinutes},</if>
|
|||
|
|
<if test="downtimeReason != null">#{downtimeReason},</if>
|
|||
|
|
</trim>
|
|||
|
|
</insert>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**改动4:新增查询方法(按工单ID查询报工记录)**
|
|||
|
|
```xml
|
|||
|
|
<!-- 根据工单ID查询报工记录(连续制造业使用) -->
|
|||
|
|
<select id="selectReportsByWorkOrderId" resultMap="ProReportResult">
|
|||
|
|
<include refid="selectProReportVo"/>
|
|||
|
|
where r.work_order_id = #{workOrderId}
|
|||
|
|
order by r.report_period_start desc, r.report_sequence desc
|
|||
|
|
</select>
|
|||
|
|
|
|||
|
|
<!-- 检查时间段是否重叠 -->
|
|||
|
|
<select id="checkTimeOverlap" resultType="int">
|
|||
|
|
select count(1)
|
|||
|
|
from pro_report
|
|||
|
|
where work_order_id = #{workOrderId}
|
|||
|
|
and (
|
|||
|
|
(report_period_start <= #{periodStart} and report_period_end > #{periodStart})
|
|||
|
|
or (report_period_start < #{periodEnd} and report_period_end >= #{periodEnd})
|
|||
|
|
or (report_period_start >= #{periodStart} and report_period_end <= #{periodEnd})
|
|||
|
|
)
|
|||
|
|
</select>
|
|||
|
|
|
|||
|
|
<!-- 获取下一个报工序号 -->
|
|||
|
|
<select id="getNextSequence" resultType="int">
|
|||
|
|
select IFNULL(MAX(report_sequence), 0) + 1
|
|||
|
|
from pro_report
|
|||
|
|
where work_order_id = #{workOrderId}
|
|||
|
|
</select>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### ✅ SalOrderMapper.xml(可选改动)
|
|||
|
|
**文件路径**:`resources/mapper/SalOrderMapper.xml`
|
|||
|
|
|
|||
|
|
**改动:查询订单明细时关联物料的制造类型**
|
|||
|
|
```xml
|
|||
|
|
<sql id="selectSalOrderEntryVo">
|
|||
|
|
select e.id, e.main_id, e.material_id, e.material_name, e.material_specification,
|
|||
|
|
e.quantity, e.status, e.delivery_date,
|
|||
|
|
<!-- 关联物料表,获取制造类型 -->
|
|||
|
|
m.manufacture_type as material_manufacture_type,
|
|||
|
|
m.report_mode as material_report_mode,
|
|||
|
|
<!-- 其他字段... -->
|
|||
|
|
from sal_order_entry e
|
|||
|
|
left join md_material m on e.material_id = m.id
|
|||
|
|
</sql>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4.3 Mapper 接口改动
|
|||
|
|
|
|||
|
|
#### ProWorkorderMapper.java
|
|||
|
|
```java
|
|||
|
|
/**
|
|||
|
|
* 查询连续制造业工单列表
|
|||
|
|
*/
|
|||
|
|
List<ProWorkorder> selectContinuousWorkOrders(@Param("proStatus") String proStatus);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### ProReportMapper.java
|
|||
|
|
```java
|
|||
|
|
/**
|
|||
|
|
* 根据工单ID查询报工记录
|
|||
|
|
*/
|
|||
|
|
List<ProReport> selectReportsByWorkOrderId(@Param("workOrderId") Long workOrderId);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 检查时间段是否重叠
|
|||
|
|
*/
|
|||
|
|
int checkTimeOverlap(@Param("workOrderId") Long workOrderId,
|
|||
|
|
@Param("periodStart") Date periodStart,
|
|||
|
|
@Param("periodEnd") Date periodEnd);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 获取下一个报工序号
|
|||
|
|
*/
|
|||
|
|
int getNextSequence(@Param("workOrderId") Long workOrderId);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 业务流程改动
|
|||
|
|
|
|||
|
|
### 4.1 连续制造业流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
销售订单 → 生成一个工单(不按工序) → 按时间段报工(多次) → 累计达到计划数量 → 完成
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 工单生成逻辑
|
|||
|
|
|
|||
|
|
**离散制造业(保持不变)**:
|
|||
|
|
```java
|
|||
|
|
// 按工序路线生成多个工单
|
|||
|
|
for (RouteProcess process : routeProcessList) {
|
|||
|
|
WorkOrder workOrder = new WorkOrder();
|
|||
|
|
workOrder.setManufactureType("DISCRETE");
|
|||
|
|
workOrder.setBatchNumber(orderNumber + "-P" + processSort);
|
|||
|
|
// ...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**连续制造业(新增)**:
|
|||
|
|
```java
|
|||
|
|
// 只生成一个工单
|
|||
|
|
WorkOrder workOrder = new WorkOrder();
|
|||
|
|
workOrder.setManufactureType("CONTINUOUS");
|
|||
|
|
workOrder.setReportMode(material.getReportMode()); // 从物料继承
|
|||
|
|
workOrder.setBatchNumber(orderNumber); // 不使用-P序号
|
|||
|
|
workOrder.setEquipmentId(dto.getEquipmentId());
|
|||
|
|
// 不创建工单分录
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.3 报工逻辑
|
|||
|
|
|
|||
|
|
**离散制造业(保持不变)**:
|
|||
|
|
```java
|
|||
|
|
// 按工序报工,关联工单分录
|
|||
|
|
Report report = new Report();
|
|||
|
|
report.setWorkOrderEntryId(entryId);
|
|||
|
|
report.setReportQuantity(quantity);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**连续制造业(新增)**:
|
|||
|
|
```java
|
|||
|
|
// 按时间段报工,直接关联工单
|
|||
|
|
Report report = new Report();
|
|||
|
|
report.setWorkOrderId(workOrderId); // 直接关联工单
|
|||
|
|
report.setReportPeriodStart(periodStart);
|
|||
|
|
report.setReportPeriodEnd(periodEnd);
|
|||
|
|
report.setReportSequence(sequence);
|
|||
|
|
report.setShiftName(shiftName);
|
|||
|
|
report.setReportQuantity(quantity);
|
|||
|
|
|
|||
|
|
// 更新工单累计数量
|
|||
|
|
workOrder.setTotalReportedQuantity(
|
|||
|
|
workOrder.getTotalReportedQuantity().add(quantity)
|
|||
|
|
);
|
|||
|
|
workOrder.setTotalReportCount(workOrder.getTotalReportCount() + 1);
|
|||
|
|
|
|||
|
|
// 检查是否完成
|
|||
|
|
if (workOrder.getTotalReportedQuantity().compareTo(workOrder.getQuantity()) >= 0) {
|
|||
|
|
workOrder.setProStatus("D"); // 已完成
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 前端改动
|
|||
|
|
|
|||
|
|
### 5.1 物料管理页面
|
|||
|
|
|
|||
|
|
**新增字段**:
|
|||
|
|
- 制造类型:单选(离散制造业/连续制造业)
|
|||
|
|
- 报工模式:下拉(按工序/按时间/按产量)
|
|||
|
|
- 报工间隔:数字输入(分钟)
|
|||
|
|
|
|||
|
|
### 5.2 新增页面:连续制造业报工
|
|||
|
|
|
|||
|
|
**路由**:`/production/continuous-report`
|
|||
|
|
|
|||
|
|
**页面布局**:
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────┐
|
|||
|
|
│ 1. 工单选择区 │
|
|||
|
|
│ - 显示工单信息、设备、进度 │
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 2. 快速报工表单 │
|
|||
|
|
│ - 时间段、班次、操作员 │
|
|||
|
|
│ - 产量、合格数、不合格数 │
|
|||
|
|
│ - 停机时间、停机原因 │
|
|||
|
|
│ - 备注 │
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 3. 报工历史列表 │
|
|||
|
|
│ - 显示已报工记录 │
|
|||
|
|
├─────────────────────────────────────┤
|
|||
|
|
│ 4. 产量趋势图表 │
|
|||
|
|
│ - 按小时/班次显示产量趋势 │
|
|||
|
|
└─────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.3 工单管理页面
|
|||
|
|
|
|||
|
|
**新增列**:
|
|||
|
|
- 制造类型(标签显示)
|
|||
|
|
- 累计报工数量(连续制造业显示)
|
|||
|
|
- 报工次数(连续制造业显示)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 后端接口(新增)
|
|||
|
|
|
|||
|
|
### 6.1 获取连续制造业工单列表
|
|||
|
|
```
|
|||
|
|
GET /api/production/continuous/workorders
|
|||
|
|
参数: status, equipmentId, pageNum, pageSize
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 提交连续制造业报工
|
|||
|
|
```
|
|||
|
|
POST /api/production/continuous/report/submit
|
|||
|
|
参数: {
|
|||
|
|
workOrderId,
|
|||
|
|
reportPeriodStart,
|
|||
|
|
reportPeriodEnd,
|
|||
|
|
reportQuantity,
|
|||
|
|
qualifiedQuantity,
|
|||
|
|
unqualifiedQuantity,
|
|||
|
|
shiftName,
|
|||
|
|
downtimeMinutes,
|
|||
|
|
downtimeReason,
|
|||
|
|
remark
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.3 获取报工历史
|
|||
|
|
```
|
|||
|
|
GET /api/production/continuous/report/history
|
|||
|
|
参数: workOrderId, startTime, endTime
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.4 获取产量趋势
|
|||
|
|
```
|
|||
|
|
GET /api/production/continuous/report/trend
|
|||
|
|
参数: workOrderId, startTime, endTime, groupBy(HOUR/SHIFT/DAY)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 实施步骤
|
|||
|
|
|
|||
|
|
### 第一阶段:数据库改动(1天)
|
|||
|
|
1. 执行SQL脚本,新增字段
|
|||
|
|
2. 执行数据迁移脚本
|
|||
|
|
3. 验证现有功能不受影响
|
|||
|
|
|
|||
|
|
### 第二阶段:后端开发(5天)
|
|||
|
|
|
|||
|
|
#### 2.1 实体类和Mapper改动(1天)
|
|||
|
|
1. 修改 `Material.java`:新增 `manufactureType`, `reportMode`
|
|||
|
|
2. 修改 `ProWorkorder.java`:新增 9个字段
|
|||
|
|
3. 修改 `ProReport.java`:新增 9个字段
|
|||
|
|
4. 修改 `MaterialMapper.xml`:新增字段映射
|
|||
|
|
5. 修改 `ProWorkorderMapper.xml`:新增字段映射
|
|||
|
|
6. 修改 `ProReportMapper.xml`:新增字段映射
|
|||
|
|
|
|||
|
|
#### 2.2 Service层改动(2天)
|
|||
|
|
1. **AutoCompleteService**:
|
|||
|
|
- 修改 `autoCompleteSaleOrder` 方法,增加制造类型判断
|
|||
|
|
- 新增 `autoCompleteContinuous` 方法(连续制造业一键完成)
|
|||
|
|
- 新增 `autoCompleteDiscrete` 方法(重构现有逻辑)
|
|||
|
|
|
|||
|
|
2. **TimedCompleteService**:
|
|||
|
|
- 修改 `batchExecute` 方法,增加制造类型判断
|
|||
|
|
- 跳过或特殊处理连续制造业订单
|
|||
|
|
|
|||
|
|
3. **ReportService**:
|
|||
|
|
- 修改 `submitReport` 方法,增加制造类型判断
|
|||
|
|
- 新增 `submitContinuousReport` 方法(连续制造业报工)
|
|||
|
|
- 新增 `submitDiscreteReport` 方法(重构现有逻辑)
|
|||
|
|
|
|||
|
|
4. **WorkOrderService**:
|
|||
|
|
- 修改工单生成逻辑,支持连续制造业
|
|||
|
|
- 新增工单完成判断逻辑(累计数量 >= 计划数量)
|
|||
|
|
|
|||
|
|
#### 2.3 Controller和API(1天)
|
|||
|
|
1. 新增连续制造业报工接口
|
|||
|
|
2. 新增报工历史查询接口
|
|||
|
|
3. 新增产量趋势统计接口
|
|||
|
|
4. 修改现有接口,支持新字段
|
|||
|
|
|
|||
|
|
#### 2.4 单元测试(1天)
|
|||
|
|
1. 测试连续制造业工单生成
|
|||
|
|
2. 测试连续制造业报工
|
|||
|
|
3. 测试一键完成功能(离散+连续)
|
|||
|
|
4. 测试定时完成功能(离散+连续)
|
|||
|
|
|
|||
|
|
### 第三阶段:前端开发(5天)
|
|||
|
|
|
|||
|
|
#### 3.1 物料管理页面(1天)
|
|||
|
|
1. 新增制造类型字段(下拉框)
|
|||
|
|
2. 新增报工模式字段(下拉框)
|
|||
|
|
3. 实现字段联动逻辑
|
|||
|
|
4. 表单验证
|
|||
|
|
|
|||
|
|
#### 3.2 报工页面改造(2天)
|
|||
|
|
1. **创建连续制造业报工页面**:
|
|||
|
|
- 按时间报工界面(时段选择)
|
|||
|
|
- 按班次报工界面(班次选择)
|
|||
|
|
- 按产量报工界面(累计产量)
|
|||
|
|
- 按批次报工界面(批次号)
|
|||
|
|
|
|||
|
|
2. **改造现有报工页面**:
|
|||
|
|
- 增加制造类型判断
|
|||
|
|
- 根据报工模式动态显示控件
|
|||
|
|
- 报工序号自动生成
|
|||
|
|
|
|||
|
|
#### 3.3 工序执行情况页面改造(1天)
|
|||
|
|
1. **一键完成功能改造**:
|
|||
|
|
- 增加制造类型判断
|
|||
|
|
- 连续制造业:只生成工单,不自动报工
|
|||
|
|
- 离散制造业:保持现有逻辑
|
|||
|
|
|
|||
|
|
2. **定时完成功能改造**:
|
|||
|
|
- 增加制造类型判断
|
|||
|
|
- 连续制造业:跳过或仅生成工单
|
|||
|
|
|
|||
|
|
3. **进度条显示改造**:
|
|||
|
|
- 离散制造业:显示工序进度条
|
|||
|
|
- 连续制造业:显示报工次数和累计产量
|
|||
|
|
|
|||
|
|
#### 3.4 工单管理页面(0.5天)
|
|||
|
|
1. 列表新增列:制造类型、报工模式、报工次数、累计报工数量
|
|||
|
|
2. 详情页显示:设备信息、实际时间、停机时间
|
|||
|
|
3. 连续制造业:显示报工历史列表
|
|||
|
|
|
|||
|
|
#### 3.5 集成测试(0.5天)
|
|||
|
|
1. 端到端测试(物料 → 订单 → 工单 → 报工)
|
|||
|
|
2. 兼容性测试(离散制造业功能不受影响)
|
|||
|
|
|
|||
|
|
### 第四阶段:测试上线(2天)
|
|||
|
|
1. 功能测试(所有报工模式)
|
|||
|
|
2. 兼容性测试(离散制造业)
|
|||
|
|
3. 性能测试(批量报工)
|
|||
|
|
4. 用户培训
|
|||
|
|
5. 上线部署
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 注意事项
|
|||
|
|
|
|||
|
|
### 8.1 兼容性
|
|||
|
|
- ✅ 现有离散制造业流程完全不受影响
|
|||
|
|
- ✅ 新增字段都有默认值
|
|||
|
|
- ✅ 接口向后兼容
|
|||
|
|
|
|||
|
|
### 8.2 性能优化
|
|||
|
|
- 创建必要的索引(已在SQL中体现)
|
|||
|
|
- 报工历史查询限制时间范围(最近30天)
|
|||
|
|
- 使用分页查询
|
|||
|
|
|
|||
|
|
### 8.3 数据验证
|
|||
|
|
- 报工时间段不能重叠
|
|||
|
|
- 累计报工数量不能超过计划数量太多(允许10%误差)
|
|||
|
|
- 合格数量 + 不合格数量 = 报工数量
|
|||
|
|
|
|||
|
|
### 8.4 关键实现细节
|
|||
|
|
|
|||
|
|
#### 8.4.1 字段使用说明
|
|||
|
|
**pro_report 表字段使用规则**:
|
|||
|
|
- **离散制造业**:
|
|||
|
|
- 必填:`work_order_entry_id`(工单分录ID)
|
|||
|
|
- 不填:`work_order_id`, `report_period_start/end`, `report_sequence`, `shift_name`
|
|||
|
|
|
|||
|
|
- **连续制造业**:
|
|||
|
|
- 必填:`work_order_id`(工单ID)
|
|||
|
|
- 可选:`report_period_start/end`(TIME/SHIFT模式使用)
|
|||
|
|
- 可选:`shift_name`(SHIFT模式使用)
|
|||
|
|
- 可选:`report_sequence`(所有模式建议使用,便于排序)
|
|||
|
|
- 不填:`work_order_entry_id`(设为NULL或0)
|
|||
|
|
|
|||
|
|
#### 8.4.2 报工人字段说明
|
|||
|
|
- 使用现有字段 `report_user_id` 和 `report_user_name` 记录主报工人
|
|||
|
|
- 如需记录多人协作,可在 `remark` 字段中补充说明
|
|||
|
|
- **已删除字段**:`operator_ids`(与现有字段重复,已移除)
|
|||
|
|
|
|||
|
|
#### 8.4.3 工单完成判断逻辑
|
|||
|
|
```java
|
|||
|
|
// 连续制造业工单完成判断
|
|||
|
|
if (workOrder.getTotalReportedQuantity() >= workOrder.getQuantity()) {
|
|||
|
|
workOrder.setProStatus("FINISHED");
|
|||
|
|
workOrder.setRealFinishDate(new Date());
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.4.4 报工序号自动生成
|
|||
|
|
```java
|
|||
|
|
// 获取当前工单的最大报工序号
|
|||
|
|
Integer maxSequence = reportMapper.selectMaxSequence(workOrderId);
|
|||
|
|
report.setReportSequence(maxSequence == null ? 1 : maxSequence + 1);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.4.5 设备关联说明
|
|||
|
|
- `pro_workorder.equipment_id` 和 `pro_report.equipment_id` 都关联到 `dm_equipment.id`
|
|||
|
|
- 工单级别的设备ID表示主要使用的设备
|
|||
|
|
- 报工级别的设备ID允许不同(支持多设备轮换)
|
|||
|
|
|
|||
|
|
#### 8.4.6 销售订单表无需修改
|
|||
|
|
- `sal_order` 表**不需要**新增任何字段
|
|||
|
|
- 制造类型信息存储在 `md_material` 表中
|
|||
|
|
- 工单生成时从物料表读取 `manufacture_type` 和 `report_mode`
|
|||
|
|
- 保持销售订单与制造类型解耦
|
|||
|
|
|
|||
|
|
### 8.5 前端界面改动
|
|||
|
|
|
|||
|
|
#### 8.5.1 报工页面控件差异
|
|||
|
|
|
|||
|
|
**核心原则**:报工页面根据**工单的制造类型和报工模式**动态显示不同控件。
|
|||
|
|
|
|||
|
|
**实现逻辑**:
|
|||
|
|
```javascript
|
|||
|
|
// 1. 选择工单后,查询工单详情
|
|||
|
|
getWorkOrderDetail(workOrderId) {
|
|||
|
|
getWorkOrder(workOrderId).then(response => {
|
|||
|
|
this.workOrder = response.data;
|
|||
|
|
this.manufactureType = response.data.manufactureType; // DISCRETE 或 CONTINUOUS
|
|||
|
|
this.reportMode = response.data.reportMode; // PROCESS, TIME, SHIFT, QUANTITY, BATCH
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2. 根据制造类型和报工模式显示不同控件
|
|||
|
|
<template v-if="manufactureType === 'DISCRETE'">
|
|||
|
|
<!-- 离散制造业:显示工序选择 -->
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<template v-if="manufactureType === 'CONTINUOUS' && reportMode === 'TIME'">
|
|||
|
|
<!-- 连续制造业-按时间:显示时段选择 -->
|
|||
|
|
</template>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**离散制造业(PROCESS模式)**:
|
|||
|
|
- ✅ 显示工序选择下拉框
|
|||
|
|
- ✅ 显示工单分录列表
|
|||
|
|
- ✅ 报工时间:单个时间点
|
|||
|
|
- ✅ 报工数量:单次报工数量
|
|||
|
|
- ✅ 字段:`workOrderEntryId`(关联工单分录)
|
|||
|
|
- ❌ 不显示:时段选择、班次选择、报工序号
|
|||
|
|
|
|||
|
|
**连续制造业 - 按时间(TIME模式)**:
|
|||
|
|
- ❌ 不显示工序选择
|
|||
|
|
- ✅ 显示时段选择:开始时间 + 结束时间
|
|||
|
|
- ✅ 显示报工序号(后端自动生成:第1次、第2次...)
|
|||
|
|
- ✅ 显示设备选择
|
|||
|
|
- ✅ 显示停机时间和停机原因
|
|||
|
|
- ✅ 报工数量:该时段产量
|
|||
|
|
- ✅ 字段:`workOrderId`, `reportPeriodStart`, `reportPeriodEnd`, `equipmentId`, `downtimeMinutes`
|
|||
|
|
|
|||
|
|
**连续制造业 - 按班次(SHIFT模式)**:
|
|||
|
|
- ❌ 不显示工序选择
|
|||
|
|
- ✅ 显示班次选择下拉框(使用字典:`sys_shift_type`)
|
|||
|
|
- ✅ 显示时段选择:班次开始时间 + 结束时间
|
|||
|
|
- ✅ 显示报工序号(后端自动生成)
|
|||
|
|
- ✅ 显示设备选择
|
|||
|
|
- ✅ 报工数量:该班次产量
|
|||
|
|
- ✅ 字段:`workOrderId`, `shiftName`, `reportPeriodStart`, `reportPeriodEnd`, `equipmentId`
|
|||
|
|
|
|||
|
|
**连续制造业 - 按产量(QUANTITY模式)**:
|
|||
|
|
- ❌ 不显示工序选择
|
|||
|
|
- ❌ 不显示时段选择
|
|||
|
|
- ✅ 显示累计产量(只读,从工单获取)
|
|||
|
|
- ✅ 显示报工序号(后端自动生成)
|
|||
|
|
- ✅ 显示设备选择
|
|||
|
|
- ✅ 报工数量:本次报工产量
|
|||
|
|
- ✅ 系统自动计算:累计产量 = 前次累计 + 本次报工
|
|||
|
|
- ✅ 字段:`workOrderId`, `reportQuantity`, `equipmentId`
|
|||
|
|
|
|||
|
|
**连续制造业 - 按批次(BATCH模式)**:
|
|||
|
|
- ❌ 不显示工序选择
|
|||
|
|
- ✅ 显示批次说明输入框
|
|||
|
|
- ✅ 显示报工序号(后端自动生成)
|
|||
|
|
- ✅ 显示设备选择
|
|||
|
|
- ✅ 报工数量:该批次产量
|
|||
|
|
- ✅ 备注字段:记录批次详细信息
|
|||
|
|
- ✅ 字段:`workOrderId`, `reportQuantity`, `remark`, `equipmentId`
|
|||
|
|
|
|||
|
|
**字段映射关系**:
|
|||
|
|
|
|||
|
|
| 制造类型 | 报工模式 | 关键字段 | 后端判断依据 |
|
|||
|
|
|---------|---------|---------|------------|
|
|||
|
|
| DISCRETE | PROCESS | `workOrderEntryId` | `workOrderEntryId != null` |
|
|||
|
|
| CONTINUOUS | TIME | `workOrderId`, `reportPeriodStart/End` | `workOrderId != null` |
|
|||
|
|
| CONTINUOUS | SHIFT | `workOrderId`, `shiftName` | `workOrderId != null` |
|
|||
|
|
| CONTINUOUS | QUANTITY | `workOrderId` | `workOrderId != null` |
|
|||
|
|
| CONTINUOUS | BATCH | `workOrderId` | `workOrderId != null` |
|
|||
|
|
|
|||
|
|
**前端示例代码**:
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<el-form ref="reportForm" :model="reportForm">
|
|||
|
|
<!-- 公共字段 -->
|
|||
|
|
<el-form-item label="报工数量" prop="reportQuantity">
|
|||
|
|
<el-input-number v-model="reportForm.reportQuantity" :min="0" />
|
|||
|
|
</el-form-item>
|
|||
|
|
|
|||
|
|
<!-- 离散制造业:工序选择 -->
|
|||
|
|
<template v-if="manufactureType === 'DISCRETE'">
|
|||
|
|
<el-form-item label="工序" prop="workOrderEntryId">
|
|||
|
|
<el-select v-model="reportForm.workOrderEntryId">
|
|||
|
|
<el-option v-for="entry in workOrderEntryList"
|
|||
|
|
:key="entry.id"
|
|||
|
|
:label="entry.processName"
|
|||
|
|
:value="entry.id" />
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<!-- 连续制造业-按时间 -->
|
|||
|
|
<template v-if="manufactureType === 'CONTINUOUS' && reportMode === 'TIME'">
|
|||
|
|
<el-form-item label="报工时段">
|
|||
|
|
<el-date-picker v-model="reportForm.reportPeriod"
|
|||
|
|
type="datetimerange"
|
|||
|
|
value-format="yyyy-MM-dd HH:mm:ss" />
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="设备">
|
|||
|
|
<el-select v-model="reportForm.equipmentId">
|
|||
|
|
<el-option v-for="equip in equipmentList"
|
|||
|
|
:key="equip.id"
|
|||
|
|
:label="equip.name"
|
|||
|
|
:value="equip.id" />
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
<el-form-item label="停机时间(分钟)">
|
|||
|
|
<el-input-number v-model="reportForm.downtimeMinutes" :min="0" />
|
|||
|
|
</el-form-item>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<!-- 连续制造业-按班次 -->
|
|||
|
|
<template v-if="manufactureType === 'CONTINUOUS' && reportMode === 'SHIFT'">
|
|||
|
|
<el-form-item label="班次">
|
|||
|
|
<el-select v-model="reportForm.shiftName">
|
|||
|
|
<el-option v-for="dict in dict.type.sys_shift_type"
|
|||
|
|
:key="dict.value"
|
|||
|
|
:label="dict.label"
|
|||
|
|
:value="dict.label" />
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
</template>
|
|||
|
|
</el-form>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
dicts: ['sys_shift_type'], // 使用班次字典
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
manufactureType: null,
|
|||
|
|
reportMode: null,
|
|||
|
|
reportForm: {
|
|||
|
|
workOrderId: null, // 连续制造业使用
|
|||
|
|
workOrderEntryId: null, // 离散制造业使用
|
|||
|
|
reportQuantity: null,
|
|||
|
|
reportPeriodStart: null,
|
|||
|
|
reportPeriodEnd: null,
|
|||
|
|
shiftName: null,
|
|||
|
|
equipmentId: null,
|
|||
|
|
downtimeMinutes: 0
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.5.2 工序执行情况页面改动
|
|||
|
|
|
|||
|
|
**现有功能**:
|
|||
|
|
- 一键完成:为离散制造业订单自动生成工单和报工
|
|||
|
|
- 定时完成(批量完成):定时批量处理超期订单
|
|||
|
|
|
|||
|
|
**需要修改的逻辑**:
|
|||
|
|
|
|||
|
|
1. **一键完成功能**:
|
|||
|
|
```java
|
|||
|
|
// 现有逻辑:按工序路线生成多个工单
|
|||
|
|
if (DISCRETE) {
|
|||
|
|
for (每个工序) {
|
|||
|
|
创建工单:batch_number = "XS001-P01", "XS001-P02"
|
|||
|
|
创建工单分录
|
|||
|
|
创建报工单
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 新增逻辑:连续制造业生成单个工单
|
|||
|
|
if (CONTINUOUS) {
|
|||
|
|
创建工单:batch_number = "XS001"(不按工序)
|
|||
|
|
不创建工单分录
|
|||
|
|
不自动创建报工单(由用户按时间/班次/产量/批次报工)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **定时完成(批量完成)功能**:
|
|||
|
|
```java
|
|||
|
|
// 需要判断制造类型
|
|||
|
|
if (material.getManufactureType() == 'DISCRETE') {
|
|||
|
|
// 使用现有逻辑:自动完成所有工序
|
|||
|
|
autoCompleteAllProcesses();
|
|||
|
|
} else if (material.getManufactureType() == 'CONTINUOUS') {
|
|||
|
|
// 连续制造业:只生成工单,不自动报工
|
|||
|
|
// 或者:跳过连续制造业订单
|
|||
|
|
skipOrGenerateWorkOrderOnly();
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **工序进度条显示**:
|
|||
|
|
```javascript
|
|||
|
|
// 离散制造业:显示工序进度条
|
|||
|
|
if (order.manufactureType === 'DISCRETE') {
|
|||
|
|
显示工序步骤条(工序1 → 工序2 → 工序3)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 连续制造业:显示报工次数进度
|
|||
|
|
if (order.manufactureType === 'CONTINUOUS') {
|
|||
|
|
显示报工进度:已报工 X 次,累计 Y 吨 / 计划 Z 吨
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.5.3 物料管理页面改动
|
|||
|
|
|
|||
|
|
**新增字段**:
|
|||
|
|
- 制造类型:下拉框(离散/连续)
|
|||
|
|
- 报工模式:下拉框(按工序/按时间/按班次/按产量/按批次)
|
|||
|
|
- 当制造类型=离散时,报工模式固定为"按工序"
|
|||
|
|
- 当制造类型=连续时,报工模式可选其他4种
|
|||
|
|
|
|||
|
|
**字段联动**:
|
|||
|
|
```javascript
|
|||
|
|
onManufactureTypeChange(value) {
|
|||
|
|
if (value === 'DISCRETE') {
|
|||
|
|
this.form.reportMode = 'PROCESS'
|
|||
|
|
this.reportModeDisabled = true
|
|||
|
|
} else {
|
|||
|
|
this.reportModeDisabled = false
|
|||
|
|
this.form.reportMode = 'TIME' // 默认按时间
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.5.4 工单管理页面改动
|
|||
|
|
|
|||
|
|
**列表显示**:
|
|||
|
|
- 新增列:制造类型(离散/连续)
|
|||
|
|
- 新增列:报工模式
|
|||
|
|
- 新增列:报工次数(连续制造业显示)
|
|||
|
|
- 新增列:累计报工数量(连续制造业显示)
|
|||
|
|
|
|||
|
|
**详情页面**:
|
|||
|
|
- 显示设备信息
|
|||
|
|
- 显示实际开始/结束时间
|
|||
|
|
- 显示累计停机时间
|
|||
|
|
- 连续制造业:显示报工历史列表
|
|||
|
|
|
|||
|
|
### 8.6 统计报表功能改动
|
|||
|
|
|
|||
|
|
#### 8.6.1 WorkOrderExecutionService(工单执行情况统计)
|
|||
|
|
|
|||
|
|
**文件**:`WorkOrderExecutionServiceImpl.java`、`WorkOrderExecutionMapper.xml`
|
|||
|
|
|
|||
|
|
**需要修改的功能**:
|
|||
|
|
|
|||
|
|
1. **工单列表查询**:
|
|||
|
|
```xml
|
|||
|
|
<!-- 需要增加制造类型和报工模式字段 -->
|
|||
|
|
<select id="selectWorkOrderExecutionList">
|
|||
|
|
SELECT
|
|||
|
|
pw.id, pw.number, pw.material_name, pw.specification,
|
|||
|
|
pw.quantity, pw.batch_number, pw.pro_status,
|
|||
|
|
<!-- 新增字段 -->
|
|||
|
|
pw.manufacture_type, pw.report_mode,
|
|||
|
|
pw.total_report_count, pw.total_reported_quantity,
|
|||
|
|
<!-- 现有字段 -->
|
|||
|
|
pw.begin_pro_date, pw.plan_finish_date,
|
|||
|
|
pw.current_process_name, pw.completion_rate
|
|||
|
|
FROM pro_workorder pw
|
|||
|
|
WHERE pw.status = 'A'
|
|||
|
|
</select>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **工序列表查询(离散制造业)**:
|
|||
|
|
```xml
|
|||
|
|
<!-- 现有逻辑:查询工单分录 -->
|
|||
|
|
<select id="selectProcessListByWorkOrderId">
|
|||
|
|
SELECT pwe.id, pwe.process_name, pwe.process_sort,
|
|||
|
|
pwe.report_quantity, pwe.reported_quantity
|
|||
|
|
FROM pro_workorder_entry pwe
|
|||
|
|
WHERE pwe.workorder_id = #{workOrderId}
|
|||
|
|
AND pwe.type = 'report'
|
|||
|
|
ORDER BY pwe.process_sort ASC
|
|||
|
|
</select>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **报工历史查询(连续制造业)**:
|
|||
|
|
```xml
|
|||
|
|
<!-- 新增:直接查询工单的报工记录 -->
|
|||
|
|
<select id="selectReportListByWorkOrderId">
|
|||
|
|
SELECT pr.id, pr.number, pr.report_user_name,
|
|||
|
|
pr.report_time, pr.report_quantity,
|
|||
|
|
pr.report_sequence, pr.shift_name,
|
|||
|
|
pr.report_period_start, pr.report_period_end
|
|||
|
|
FROM pro_report pr
|
|||
|
|
WHERE pr.work_order_id = #{workOrderId}
|
|||
|
|
AND pr.status = 'A'
|
|||
|
|
ORDER BY pr.report_sequence ASC
|
|||
|
|
</select>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
4. **Service层适配**:
|
|||
|
|
```java
|
|||
|
|
@Override
|
|||
|
|
public List<ProcessExecutionVO> selectProcessListByWorkOrderId(Long workOrderId) {
|
|||
|
|
// 1. 查询工单信息,判断制造类型
|
|||
|
|
WorkOrder workOrder = workOrderMapper.selectById(workOrderId);
|
|||
|
|
|
|||
|
|
if ("DISCRETE".equals(workOrder.getManufactureType())) {
|
|||
|
|
// 离散制造业:查询工序列表
|
|||
|
|
return workOrderExecutionMapper.selectProcessListByWorkOrderId(workOrderId);
|
|||
|
|
} else if ("CONTINUOUS".equals(workOrder.getManufactureType())) {
|
|||
|
|
// 连续制造业:返回报工历史摘要
|
|||
|
|
return buildContinuousProcessSummary(workOrderId, workOrder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 新增方法:构建连续制造业的"工序"摘要(实际是报工摘要)
|
|||
|
|
private List<ProcessExecutionVO> buildContinuousProcessSummary(Long workOrderId, WorkOrder workOrder) {
|
|||
|
|
List<ProcessExecutionVO> summary = new ArrayList<>();
|
|||
|
|
|
|||
|
|
// 创建一个虚拟的"连续生产"工序
|
|||
|
|
ProcessExecutionVO continuousProcess = new ProcessExecutionVO();
|
|||
|
|
continuousProcess.setId(workOrderId);
|
|||
|
|
continuousProcess.setProcessName("连续生产");
|
|||
|
|
continuousProcess.setProcessSort(1);
|
|||
|
|
continuousProcess.setPlanQuantity(workOrder.getQuantity());
|
|||
|
|
continuousProcess.setReportedQuantity(workOrder.getTotalReportedQuantity());
|
|||
|
|
|
|||
|
|
// 计算完成率
|
|||
|
|
BigDecimal completionRate = BigDecimal.ZERO;
|
|||
|
|
if (workOrder.getQuantity().compareTo(BigDecimal.ZERO) > 0) {
|
|||
|
|
completionRate = workOrder.getTotalReportedQuantity()
|
|||
|
|
.divide(workOrder.getQuantity(), 2, RoundingMode.HALF_UP)
|
|||
|
|
.multiply(new BigDecimal("100"));
|
|||
|
|
}
|
|||
|
|
continuousProcess.setCompletionRate(completionRate);
|
|||
|
|
|
|||
|
|
// 设置状态
|
|||
|
|
if (completionRate.compareTo(new BigDecimal("100")) >= 0) {
|
|||
|
|
continuousProcess.setStatus("已完成");
|
|||
|
|
} else if (completionRate.compareTo(BigDecimal.ZERO) > 0) {
|
|||
|
|
continuousProcess.setStatus("进行中");
|
|||
|
|
} else {
|
|||
|
|
continuousProcess.setStatus("未开始");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 设置报工次数
|
|||
|
|
continuousProcess.setReportCount(workOrder.getTotalReportCount());
|
|||
|
|
|
|||
|
|
summary.add(continuousProcess);
|
|||
|
|
return summary;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.7 前端统计页面改动
|
|||
|
|
|
|||
|
|
#### 8.7.1 工单执行情况页面
|
|||
|
|
|
|||
|
|
**文件**:`mes-ui/src/views/mes/statement/workOrderExecution/index.vue`
|
|||
|
|
|
|||
|
|
**需要修改的显示逻辑**:
|
|||
|
|
|
|||
|
|
1. **工单卡片显示**:
|
|||
|
|
```javascript
|
|||
|
|
// 在工单卡片中显示制造类型和报工模式
|
|||
|
|
<div class="header-right">
|
|||
|
|
<span class="manufacture-type">
|
|||
|
|
{{ workOrder.manufactureType === 'DISCRETE' ? '离散制造' : '连续制造' }}
|
|||
|
|
</span>
|
|||
|
|
<span class="report-mode">
|
|||
|
|
{{ getReportModeText(workOrder.reportMode) }}
|
|||
|
|
</span>
|
|||
|
|
<span class="batch-number">批次:{{ workOrder.batchNumber }}</span>
|
|||
|
|
<span class="quantity">数量:{{ workOrder.quantity }}</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
// 方法:获取报工模式文本
|
|||
|
|
getReportModeText(mode) {
|
|||
|
|
const modeMap = {
|
|||
|
|
'PROCESS': '按工序',
|
|||
|
|
'TIME': '按时间',
|
|||
|
|
'SHIFT': '按班次',
|
|||
|
|
'QUANTITY': '按产量',
|
|||
|
|
'BATCH': '按批次'
|
|||
|
|
};
|
|||
|
|
return modeMap[mode] || mode;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **进度条显示差异**:
|
|||
|
|
```javascript
|
|||
|
|
// 离散制造业:显示工序进度
|
|||
|
|
<div v-if="workOrder.manufactureType === 'DISCRETE'" class="process-progress">
|
|||
|
|
<span class="current-process">
|
|||
|
|
当前工序:{{ workOrder.currentProcess || '未开始' }}
|
|||
|
|
</span>
|
|||
|
|
<span class="process-count">
|
|||
|
|
{{ workOrder.completedProcessCount }}/{{ workOrder.totalProcessCount }} 个工序
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
// 连续制造业:显示报工次数和累计产量
|
|||
|
|
<div v-else class="continuous-progress">
|
|||
|
|
<span class="report-count">
|
|||
|
|
已报工:{{ workOrder.totalReportCount }} 次
|
|||
|
|
</span>
|
|||
|
|
<span class="reported-quantity">
|
|||
|
|
累计产量:{{ workOrder.totalReportedQuantity }}/{{ workOrder.quantity }}
|
|||
|
|
</span>
|
|||
|
|
</div>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **展开内容差异**:
|
|||
|
|
```javascript
|
|||
|
|
// 离散制造业:显示工序列表
|
|||
|
|
<el-table v-if="workOrder.manufactureType === 'DISCRETE'"
|
|||
|
|
:data="workOrder.processList">
|
|||
|
|
<el-table-column label="工序名称" prop="processName" />
|
|||
|
|
<el-table-column label="完成率" prop="completionRate" />
|
|||
|
|
<!-- ... 其他工序字段 -->
|
|||
|
|
</el-table>
|
|||
|
|
|
|||
|
|
// 连续制造业:显示报工历史
|
|||
|
|
<el-table v-else :data="workOrder.reportList">
|
|||
|
|
<el-table-column label="报工序号" prop="reportSequence" />
|
|||
|
|
<el-table-column label="报工时间" prop="reportTime" />
|
|||
|
|
<el-table-column label="报工数量" prop="reportQuantity" />
|
|||
|
|
<el-table-column label="班次" prop="shiftName" />
|
|||
|
|
<el-table-column label="时段" width="200">
|
|||
|
|
<template slot-scope="scope">
|
|||
|
|
{{ scope.row.reportPeriodStart }} ~ {{ scope.row.reportPeriodEnd }}
|
|||
|
|
</template>
|
|||
|
|
</el-table-column>
|
|||
|
|
</el-table>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 8.8 后端Service改动
|
|||
|
|
|
|||
|
|
#### 8.6.1 AutoCompleteService(一键完成)
|
|||
|
|
|
|||
|
|
**文件**:`AutoCompleteServiceImpl.java`
|
|||
|
|
|
|||
|
|
**需要修改的方法**:
|
|||
|
|
```java
|
|||
|
|
@Override
|
|||
|
|
@Transactional
|
|||
|
|
public AjaxResult autoCompleteSaleOrder(AutoCompleteDTO dto) {
|
|||
|
|
// 1. 查询物料信息
|
|||
|
|
Material material = materialMapper.selectById(salOrderEntry.getMaterialId());
|
|||
|
|
|
|||
|
|
// 2. 判断制造类型
|
|||
|
|
if ("DISCRETE".equals(material.getManufactureType())) {
|
|||
|
|
// 现有逻辑:按工序生成多个工单 + 自动报工
|
|||
|
|
return autoCompleteDiscrete(dto, material);
|
|||
|
|
} else if ("CONTINUOUS".equals(material.getManufactureType())) {
|
|||
|
|
// 新增逻辑:生成单个工单,不自动报工
|
|||
|
|
return autoCompleteContinuous(dto, material);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 新增方法:连续制造业一键完成
|
|||
|
|
private AjaxResult autoCompleteContinuous(AutoCompleteDTO dto, Material material) {
|
|||
|
|
// 1. 生成单个工单(不按工序)
|
|||
|
|
WorkOrder workOrder = new WorkOrder();
|
|||
|
|
workOrder.setBatchNumber(salOrder.getNumber()); // 批次号 = 订单号
|
|||
|
|
workOrder.setManufactureType("CONTINUOUS");
|
|||
|
|
workOrder.setReportMode(material.getReportMode());
|
|||
|
|
workOrder.setQuantity(salOrderEntry.getQuantity());
|
|||
|
|
// ... 其他字段
|
|||
|
|
workOrderMapper.insert(workOrder);
|
|||
|
|
|
|||
|
|
// 2. 不创建工单分录
|
|||
|
|
// 3. 不自动创建报工单
|
|||
|
|
// 4. 更新订单状态为"已生成工单"(不是"生产完成")
|
|||
|
|
|
|||
|
|
return AjaxResult.success("工单生成成功,请手动报工");
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.6.2 TimedCompleteService(定时完成)
|
|||
|
|
|
|||
|
|
**文件**:`TimedCompleteServiceImpl.java`
|
|||
|
|
|
|||
|
|
**需要修改的方法**:
|
|||
|
|
```java
|
|||
|
|
@Override
|
|||
|
|
public AjaxResult batchExecute(BatchExecuteDTO dto) {
|
|||
|
|
List<OverdueOrderVO> orders = getOverdueOrders(...);
|
|||
|
|
|
|||
|
|
for (OverdueOrderVO order : orders) {
|
|||
|
|
// 查询物料信息
|
|||
|
|
Material material = materialMapper.selectById(order.getMaterialId());
|
|||
|
|
|
|||
|
|
// 判断制造类型
|
|||
|
|
if ("DISCRETE".equals(material.getManufactureType())) {
|
|||
|
|
// 自动完成
|
|||
|
|
autoCompleteService.autoCompleteSaleOrder(...);
|
|||
|
|
} else if ("CONTINUOUS".equals(material.getManufactureType())) {
|
|||
|
|
// 跳过或仅生成工单
|
|||
|
|
log.info("跳过连续制造业订单: " + order.getOrderNumber());
|
|||
|
|
skipCount++;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.6.3 ReportService(报工服务)
|
|||
|
|
|
|||
|
|
**需要修改的方法**:
|
|||
|
|
```java
|
|||
|
|
@Override
|
|||
|
|
public AjaxResult submitReport(Report report) {
|
|||
|
|
// 1. 判断是离散还是连续制造业
|
|||
|
|
if (report.getWorkOrderEntryId() != null) {
|
|||
|
|
// 离散制造业:现有逻辑
|
|||
|
|
return submitDiscreteReport(report);
|
|||
|
|
} else if (report.getWorkOrderId() != null) {
|
|||
|
|
// 连续制造业:新逻辑
|
|||
|
|
return submitContinuousReport(report);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 新增方法:连续制造业报工
|
|||
|
|
private AjaxResult submitContinuousReport(Report report) {
|
|||
|
|
// 1. 查询工单
|
|||
|
|
WorkOrder workOrder = workOrderMapper.selectById(report.getWorkOrderId());
|
|||
|
|
|
|||
|
|
// 2. 自动生成报工序号
|
|||
|
|
Integer maxSequence = reportMapper.selectMaxSequence(report.getWorkOrderId());
|
|||
|
|
report.setReportSequence(maxSequence == null ? 1 : maxSequence + 1);
|
|||
|
|
|
|||
|
|
// 3. 插入报工单
|
|||
|
|
reportMapper.insert(report);
|
|||
|
|
|
|||
|
|
// 4. 更新工单累计数据
|
|||
|
|
workOrder.setTotalReportCount(workOrder.getTotalReportCount() + 1);
|
|||
|
|
workOrder.setTotalReportedQuantity(
|
|||
|
|
workOrder.getTotalReportedQuantity().add(report.getReportQuantity())
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 5. 判断是否完成
|
|||
|
|
if (workOrder.getTotalReportedQuantity().compareTo(workOrder.getQuantity()) >= 0) {
|
|||
|
|
workOrder.setProStatus("FINISHED");
|
|||
|
|
workOrder.setRealFinishDate(new Date());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
workOrderMapper.updateById(workOrder);
|
|||
|
|
|
|||
|
|
return AjaxResult.success("报工成功");
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 8.6.4 WorkOrderService(工单服务)
|
|||
|
|
|
|||
|
|
**需要修改的方法**:
|
|||
|
|
|
|||
|
|
1. **insertWorkOrder 方法**:
|
|||
|
|
```java
|
|||
|
|
@Override
|
|||
|
|
public int insertWorkOrder(WorkOrder workOrder) {
|
|||
|
|
// ... 现有逻辑 ...
|
|||
|
|
|
|||
|
|
// 新增:保存工单后,判断是否需要创建工单分录
|
|||
|
|
int rows = workOrderMapper.insert(workOrder);
|
|||
|
|
|
|||
|
|
// 判断制造类型
|
|||
|
|
if ("DISCRETE".equals(workOrder.getManufactureType())) {
|
|||
|
|
// 离散制造业:创建工单分录(按工序)
|
|||
|
|
insertWorkOrderEntry(workOrder);
|
|||
|
|
} else if ("CONTINUOUS".equals(workOrder.getManufactureType())) {
|
|||
|
|
// 连续制造业:不创建工单分录
|
|||
|
|
// 工单直接可用于报工
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return rows;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. **insertWorkOrderEntry 方法**:
|
|||
|
|
```java
|
|||
|
|
public void insertWorkOrderEntry(WorkOrder workOrder) {
|
|||
|
|
// 检查制造类型
|
|||
|
|
if ("CONTINUOUS".equals(workOrder.getManufactureType())) {
|
|||
|
|
// 连续制造业不创建工单分录
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ... 现有逻辑(为离散制造业创建工单分录)...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
3. **批量生成工单方法**:
|
|||
|
|
```java
|
|||
|
|
// 从销售订单批量生成工单时,需要判断物料的制造类型
|
|||
|
|
public List<WorkOrder> generateWorkOrdersFromSaleOrder(SalOrder salOrder) {
|
|||
|
|
List<WorkOrder> workOrders = new ArrayList<>();
|
|||
|
|
|
|||
|
|
for (SalOrderEntry entry : salOrder.getEntries()) {
|
|||
|
|
// 查询物料信息
|
|||
|
|
Material material = materialMapper.selectById(entry.getMaterialId());
|
|||
|
|
|
|||
|
|
if ("DISCRETE".equals(material.getManufactureType())) {
|
|||
|
|
// 离散制造业:按工序路线生成多个工单
|
|||
|
|
List<WorkOrder> processWorkOrders = generateDiscreteWorkOrders(entry, material);
|
|||
|
|
workOrders.addAll(processWorkOrders);
|
|||
|
|
} else if ("CONTINUOUS".equals(material.getManufactureType())) {
|
|||
|
|
// 连续制造业:生成单个工单
|
|||
|
|
WorkOrder workOrder = generateContinuousWorkOrder(entry, material);
|
|||
|
|
workOrders.add(workOrder);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return workOrders;
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 班次管理说明
|
|||
|
|
|
|||
|
|
### 9.1 班次名称配置
|
|||
|
|
|
|||
|
|
**问题**:连续制造业按班次报工时,需要选择班次名称(如:早班、中班、晚班)。
|
|||
|
|
|
|||
|
|
**解决方案**:使用系统现有的**数据字典功能**管理班次选项。
|
|||
|
|
|
|||
|
|
### 9.2 实现方式
|
|||
|
|
|
|||
|
|
#### 数据库配置
|
|||
|
|
|
|||
|
|
已在SQL脚本中添加班次字典配置:
|
|||
|
|
|
|||
|
|
```sql
|
|||
|
|
-- 添加班次类型字典
|
|||
|
|
INSERT INTO `sys_dict_type` (`dict_name`, `dict_type`, `status`, `create_by`, `create_time`, `remark`)
|
|||
|
|
VALUES ('班次类型', 'sys_shift_type', '0', 'admin', NOW(), '用于连续制造业按班次报工');
|
|||
|
|
|
|||
|
|
-- 添加默认班次选项
|
|||
|
|
INSERT INTO `sys_dict_data` (`dict_sort`, `dict_label`, `dict_value`, `dict_type`, `css_class`, `list_class`, `is_default`, `status`, `create_by`, `create_time`, `remark`) VALUES
|
|||
|
|
(1, '早班', 'MORNING', 'sys_shift_type', '', 'default', 'Y', '0', 'admin', NOW(), '08:00-16:00'),
|
|||
|
|
(2, '中班', 'AFTERNOON', 'sys_shift_type', '', 'default', 'N', '0', 'admin', NOW(), '16:00-00:00'),
|
|||
|
|
(3, '晚班', 'NIGHT', 'sys_shift_type', '', 'default', 'N', '0', 'admin', NOW(), '00:00-08:00');
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
#### 前端使用方式
|
|||
|
|
|
|||
|
|
报工页面使用字典组件:
|
|||
|
|
|
|||
|
|
```vue
|
|||
|
|
<template>
|
|||
|
|
<!-- 班次选择(仅SHIFT模式显示) -->
|
|||
|
|
<el-form-item v-if="reportMode === 'SHIFT'" label="班次" prop="shiftName">
|
|||
|
|
<el-select v-model="form.shiftName" placeholder="请选择班次">
|
|||
|
|
<el-option
|
|||
|
|
v-for="dict in dict.type.sys_shift_type"
|
|||
|
|
:key="dict.value"
|
|||
|
|
:label="dict.label"
|
|||
|
|
:value="dict.label"
|
|||
|
|
/>
|
|||
|
|
</el-select>
|
|||
|
|
</el-form-item>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
export default {
|
|||
|
|
// 声明使用的字典类型
|
|||
|
|
dicts: ['sys_shift_type'],
|
|||
|
|
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
form: {
|
|||
|
|
shiftName: ''
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 9.3 配置管理
|
|||
|
|
|
|||
|
|
企业可以在**系统管理 → 字典管理**中灵活配置:
|
|||
|
|
|
|||
|
|
1. **修改班次名称**:将"早班"改为"白班"、"A班"等
|
|||
|
|
2. **调整班次数量**:支持两班制、三班制、四班制
|
|||
|
|
3. **设置默认班次**:`is_default='Y'`
|
|||
|
|
4. **记录时间段**:在`remark`字段记录班次时间(仅供参考)
|
|||
|
|
|
|||
|
|
**示例配置**:
|
|||
|
|
- 两班制:白班(08:00-20:00)、夜班(20:00-08:00)
|
|||
|
|
- 三班制:早班、中班、晚班
|
|||
|
|
- 四班制:A班、B班、C班、D班
|
|||
|
|
|
|||
|
|
### 9.4 优点
|
|||
|
|
|
|||
|
|
1. ✅ **无需新建表**:利用现有字典功能
|
|||
|
|
2. ✅ **灵活配置**:可在系统管理中修改,无需改代码
|
|||
|
|
3. ✅ **实施简单**:只需执行SQL脚本
|
|||
|
|
4. ✅ **满足需求**:支持各种班次制度
|
|||
|
|
|
|||
|
|
## 10. 废弃内容说明
|
|||
|
|
|
|||
|
|
以下内容在简化方案中**不实施**:
|
|||
|
|
|
|||
|
|
❌ 工单分录表的复杂改动(连续制造业不使用工单分录)
|
|||
|
|
❌ 设备管理表(如果系统已有设备模块则复用,否则暂不实施)
|
|||
|
|
❌ 停机记录表(停机信息直接记录在报工单中)
|
|||
|
|
❌ 复杂的批次号规则(第一版只支持订单号作为批次号)
|
|||
|
|
❌ 质量状态字段(第一版只记录合格/不合格数量)
|
|||
|
|
|
|||
|
|
这些功能可在后续版本中根据实际需求逐步添加。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**文档版本**: v3.0(完整版)
|
|||
|
|
**创建日期**: 2025-11-11
|
|||
|
|
**最后更新**: 2025-11-11
|
|||
|
|
**状态**: 待实施
|
|||
|
|
**预计工期**: 13个工作日(数据库1天 + 后端5天 + 前端5天 + 测试2天)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 附录:影响范围总结
|
|||
|
|
|
|||
|
|
### 数据库改动
|
|||
|
|
- ✅ `md_material`:2个字段
|
|||
|
|
- ✅ `pro_workorder`:9个字段
|
|||
|
|
- ✅ `pro_report`:9个字段
|
|||
|
|
- ✅ 索引:8个
|
|||
|
|
- ✅ 数据字典:1个字典类型 + 3个字典数据(班次配置)
|
|||
|
|
|
|||
|
|
### 后端文件改动
|
|||
|
|
- ✅ 实体类:3个(Material, ProWorkorder, ProReport)
|
|||
|
|
- ✅ Mapper XML:4个(MaterialMapper, ProWorkorderMapper, ProReportMapper, WorkOrderExecutionMapper)
|
|||
|
|
- ✅ Service:5个(AutoCompleteService, TimedCompleteService, ReportService, WorkOrderService, WorkOrderExecutionService)
|
|||
|
|
- ✅ Controller:2个(ReportController, WorkOrderExecutionController)
|
|||
|
|
|
|||
|
|
### 前端页面改动
|
|||
|
|
- ✅ 物料管理页面:新增2个字段 + 联动逻辑
|
|||
|
|
- ✅ 报工页面:新建或改造,支持5种报工模式,使用字典组件获取班次选项
|
|||
|
|
- ✅ 工序执行情况页面:一键完成 + 定时完成 + 进度条显示
|
|||
|
|
- ✅ 工单管理页面:新增列 + 详情页改造
|
|||
|
|
- ✅ 工单执行情况统计页面:制造类型显示 + 进度条差异 + 展开内容差异
|
|||
|
|
|
|||
|
|
### 关键功能点
|
|||
|
|
1. ✅ 制造类型判断(离散/连续)
|
|||
|
|
2. ✅ 报工模式支持(5种)
|
|||
|
|
3. ✅ 报工控件差异化
|
|||
|
|
4. ✅ 一键完成功能改造
|
|||
|
|
5. ✅ 定时完成功能改造
|
|||
|
|
6. ✅ 工序进度条改造
|
|||
|
|
7. ✅ 报工序号自动生成
|
|||
|
|
8. ✅ 累计数量统计
|
|||
|
|
9. ✅ 工单完成判断
|
|||
|
|
10. ✅ 统计报表适配(工单执行情况)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 附录B:实施过程中的Bug修复记录
|
|||
|
|
|
|||
|
|
### Bug #1:工单查询未返回 `manufactureType` 字段
|
|||
|
|
|
|||
|
|
**日期**:2025-11-12
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
- 前端工单列表页面点击"报工"按钮时,`workOrder.manufactureType` 为 `undefined`
|
|||
|
|
- 导致连续制造业工单无法正确识别,仍然提示"该工单没有工序分录,无法报工!"
|
|||
|
|
|
|||
|
|
**根本原因**:
|
|||
|
|
`WorkOrderMapper.xml` 中的查询SQL和resultMap缺少 `manufacture_type` 等连续制造业相关字段的映射
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
1. 在 `WorkOrderMapper.xml` 的 `resultMap` 中添加字段映射:
|
|||
|
|
```xml
|
|||
|
|
<result property="manufactureType" column="manufacture_type"/>
|
|||
|
|
<result property="reportMode" column="report_mode"/>
|
|||
|
|
<result property="totalReportCount" column="total_report_count"/>
|
|||
|
|
<result property="totalReportedQuantity" column="total_reported_quantity"/>
|
|||
|
|
<result property="equipmentId" column="equipment_id"/>
|
|||
|
|
<result property="equipmentName" column="equipment_name"/>
|
|||
|
|
<result property="actualStartTime" column="actual_start_time"/>
|
|||
|
|
<result property="actualEndTime" column="actual_end_time"/>
|
|||
|
|
<result property="downtimeMinutes" column="downtime_minutes"/>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. 在 `selectWorkOrderVo` SQL中添加查询字段:
|
|||
|
|
```xml
|
|||
|
|
a.manufacture_type,
|
|||
|
|
a.report_mode,
|
|||
|
|
a.total_report_count,
|
|||
|
|
a.total_reported_quantity,
|
|||
|
|
a.equipment_id,
|
|||
|
|
a.equipment_name,
|
|||
|
|
a.actual_start_time,
|
|||
|
|
a.actual_end_time,
|
|||
|
|
a.downtime_minutes,
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**影响范围**:
|
|||
|
|
- ✅ 不影响现有功能
|
|||
|
|
- ✅ 只是补充缺失的字段映射
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Bug #2:报工记录查询返回所有工单的数据(804条)
|
|||
|
|
|
|||
|
|
**日期**:2025-11-12
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
- 连续制造业工单点击"报工"后,页面卡死
|
|||
|
|
- 控制台显示查询到804条报工记录(实际应该是0条或该工单的报工记录)
|
|||
|
|
- 原因是查询参数 `workOrderId` 没有传递到后端SQL
|
|||
|
|
|
|||
|
|
**根本原因**:
|
|||
|
|
1. **前端问题**:`form.vue` 中使用动态导入API失败,且使用路由参数ID而不是工单真实ID
|
|||
|
|
2. **后端问题**:`ReportMapper.xml` 中缺少 `workOrderId` 的查询条件
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
|
|||
|
|
**前端修复** (`mes-ui/src/views/mes/production/report/form.vue`):
|
|||
|
|
1. 添加API导入:
|
|||
|
|
```javascript
|
|||
|
|
import {getEntryRealSort, getWorkOrderByEntryId, getWorkOrder} from '@/api/mes/production/workOrder'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
2. 修复API调用和参数传递:
|
|||
|
|
```javascript
|
|||
|
|
// 正确调用API
|
|||
|
|
const apiCall = isContinuous ? getWorkOrder(id) : getWorkOrderByEntryId(id);
|
|||
|
|
|
|||
|
|
// 使用响应数据中的真实工单ID
|
|||
|
|
if (isContinuous) {
|
|||
|
|
this.form.workOrderId = response.data.id; // 使用真实ID
|
|||
|
|
this.form.workOrderEntryId = null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 查询报工记录时使用真实ID
|
|||
|
|
const queryParams = isContinuous ?
|
|||
|
|
{ pageSize:99999, workOrderId: response.data.id } :
|
|||
|
|
{ pageSize:99999, workOrderEntryId:id };
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**后端修复** (`ReportMapper.xml`):
|
|||
|
|
在 `selectReportList` 和 `selectReportListCount` 两个查询中都添加:
|
|||
|
|
```xml
|
|||
|
|
<if test="workOrderId != null and workOrderId != ''"> and prp.work_order_id =#{workOrderId}</if>
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**影响范围**:
|
|||
|
|
- ✅ 不影响离散制造业(仍使用 `workOrderEntryId` 查询)
|
|||
|
|
- ✅ 修复连续制造业报工查询性能问题
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Bug #3:报工保存失败 - `work_order_entry_id` 字段无默认值
|
|||
|
|
|
|||
|
|
**日期**:2025-11-12
|
|||
|
|
|
|||
|
|
**问题描述**:
|
|||
|
|
- 连续制造业报工点击"保存"按钮时报错
|
|||
|
|
- 错误信息:`Field 'work_order_entry_id' doesn't have a default value`
|
|||
|
|
- 原因是数据库表 `pro_report` 中的 `work_order_entry_id` 字段不允许为空
|
|||
|
|
|
|||
|
|
**根本原因**:
|
|||
|
|
数据库表设计时,`work_order_entry_id` 字段被设置为 `NOT NULL`,但连续制造业报工不使用工序分录,此字段应该为 `NULL`
|
|||
|
|
|
|||
|
|
**修复方案**:
|
|||
|
|
执行SQL修改表结构:
|
|||
|
|
```sql
|
|||
|
|
-- 修改 pro_report 表,让 work_order_entry_id 可以为空
|
|||
|
|
ALTER TABLE pro_report
|
|||
|
|
MODIFY COLUMN work_order_entry_id BIGINT(20) NULL COMMENT '工单子表ID(离散制造业使用)';
|
|||
|
|
|
|||
|
|
-- 为 work_order_entry_id 添加索引(如果不存在)
|
|||
|
|
CREATE INDEX IF NOT EXISTS idx_work_order_entry_id ON pro_report(work_order_entry_id);
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**影响分析**:
|
|||
|
|
- ✅ **离散制造业**:不受影响,仍然传递 `work_order_entry_id`,值不为空
|
|||
|
|
- ✅ **连续制造业**:可以将 `work_order_entry_id` 设置为 `NULL`
|
|||
|
|
- ✅ **现有报工记录**:不受影响,已有数据保持不变
|
|||
|
|
- ✅ **查询功能**:不受影响,`WHERE work_order_entry_id = ?` 仍然有效
|
|||
|
|
- ✅ **关联查询**:不受影响,`LEFT JOIN` 仍然正常工作
|
|||
|
|
|
|||
|
|
**验证SQL**:
|
|||
|
|
```sql
|
|||
|
|
-- 验证修改是否成功
|
|||
|
|
SHOW CREATE TABLE pro_report;
|
|||
|
|
|
|||
|
|
-- 验证现有数据不受影响
|
|||
|
|
SELECT
|
|||
|
|
COUNT(*) as total_reports,
|
|||
|
|
SUM(CASE WHEN work_order_id IS NOT NULL THEN 1 ELSE 0 END) as continuous_report_count,
|
|||
|
|
SUM(CASE WHEN work_order_entry_id IS NOT NULL THEN 1 ELSE 0 END) as discrete_report_count
|
|||
|
|
FROM pro_report;
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### Bug修复总结
|
|||
|
|
|
|||
|
|
| Bug编号 | 问题 | 影响 | 修复文件 | 状态 |
|
|||
|
|
|--------|------|------|---------|------|
|
|||
|
|
| #1 | 工单查询缺少字段映射 | 前端无法识别制造类型 | `WorkOrderMapper.xml` | ✅ 已修复 |
|
|||
|
|
| #2 | 报工记录查询无过滤条件 | 查询所有报工记录,页面卡死 | `form.vue`, `ReportMapper.xml` | ✅ 已修复 |
|
|||
|
|
| #3 | 字段不允许为空 | 连续制造业报工无法保存 | 数据库表结构 | ✅ 已修复 |
|
|||
|
|
|
|||
|
|
**重要提示**:
|
|||
|
|
- 所有修复都向后兼容,不影响现有离散制造业功能
|
|||
|
|
- 修复后需要重启后端服务和刷新前端页面
|
|||
|
|
- 建议在测试环境验证后再部署到生产环境
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 功能增强总结
|
|||
|
|
|
|||
|
|
| 功能编号 | 功能描述 | 实现方案 | 影响文件 | 状态 |
|
|||
|
|
|----------|----------|----------|----------|------|
|
|||
|
|
| Feature #1 | 工单列表数量显示优化 | 显示格式改为"已报工数量/总数量",类似销售订单 | `jinzhong.js` | ✅ 已完成 |
|
|||
|
|
| Feature #2 | 列表页面空值显示优化 | 统一将空值显示为"-" | `jinzhong.js`, `index.vue` | ✅ 已完成 |
|
|||
|
|
| Feature #3 | 连续制造业销售订单状态自动更新 | 连续制造业工单状态变更时自动同步销售订单状态:开始排产→生产中,报工完成→已完成 | `ReportServiceImpl.java`, `WorkOrderServiceImpl.java` | ✅ 已完成 |
|