Files
MES/yawei-mes/.tasks/2025-11-21_生产一键生成和批量生成优化.md
2026-04-02 10:39:03 +08:00

37 KiB
Raw Blame History

工序执行情况表 - 一键完成和批量生成优化

文档信息

  • 创建日期: 2025-11-21
  • 创建人: 周启威
  • 功能模块: 生产管理 - 工序执行情况表

需求概述

针对工序执行情况表的一键完成和批量生成功能进行三项优化:

问题1一键完成/批量完成对话框 - 时间支持修改并自动重算

现状:

  • 在一键完成/批量完成对话框中
  • 工序开始时间是只读的disabled不能修改
  • 报工时间(完成时间)可以修改,但修改后:
    • 后续工序的开始时间不会自动更新
    • 需要手动逐个修改每个工序的时间
  • 缺少时间提示信息(工序持续时间、转运时间等)

需求:

  1. 所有时间支持修改:工序开始时间也应该可以修改
  2. 新增提示信息:显示工序持续时间、转运时间等
  3. 自动重算:修改某个工序的时间后,自动重新计算后续所有工序的时间
  4. 保持连续性:前工序完成时间 = 后工序开始时间

影响范围:

  • 一键完成对话框(单个订单)
  • 批量完成对话框(多个订单)
  • 离散制造 + 连续制造

问题2批量完成 - 跨订单按工序批量设置执行人

现状:

  • 批量完成多个订单时
  • 只能对单个订单的所有工序批量设置执行人
  • 如果多个订单都有"工序A",需要在每个订单中分别设置
  • 效率低,重复操作多

需求:

  • 支持对所有订单的相同工序批量设置执行人
  • 例如:一次操作将所有订单的"工序A"都设为"张三"
  • 提高批量操作效率

影响范围:

  • 批量完成对话框(多个订单)
  • 仅针对离散制造

问题3报工表单保存后 - 后续工序时间不同步

现状:

  • 在报工表单中修改了某个工序的报工时间
  • 保存表单后,系统自动生成下一个工序的执行记录
  • 问题: 下一工序的开始时间仍使用旧时间(修改前的时间),而不是修改后的时间

场景示例:

1. 工序1原本的报工时间是 10:00
2. 打开报工表单,修改为 11:00
3. 保存表单
4. 系统自动生成工序2的执行记录
5. 问题工序2的开始时间是 10:00而不是 11:00

原因:

  • 后端生成下一工序时,使用的是内存中的旧时间
  • 而不是从数据库读取最新保存的时间

需求:

  • 后端生成下一工序时,从数据库读取最新的执行记录时间
  • 确保时间链条的连续性

影响范围:

  • 报工表单保存后的后续工序生成逻辑(后端)
  • 离散制造 + 连续制造

功能设计

1. 报工时间修改后自动重算问题1

UI设计

离散制造:

┌─────────────────────────────────────────────────────────┐
│  工序1下料                                             │
├─────────────────────────────────────────────────────────┤
│  工序开始时间:[2025-11-21 08:00]  📅  ← 可修改         │
│   此时间为该工序的实际开始时间,根据生产开始时间和     │
│     前工序的持续时间和此工序的转运时间自动计算           │
│   转运时间600秒10分钟                           │
│  ⚠️ 修改后,后续工序时间将自动重算                       │
│                                                          │
│  报工时间(完成时间):[2025-11-21 10:00]  📅  ← 可修改 │
│   此工序持续时间7200秒2小时                     │
│  ⚠️ 修改后,后续工序时间将自动重算                       │
│                                                          │
│  报工人:[张三▼]  报工车间:[车间A▼]                    │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  工序2焊接                                             │
├─────────────────────────────────────────────────────────┤
│  工序开始时间:[2025-11-21 10:10]  📅  ← 可修改         │
│   根据前工序完成时间 + 转运时间自动计算                │
│   转运时间300秒5分钟                            │
│  ⚠️ 修改后,后续工序时间将自动重算                       │
│                                                          │
│  报工时间(完成时间):[2025-11-21 13:10]  📅  ← 可修改 │
│   此工序持续时间10800秒3小时                    │
│  ⚠️ 修改后,后续工序时间将自动重算                       │
│                                                          │
│  报工人:[李四▼]  报工车间:[车间B▼]                    │
└─────────────────────────────────────────────────────────┘

