3 天以前 06f3df285a24234e60883cd5ae73c6153abf4155
feat(mes): 添加生产任务进度显示和工艺参数模板功能

- 在任务列表中新增完成进度列,使用进度条展示任务完成情况
- 添加工艺参数模板字段到工序数据结构中并支持模板ID显示
- 集成Ant Design Vue的Progress组件用于进度可视化
- 更新任务表单中的工序步骤显示,添加参数模板描述信息
- 优化工作订单流程,移除预览模态框相关代码
- 在任务列表中集成快速报工功能,支持实时产量反馈
- 调整排产甘特图展示逻辑,增加任务计划说明文字
- 修改排产按钮标签为排产维护以更准确反映功能用途
已修改5个文件
86 ■■■■■ 文件已修改
src/api/mes/pro/workorder/process/index.ts 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/task/data.ts 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/task/index.vue 44 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/task/modules/schedule-form.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/task/modules/task-list.vue 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/mes/pro/workorder/process/index.ts
@@ -19,6 +19,7 @@
    processId?: number; // 工序编号
    processCode?: string; // 工序编码
    processName?: string; // 工序名称
    paramTemplateId?: number; // 工艺参数模板编号
    sort?: number; // 序号
    nextProcessId?: number; // 下一道工序编号
    nextProcessName?: string; // 下一道工序名称