连续制造:

┌─────────────────────────────────────────────────────────┐
│  报工单1                                                 │
├─────────────────────────────────────────────────────────┤
│  工序开始时间:[2025-11-21 08:00]  📅                   │
│   工序等待开始时间0秒连续制造工序同时开始        │
│                                                          │
│  工序完成时间:[2025-11-21 16:00]  📅  ← 可修改         │
│   此工序持续时间28800秒8小时                    │
│  ⚠️ 修改后,后续报工单时间将自动重算                     │
│                                                          │
│  报工人:[张三▼]  报工车间:[车间A▼]                    │
│  报工数量:[100]                                         │
└─────────────────────────────────────────────────────────┘

时间计算规则

离散制造:

工序N的开始时间 = 工序(N-1)的完成时间 + 工序N的转运时间
工序N的完成时间 = 工序N的开始时间 + 工序N的持续时间

示例:
- 工序1开始08:00
- 工序1持续2小时7200秒
- 工序1完成10:00
- 工序2转运10分钟600秒
- 工序2开始10:10  ← 自动计算
- 工序2持续3小时10800秒
- 工序2完成13:10  ← 自动计算

连续制造:

报工单N的开始时间 = 报工单(N-1)的完成时间
报工单N的完成时间 = 报工单N的开始时间 + 报工单N的持续时间

注意连续制造的所有工序同时进行工序等待开始时间通常为0

前端实现要点

1. 在时间选择器下方添加提示信息

离散制造:

<!-- 工序开始时间 -->
<el-form-item label="工序开始时间">
  <el-date-picker
    v-model="autoCompleteForm.processConfigs[index].processStartTime"
    type="datetime"
    placeholder="工序开始时间"
    @change="handleProcessStartTimeChange(index)"
  />
  <!-- 提示信息 -->
  <div style="color: #909399; font-size: 12px; margin-top: 5px; line-height: 1.5">
    <div>
      <i class="el-icon-info"></i>
      此时间为该工序的实际开始时间根据生产开始时间和前工序的持续时间和此工序的转运时间自动计算
    </div>
    <div v-if="selectedRouteProcessList[index].transportTime">
      <i class="el-icon-info"></i>
      转运时间{{ formatDuration(selectedRouteProcessList[index].transportTime) }}
    </div>
    <div v-if="processStartTimeChanged[index]" style="color: #E6A23C">
      <i class="el-icon-warning"></i>
      修改后后续工序时间将自动重算
    </div>
  </div>
</el-form-item>

<!-- 报工时间完成时间 -->
<el-form-item label="报工时间(完成时间)">
  <el-date-picker
    v-model="autoCompleteForm.processConfigs[index].reportTime"
    type="datetime"
    placeholder="选择报工时间(完成时间)"
    @change="handleReportTimeChange(index)"
  />
  <!-- 提示信息 -->
  <div style="color: #909399; font-size: 12px; margin-top: 5px; line-height: 1.5">
    <div>
      <i class="el-icon-info"></i>
      此工序持续时间{{ formatDuration(selectedRouteProcessList[index].duration) }}
    </div>
    <div v-if="reportTimeChanged[index]" style="color: #E6A23C">
      <i class="el-icon-warning"></i>
      修改后后续工序时间将自动重算
    </div>
  </div>
</el-form-item>

连续制造:

<el-form-item label="工序完成时间">
  <el-date-picker
    v-model="autoCompleteForm.continuousReports[index].reportPeriodEnd"
    type="datetime"
    placeholder="选择完成时间"
    @change="handleContinuousReportTimeChange(index)"
  />
  <!-- 提示信息 -->
  <div style="color: #909399; font-size: 12px; margin-top: 5px; line-height: 1.5">
    <div>
      <i class="el-icon-info"></i>
      工序等待开始时间0连续制造工序同时开始
    </div>
    <div v-if="continuousReportTimeChanged[index]" style="color: #E6A23C">
      <i class="el-icon-warning"></i>
      修改后后续报工单时间将自动重算
    </div>
  </div>
</el-form-item>

2. 添加时间格式化方法

methods: {
  // 格式化持续时间(秒 -> 小时分钟)
  formatDuration(seconds) {
    if (!seconds) return '未设置'
    const hours = Math.floor(seconds / 3600)
    const minutes = Math.floor((seconds % 3600) / 60)
    const secs = seconds % 60
    
    let result = `${seconds}秒`
    if (hours > 0) {
      result += ` (${hours}小时`
      if (minutes > 0) result += `${minutes}分钟`
      result += ')'
    } else if (minutes > 0) {
      result += ` (${minutes}分钟`
      if (secs > 0) result += `${secs}秒`
      result += ')'
    }
    return result
  }
}

3. 监听报工时间修改,自动重算后续工序

data() {
  return {
    processStartTimeChanged: {}, // 记录哪些工序的开始时间被修改过
    reportTimeChanged: {}, // 记录哪些工序的报工时间被修改过
    continuousReportTimeChanged: {} // 连续制造报工单时间修改标记
  }
},

methods: {
  // 离散制造:工序开始时间修改处理
  handleProcessStartTimeChange(index) {
    // 标记该工序开始时间已修改
    this.$set(this.processStartTimeChanged, index, true)
    
    const configs = this.autoCompleteForm.processConfigs
    const currentProcess = this.selectedRouteProcessList[index]
    
    // 根据新的开始时间和工序持续时间,重新计算完成时间
    const startTime = new Date(configs[index].processStartTime)
    const duration = currentProcess.duration || 3600
    const finishTime = new Date(startTime.getTime() + duration * 1000)
    configs[index].reportTime = this.parseTime(finishTime, '{y}-{m}-{d} {h}:{i}:{s}')
    
    // 重新计算后续所有工序的时间
    this.recalculateSubsequentProcessTimes(index)
  },
  
  // 离散制造:报工时间修改处理
  handleReportTimeChange(index) {
    // 标记该工序时间已修改
    this.$set(this.reportTimeChanged, index, true)
    
    // 重新计算后续所有工序的时间
    this.recalculateSubsequentProcessTimes(index)
  },
  
  // 重新计算后续工序时间
  recalculateSubsequentProcessTimes(startIndex) {
    const configs = this.autoCompleteForm.processConfigs
    
    for (let i = startIndex + 1; i < configs.length; i++) {
      const prevConfig = configs[i - 1]
      const currentProcess = this.selectedRouteProcessList[i]
      
      // 前工序完成时间
      const prevFinishTime = new Date(prevConfig.reportTime)
      
      // 当前工序转运时间(秒)
      const transportTime = currentProcess.transportTime || 0
      
      // 当前工序开始时间 = 前工序完成时间 + 转运时间
      const currentStartTime = new Date(prevFinishTime.getTime() + transportTime * 1000)
      configs[i].processStartTime = this.parseTime(currentStartTime, '{y}-{m}-{d} {h}:{i}:{s}')
      
      // 当前工序持续时间(秒)
      const duration = currentProcess.duration || 3600
      
      // 当前工序完成时间 = 开始时间 + 持续时间
      const currentFinishTime = new Date(currentStartTime.getTime() + duration * 1000)
      configs[i].reportTime = this.parseTime(currentFinishTime, '{y}-{m}-{d} {h}:{i}:{s}')
    }
    
    this.$message.success(`已自动重算后续 ${configs.length - startIndex - 1} 个工序的时间`)
  },
  
  // 连续制造:报工时间修改处理
  handleContinuousReportTimeChange(index) {
    this.$set(this.continuousReportTimeChanged, index, true)
    this.recalculateSubsequentContinuousReports(index)
  },
  
  // 重新计算后续报工单时间
  recalculateSubsequentContinuousReports(startIndex) {
    const reports = this.autoCompleteForm.continuousReports
    
    for (let i = startIndex + 1; i < reports.length; i++) {
      const prevReport = reports[i - 1]
      // 下一报工单开始时间 = 前一报工单结束时间
      reports[i].reportPeriodStart = prevReport.reportPeriodEnd
    }
    
    this.$message.success(`已自动重算后续 ${reports.length - startIndex - 1} 个报工单的时间`)
  }
}

4. 时间验证

  • 完成时间不能早于开始时间
  • 修改时给出警告提示

2. 定时批量完成 - 时间可选

UI设计