src/views/mes/pro/task/data.ts
@@ -166,6 +166,12 @@
      width: 100,
    },
    {
      field: 'progressPercent',
      title: '完成进度',
      width: 150,
      slots: { default: 'progressPercent' },
    },
    {
      field: 'clientCode',
      title: '客户编码',
      width: 120,
@@ -348,6 +354,12 @@
      width: 120,
    },
    {
      field: 'paramTemplateId',
      title: '工艺参数模板',
      minWidth: 140,
      formatter: ({ cellValue }) => cellValue ? `模板 #${cellValue}` : '未配置',
    },
    {
      field: 'quantity',
      title: '排产数量',
      width: 100,
src/views/mes/pro/task/index.vue
@@ -11,17 +11,16 @@
  MesProWorkOrderTypeEnum,
} from '@vben/constants';
import { Button, Card, message, Tabs } from 'ant-design-vue';
import { Button, Card, Progress, Tabs } from 'ant-design-vue';
import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
import { getGanttTaskList, previewAutoGenerate, autoGenerateTasks } from '#/api/mes/pro/task';
import { getGanttTaskList } from '#/api/mes/pro/task';
import { getWorkOrderPage } from '#/api/mes/pro/workorder';
import ArchiveDetail from '#/views/mes/pd/archive/modules/detail.vue';
import { GanttChart } from './components';
import { useGridColumns, useGridFormSchema } from './data';
import ScheduleForm from './modules/schedule-form.vue';
import SchedulePreview from '../workorder-center/modules/schedule-preview.vue';
const router = useRouter();
const ganttTasks = ref<any[]>([]); // 甘特图预览数据
@@ -35,10 +34,6 @@
  destroyOnClose: true,
});
const [SchedulePreviewModal, schedulePreviewModalApi] = useVbenModal({
  connectedComponent: SchedulePreview,
  destroyOnClose: true,
});
/** 刷新表格 */
function handleRefresh() {
@@ -65,28 +60,6 @@
}
/** 一键排产预览 */
async function handleAutoSchedulePreview(row: MesProWorkOrderApi.WorkOrder) {
  try {
    const preview = await previewAutoGenerate({ workOrderId: row.id! });
    schedulePreviewModalApi
      .setData({ workOrder: row, preview })
      .open();
  } catch {
    message.error('获取排产预览失败');
  }
}
/** 一键排产执行 */
async function handleAutoSchedule(row: MesProWorkOrderApi.WorkOrder) {
  try {
    const result = await autoGenerateTasks({ workOrderId: row.id! });
    message.success(`排产成功,生成 ${result.taskIds?.length || 0} 个任务`);
    handleRefresh();
  } catch {
    message.error('排产失败');
  }
}
/** 打开归档详情 */
function handleArchive(row: MesProWorkOrderApi.WorkOrder) {
  archiveProductCode.value = row.productCode || '';
@@ -151,10 +124,11 @@
<template>
  <Page auto-content-height>
    <ScheduleModal @success="handleRefresh" />
    <SchedulePreviewModal @success="handleRefresh" />
    <!-- 排产甘特图预览 -->
    <Card title="排产甘特图" class="mb-4">
      <template #extra>
        <span class="text-xs text-gray-400">展示已确认自制订单的任务计划</span>
      </template>
      <GanttChart :height="350" :readonly="true" :tasks="ganttTasks" />
    </Card>
@@ -186,11 +160,17 @@
          {{ row.code }}
        </Button>
      </template>
      <template #progressPercent="{ row }">
        <Progress
          :percent="Math.min(100, Math.round((row.quantity ? ((row.quantityProduced || 0) / row.quantity) * 100 : 0)))"
          size="small"
        />
      </template>
      <template #actions="{ row }">
        <TableAction
          :actions="[
            {
              label: '排产',
              label: '排产维护',
              type: 'link',
              auth: ['mes:pro-task:create'],
              ifShow: row.status === MesProWorkOrderStatusEnum.CONFIRMED,
src/views/mes/pro/task/modules/schedule-form.vue
@@ -132,6 +132,7 @@
          v-for="rp in routeProcessList"
          :key="rp.processId"
          :title="rp.processName"
          :description="rp.paramTemplateId ? `参数模板 #${rp.paramTemplateId}` : '未配置参数模板'"
        />
      </Steps>
      <template v-for="(rp, index) in routeProcessList" :key="rp.processId">
src/views/mes/pro/task/modules/task-list.vue
@@ -14,6 +14,7 @@
import { useTaskGridColumns } from '../data';
import TaskForm from './task-form.vue';
import QuickFeedbackForm from '../../workorder-center/modules/quick-feedback.vue';
const props = defineProps<{
  colorCode?: string;
@@ -29,6 +30,11 @@
const [TaskFormModal, taskFormModalApi] = useVbenModal({
  connectedComponent: TaskForm,
  destroyOnClose: true,
});
const [QuickFeedbackModal, quickFeedbackModalApi] = useVbenModal({
  connectedComponent: QuickFeedbackForm,
  destroyOnClose: true,
});
@@ -54,6 +60,18 @@
/** 编辑任务 */
function handleEdit(row: MesProTaskApi.Task) {
  taskFormModalApi.setData({ id: row.id }).open();
}
/** 快速报工 */
function handleQuickFeedback(row: MesProTaskApi.Task) {
  quickFeedbackModalApi
    .setData({
      taskId: row.id,
      taskCode: row.code,
      taskQuantity: row.quantity,
      taskProducedQuantity: row.producedQuantity,
    })
    .open();
}
/** 删除任务 */
@@ -107,7 +125,7 @@
// 工序步骤切换时重新加载当前工序的任务
watch(
  () => props.processId,
  () => [props.workOrderId, props.routeId, props.processId],
  () => handleRefresh(),
);
@@ -117,6 +135,7 @@
<template>
  <div>
    <TaskFormModal @success="handleRefresh" />
    <QuickFeedbackModal @success="handleRefresh" />
    <Grid table-title="生产任务">
      <template v-if="editable" #toolbar-tools>
        <TableAction
@@ -141,6 +160,13 @@
        <TableAction
          :actions="[
            {
              label: '报工',
              type: 'link',
              auth: ['mes:pro-feedback:create'],
              ifShow: (row.quantity ?? 0) > (row.producedQuantity ?? 0),
              onClick: handleQuickFeedback.bind(null, row),
            },
            {
              label: $t('common.edit'),
              type: 'link',
              icon: ACTION_ICON.EDIT,