┌─────────────────────────────────────┐
│  批量完成工序                        │
├─────────────────────────────────────┤
│  已选择 3 个工序                     │
│                                      │
│  统一设置:                          │
│  开始时间:[2025-11-21 08:00]  📅   │
│  完成时间:[2025-11-21 17:00]  📅   │
│  执行人:  [张三]              ▼    │
│                                      │
│  ⚠️ 将按工序顺序依次完成,时间自动衔接 │
│                                      │
│  工序列表:                          │
│  ☑ 工序A  08:00-10:00  张三         │
│  ☑ 工序B  10:00-12:00  张三         │
│  ☑ 工序C  12:00-14:00  张三         │
│                                      │
│         [取消]        [确定]         │
└─────────────────────────────────────┘

时间分配策略

第1个工序开始时间 = 用户选择,完成时间 = 开始时间 + 标准工时
第N个工序开始时间 = 第(N-1)个完成时间,完成时间 = 开始时间 + 标准工时

3. 表单时间修改同步

问题场景

1. 打开工序A执行记录表单
2. 修改报工时间10:00 → 11:00
3. 保存表单
4. 系统生成工序B执行记录
5. 问题工序B开始时间仍是10:00而不是11:00

解决方案

后端实现: 生成下一工序时,从数据库读取最新的执行记录,使用最新完成时间

private void generateNextProcessReport(Long workOrderId, Long currentProcessId) {
    // 从数据库读取最新执行记录
    ProcessReport currentReport = processReportMapper.selectLatestByProcessId(currentProcessId);
    
    if (currentReport == null || currentReport.getFinishTime() == null) {
        return;
    }
    
    // 使用最新完成时间作为下一工序开始时间
    Date nextStartTime = currentReport.getFinishTime();
    Date nextFinishTime = calculateFinishTime(nextStartTime, nextProcess.getDuration());
    
    // 创建下一工序执行记录
    ProcessReport nextReport = new ProcessReport();
    nextReport.setStartTime(nextStartTime);
    nextReport.setFinishTime(nextFinishTime);
    processReportMapper.insert(nextReport);
}

4. 批量设置执行人

UI设计

┌─────────────────────────────────────────────┐
│  批量生成工序执行记录                        │
├─────────────────────────────────────────────┤
│  工单编号WO202511210001                    │
│                                              │
│  工序列表:                                  │
│  ┌──────────────────────────────────────┐  │
│  │ 工序名称    标准工时   执行人   数量  │  │
│  ├──────────────────────────────────────┤  │
│  │ 下料       2h        [张三▼]    5    │  │
│  │ 焊接       3h        [李四▼]    5    │  │
│  │ 打磨       1h        [王五▼]    5    │  │
│  └──────────────────────────────────────┘  │
│                                              │
│  快捷操作:                                  │
│  工序:[下料▼]  执行人:[张三▼] [应用]      │  ← 新增
│                                              │
│  [全部设为同一人]  [取消]  [生成]           │  ← 新增
└─────────────────────────────────────────────┘

功能说明

  1. 按工序设置:选择工序和执行人,点击应用,该工序的所有记录都设置为该执行人
  2. 全部设为同一人:所有工序的所有记录都设置为同一个执行人

实施计划

阶段0需求确认 🔍

  • 确认"工序执行情况表"的具体页面位置
  • 确认"一键完成"功能的当前实现
  • 确认"批量生成"功能的当前实现
  • 确认相关前后端文件路径

说明:

  • 需要用户提供具体的页面路径或功能入口
  • 或者提供相关的菜单名称、页面截图

阶段1一键完成优化

  • 前端:添加完成时间选择器
  • 前端:时间验证逻辑
  • 后端:接口支持完成时间参数
  • 后端:实现后续工序时间重算

阶段2表单时间同步

  • 后端:修改生成下一工序逻辑
  • 后端:从数据库读取最新执行记录
  • 测试:验证时间链条连续性

阶段3批量设置执行人

  • 前端快捷操作区UI
  • 前端:按工序设置功能
  • 前端:全部设为同一人功能
  • 测试:批量设置功能

阶段4测试验证

  • 功能测试
  • 边界测试
  • 用户验收测试

实施进度

2025-11-21 10:35 - 需求确认阶段

页面路径: mes/statement/saleOrderExecution

找到的文件:

  • mes-ui/src/views/mes/statement/saleOrderExecution/index.vue - 销售订单执行情况表

当前功能分析:

制造类型说明

  • 离散制造 (DISCRETE) 工序按顺序执行,有明确的工序路线
  • 连续制造 (CONTINUOUS) 所有工序同时进行,按时间段或班次报工

1. 一键完成功能(单个订单)

离散制造:

  • 有生产开始时间选择器 (productionStartTime)
  • 每个工序有独立的报工时间选择器 (reportTime)
  • 工序开始时间自动计算(前工序完成时间 + 转运时间)
  • 已有批量设置功能:
    • 统一设置报工人 - 所有工序设为同一人
    • 统一设置报工时间 - 按工序持续时间递增
    • 统一设置报工车间 - 所有工序设为同一车间

连续制造:

  • 有工序开始时间和完成时间选择器
  • 可添加多条报工单
  • 已有批量设置功能:
    • 统一设置报工人
    • 统一设置车间

问题1报工时间修改后后续工序时间不会自动重算

  • 当前:修改某个工序的报工时间后,后续工序的开始时间不会更新
  • 需要:修改时间后,自动重新计算后续所有工序的时间

2. 批量完成功能(多个订单)

按钮: "定时完成(批量完成)" 对话框: batchAutoCompleteDialog

当前实现:

  • 支持批量选择多个订单
  • 每个订单独立配置工序路线和时间
  • 已有订单级批量设置功能:
    • 统一设置报工人 - 该订单所有工序设为同一人
    • 统一设置报工时间 - 按工序持续时间递增
    • 统一设置报工车间 - 该订单所有工序设为同一车间

问题2缺少跨订单的批量设置

  • 当前:只能对单个订单的所有工序批量设置
  • 需要:支持对所有订单的相同工序批量设置执行人
    • 例如:所有订单的"工序A"都设为"张三"

3. 表单时间修改同步问题

问题场景:

  1. 在报工表单中修改了某个工序的报工时间
  2. 保存后,系统生成下一个工序的执行记录
  3. 问题: 下一工序的开始时间仍使用旧时间,而不是修改后的时间

原因: 后端生成下一工序时,使用的是内存中的时间,而不是数据库中最新保存的时间

需要: 后端从数据库读取最新的执行记录时间


2025-11-21 11:00 - 明确实施策略

重新理解需求后的实施策略:

问题1报工时间修改后自动重算

  • 位置: 一键完成对话框、批量完成对话框
  • 实现: 监听报工时间修改事件,自动重算后续工序时间
  • 代码位置: index.vue 中的 @change 事件处理

问题2跨订单按工序批量设置

  • 位置: 批量完成对话框(仅离散制造)
  • 实现: 添加全局批量设置区域,支持按工序名称批量设置
  • 代码位置: batchAutoCompleteDialog 对话框顶部

问题3表单时间修改同步

  • 位置: 后端报工表单保存逻辑
  • 实现: 从数据库读取最新执行记录时间
  • 代码位置: 后端 Service 层

实施顺序:

  1. 问题1最简单先实现
  2. 问题2前端功能其次实现
  3. 问题3需要后端修改最后实现

2025-11-21 11:15 - 完善功能设计文档

已完成:

  • 更新UI设计添加详细的时间提示信息
    • 离散制造:显示工序持续时间、转运时间
    • 连续制造:显示工序等待开始时间
  • 添加时间计算规则说明和示例
  • 编写前端实现代码(含提示信息、时间格式化、自动重算逻辑)

2025-11-21 11:20 - 重新明确需求

用户确认的三个问题:

问题1 表单中的所有时间支持修改 + 新增提示 + 修改后自动计算后续时间

  • 工序开始时间改为可修改原来是disabled
  • 报工时间(完成时间)可修改
  • 添加时间提示信息(持续时间、转运时间)
  • 修改任一时间后,自动重算后续所有工序

问题2 离散的批量生成,能够批量设置同一个工序的指定人

  • 跨订单按工序批量设置
  • 例如:所有订单的"工序A"都设为"张三"

问题3 报工表单保存后后续工序时间不同步场景B

  • 后端从数据库读取最新时间
  • 而不是使用内存中的旧时间

下一步:

  • 开始实施问题1在实际代码中添加时间修改监听和自动重算功能

2025-11-21 11:35 - 实施问题1时间支持修改并自动重算

已完成:

1. 前端UI修改

  • 去掉工序开始时间的 disabled 属性,改为可修改
  • 为工序开始时间添加 @change="handleProcessStartTimeChange(index)" 监听
  • 为报工时间添加 @change="handleReportTimeChange(index)" 监听
  • 添加详细的提示信息:
    • 工序开始时间:显示转运时间
    • 报工时间:显示工序持续时间
    • 修改后显示警告:后续工序时间将自动重算

2. 数据属性

  • 添加 processStartTimeChanged: {} - 记录工序开始时间修改标记
  • 添加 reportTimeChanged: {} - 记录报工时间修改标记
  • 添加 continuousReportTimeChanged: {} - 连续制造时间修改标记

3. 方法实现

  • formatDuration(seconds) - 格式化持续时间(秒 → 小时分钟)
  • handleProcessStartTimeChange(index) - 工序开始时间修改处理
  • handleReportTimeChange(index) - 报工时间修改处理
  • recalculateSubsequentProcessTimes(startIndex) - 重新计算后续工序时间

实现效果:

  • 修改任一工序的开始时间或报工时间
  • 自动重新计算后续所有工序的时间
  • 保持时间链条的连续性
  • 显示友好的提示信息

待测试:

  • 一键完成对话框中修改时间
  • 验证后续工序时间自动重算
  • 验证时间链条连续性

下一步:

  • 实施问题2批量完成 - 跨订单按工序批量设置执行人

2025-11-21 11:45 - 实施问题2跨订单按工序批量设置

已完成:

1. UI修改

  • 在批量完成对话框的全局操作区域添加新按钮
  • 区分"全部设置"和"按工序设置"两种操作
  • 添加"按工序批量设置执行人"按钮

2. 新增对话框

  • 创建"按工序批量设置执行人"对话框
  • 显示所有工序列表(仅离散制造)
  • 显示每个工序涉及的订单数
  • 为每个工序提供执行人选择器
  • 提供"应用"按钮立即生效

3. 数据属性

  • 添加 processBatchSetDialog - 按工序批量设置对话框状态
  • processList - 工序列表(包含工序名、订单数、执行人)

4. 方法实现

  • openProcessBatchSetDialog() - 打开对话框,收集所有工序信息
  • handleProcessUserChange() - 处理执行人选择变化
  • applyProcessBatchSet() - 应用按工序批量设置

实现效果:

  • 批量完成时,可以按工序名称批量设置执行人
  • 例如:将所有订单的"工序A"都设为"张三"
  • 显示每个工序涉及的订单数量
  • 点击"应用"后立即生效,并显示成功提示

功能示例:

工序列表:
- 下料    涉及 3 个订单  [选择执行人: 张三▼] [应用]
- 焊接    涉及 3 个订单  [选择执行人: 李四▼] [应用]
- 打磨    涉及 2 个订单  [选择执行人: 王五▼] [应用]

待测试:

  • 批量完成对话框中打开按工序设置
  • 验证工序列表正确显示
  • 验证应用后所有订单的该工序都被设置

下一步:

  • 实施问题3报工表单保存后 - 后续工序时间不同步(后端)

2025-11-21 11:50 - 实施问题3后端使用前端修改的时间

问题确认:

用户反馈:在一键完成/批量完成对话框中修改了报工时间后,提交时后端生成的报工单没有使用修改后的时间,而是用系统自动计算的时间。

问题原因:

AutoCompleteServiceImpl.batchGenerateReports() 方法中第1163-1173行后端在生成报工单时重新计算了报工时间

// 原代码:直接用工序开始时间 + 持续时间计算
Date reportTime = workOrder.getProcessStartTime();
if (reportTime != null && workOrder.getDuration() != null && workOrder.getDuration() > 0) {
    reportTime = new Date(reportTime.getTime() + workOrder.getDuration() * 1000);
}

这导致前端传来的用户修改的时间被覆盖了。

解决方案:

修改后端逻辑,优先使用前端传来的报工时间

// 🔧 优先使用前端传来的报工时间(用户可能已修改)
Date reportTime = null;
try {
    if (config.getReportTime() != null && !config.getReportTime().isEmpty()) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        reportTime = sdf.parse(config.getReportTime());
        System.out.println("✓ 使用前端传来的报工时间: " + config.getReportTime());
    }
} catch (ParseException e) {
    System.err.println("✗ 解析前端报工时间失败: " + e.getMessage());
}

// 如果前端没有传报工时间,则使用后端计算的时间
if (reportTime == null) {
    reportTime = workOrder.getProcessStartTime();
    if (reportTime != null && workOrder.getDuration() != null && workOrder.getDuration() > 0) {
        reportTime = new Date(reportTime.getTime() + workOrder.getDuration() * 1000);
    }
}

修改的文件:

  • yjh-mes/src/main/java/cn/sourceplan/production/service/impl/AutoCompleteServiceImpl.java
    • 修改 batchGenerateReports() 方法
    • 优先使用前端传来的 config.getReportTime()
    • 如果前端没传,则使用后端计算的时间(兼容旧逻辑)

实现效果:

  • 用户在前端修改报工时间后,后端会使用修改后的时间
  • 如果用户没有修改,后端仍会自动计算时间(向后兼容)
  • 添加日志输出,方便调试

总结

已完成的优化

问题1时间支持修改并自动重算

  • 工序开始时间和报工时间都可以修改
  • 修改后自动重算后续所有工序时间
  • 添加详细的提示信息
  • 保持时间链条连续性

问题2跨订单按工序批量设置

  • 批量完成时支持按工序名称批量设置执行人
  • 显示每个工序涉及的订单数
  • 一次操作设置所有订单的相同工序

问题3后端使用前端修改的时间

  • 修改后端逻辑,优先使用前端传来的报工时间
  • 用户修改时间后,后端不会再重新计算覆盖
  • 向后兼容:如果前端没传时间,后端仍会自动计算

实施完成总结

修改的文件:

  • mes-ui/src/views/mes/statement/saleOrderExecution/index.vue(前端)
    • 添加时间修改监听和自动重算逻辑
    • 添加按工序批量设置对话框
    • 添加详细的提示信息
  • yjh-mes/src/main/java/cn/sourceplan/production/service/impl/AutoCompleteServiceImpl.java(后端)
    • 修改 batchGenerateReports() 方法
    • 优先使用前端传来的报工时间
    • 添加日志输出

新增功能:

  1. 工序时间可修改并自动重算
  2. 按工序批量设置执行人
  3. 时间格式化显示(秒 → 小时分钟)

待测试:

  • 问题1测试 一键完成对话框中修改时间,验证前端自动重算
  • 问题2测试 批量完成对话框中使用按工序批量设置执行人
  • 问题3测试 修改时间后提交,验证后端生成的报工单使用了修改后的时间
  • 验证时间链条的连续性
  • 验证批量设置后所有订单的该工序都被正确设置

2025-11-21 12:00 - 补充修改:报工单时间显示时分秒

需求: 报工单表单中的报工时间改成带时分秒的,并且可以编辑修改。

修改内容:

  • 将报工时间选择器从 type="date" 改为 type="datetime"
  • 增加列宽从 240px 到 280px以容纳时分秒显示
  • 保持 value-format="yyyy-MM-dd HH:mm:ss" 格式不变

修改的文件:

  • mes-ui/src/views/mes/production/report/form.vue
  • mes-ui/src/views/mes/production/report/formA.vue

修改前:

<el-date-picker type="date" ... />
<!-- 只能选择日期2025-11-21 -->

修改后:

<el-date-picker type="datetime" ... />
<!-- 可以选择日期和时间2025-11-21 14:30:00 -->

实现效果:

  • 报工时间显示完整的日期时间(年月日 时分秒)
  • 可以在表单中直接编辑修改时分秒
  • 更精确的报工时间记录

2025-11-21 12:05 - 补充修改UI样式优化

需求1统一按钮样式 全局操作按钮样式要统一,"统一设置所有报工人"等按钮和"按工序批量设置执行人"按钮格式要一样。

修改内容:

  • 所有全局操作按钮统一添加 plain 属性
  • 移除"按工序批量设置执行人"按钮的 type="warning"
  • 保持统一的扁平化按钮风格

需求2订单边框颜色区分 订单外层边框要根据制造类型显示不同颜色,内部工序/报工单不需要边框。

修改内容:

  • 批量完成对话框:订单外层边框根据制造类型显示颜色
    • 离散制造:蓝色边框 #409EFF2px
    • 连续制造:绿色边框 #67C23A2px
  • 去掉内部工序和报工单的边框(简化视觉)

修改位置:

  1. 批量完成对话框
    • 订单外层边框第1196行、第1407行根据制造类型
    • 去掉工序表单边框第1263行
    • 去掉报工单表单边框第1347行
  2. 一键完成对话框
    • 去掉工序表单边框第409行
    • 去掉报工单表单边框第594行

实现效果:

  • 按钮样式统一,视觉更协调
  • 通过订单外层边框颜色快速区分制造类型
  • 蓝色 = 离散制造绿色 = 连续制造
  • 内部表单无边框,界面更简洁

2025-11-21 12:15 - 修复:批量完成对话框时间自动重算

问题: 用户在批量完成对话框中修改了报工时间,但后续工序的时间没有自动重算。

原因: 批量完成对话框中的时间字段没有添加 @change 监听事件,导致修改时间后不会触发自动重算。

修改内容:

  1. 去掉工序开始时间的 disabled 属性,允许编辑
  2. 为工序开始时间添加 @change="handleBatchProcessStartTimeChange(orderIndex, pIndex)"
  3. 为报工时间添加 @change="handleBatchReportTimeChange(orderIndex, pIndex)"
  4. 添加三个新方法:
    • handleBatchProcessStartTimeChange - 处理工序开始时间修改
    • handleBatchReportTimeChange - 处理报工时间修改
    • recalculateBatchSubsequentProcessTimes - 重新计算后续工序时间

修改位置:

  • 模板第1279行左侧订单、第1491行右侧订单
  • 方法第2585-2641行

实现效果:

  • 修改工序开始时间后,自动计算该工序的报工时间
  • 修改报工时间后,自动重算后续所有工序的时间
  • 保持时间链条连续性
  • 显示友好的提示信息

2025-11-21 14:25 - 修复和完善:

  1. 修复了 recalculateBatchSubsequentProcessTimes 方法的逻辑错误
    • 原来从 order.routeProcessList 获取工序信息(不存在)
    • 现在直接从 configs 中获取工序信息duration、transferTime等
  2. 添加了工序持续时间和转运时间的可视化提示
    • 蓝色标签显示持续时间(分钟)
    • 黄色标签显示转运时间(分钟)
    • 方便用户了解时间计算依据

2025-11-21 14:32 - 最终修复:

  1. 修复转运时间未保存的问题
    • handleBatchRouteChange 方法中,工序配置对象添加了 transferTime 字段
    • 确保时间重算时能正确获取并使用转运时间
  2. 优化报工时间标签显示
    • 一键完成对话框:标签改为两行显示 "报工时间" + "(此工序完成时间)"
    • 批量完成对话框:同样改为两行显示
    • 说明文字使用灰色小字体,更加清晰

相关文件

前端文件

  • mes-ui/src/views/mes/statement/saleOrderExecution/index.vue - 销售订单执行情况表(主文件)
    • 包含一键完成对话框
    • 包含批量完成对话框
    • 包含定时完成功能
  • mes-ui/src/views/mes/production/report/form.vue - 报工单表单
    • 修改报工时间为datetime类型
  • mes-ui/src/views/mes/production/report/formA.vue - 报工单表单A
    • 修改报工时间为datetime类型

后端文件

  • yjh-mes/src/main/java/cn/sourceplan/production/service/impl/AutoCompleteServiceImpl.java - 一键完成服务实现
    • 修改了 batchGenerateReports() 方法
    • 优先使用前端传来的报工时间
  • yjh-mes/src/main/java/cn/sourceplan/statement/service/impl/SaleOrderExecutionServiceImpl.java

测试用例

测试1完成时间可选

  1. 打开一键完成对话框
  2. 修改完成时间
  3. 验证:完成时间不能早于开始时间
  4. 提交后验证:后续工序时间已重算

测试2时间同步

  1. 完成工序A时间为10:00
  2. 修改工序A完成时间为11:00
  3. 生成工序B
  4. 验证工序B开始时间为11:00

测试3批量设置执行人

  1. 打开批量生成对话框
  2. 选择工序"下料",执行人"张三",点击应用
  3. 验证:所有下料工序的执行人都变为张三
  4. 点击"全部设为同一人",选择"李四"
  5. 验证:所有工序的执行人都变为李四

文档版本: v1.0
创建日期: 2025-11-21
最后更新: 2025-11-21