From 889d8ddf4c13c1b1bdbabd04c2d80b904020151e Mon Sep 17 00:00:00 2001
From: hsy <1029150275@qq.com>
Date: 星期三, 19 八月 2026 12:49:24 +0800
Subject: [PATCH] 生产订单与报工模块改造汇总 (Git Commit 文档) feat(mes-pro): 生产订单及报工模块审批流与批次填报改造 1. 生产订单功能增强 (Work Order)

---
 src/views/mes/pro/workorder/modules/form.vue |  133 ++++++++++++++++++++++++++++++++++----------
 1 files changed, 102 insertions(+), 31 deletions(-)

diff --git a/src/views/mes/pro/workorder/modules/form.vue b/src/views/mes/pro/workorder/modules/form.vue
index 72d0374..5cca3a7 100644
--- a/src/views/mes/pro/workorder/modules/form.vue
+++ b/src/views/mes/pro/workorder/modules/form.vue
@@ -8,7 +8,6 @@
 
   import { confirm, useVbenModal } from "@vben/common-ui";
   import {
-    BarcodeBizTypeEnum,
     MesProWorkOrderStatusEnum,
   } from "@vben/constants";
 
@@ -24,9 +23,13 @@
   } from "#/api/mes/pro/workorder";
   import { batchSaveWorkOrderProcess, getWorkOrderProcessListByWorkOrderId } from "#/api/mes/pro/workorder/process";
   import { $t } from "#/locales";
-  import { BarcodeDetail } from "#/views/wls/barcode/components";
+  // import { BarcodeDetail } from "#/views/wls/barcode/components";
 
   import { useFormSchema } from "../data";
+  import PredictDelivery from "./ai/predict-delivery.vue";
+  import PredictDuration from "./ai/predict-duration.vue";
+  import PredictMaterial from "./ai/predict-material.vue";
+  import PredictRisk from "./ai/predict-risk.vue";
   import ItemList from "./item-list.vue";
   import ProcessList from "./process-list.vue";
 
@@ -35,7 +38,7 @@
   const formData = ref<MesProWorkOrderApi.WorkOrder>();
   const originalSnapshot = ref("");
   const subTabsName = ref("process");
-  const barcodeDetailRef = ref<InstanceType<typeof BarcodeDetail>>();
+  // const barcodeDetailRef = ref<InstanceType<typeof BarcodeDetail>>();
   const processListRef = ref<InstanceType<typeof ProcessList>>();
   const currentProductId = ref<number>(); // 褰撳墠閫変腑鐨勪骇鍝� ID锛堢敤浜庡伐搴忓姞杞斤級
   const tempProcessList = ref<MesProWorkOrderProcessApi.WorkOrderProcess[]>([]); // 涓存椂宸ュ簭鍒楄〃
@@ -50,6 +53,12 @@
     () =>
       formType.value === "update" &&
       formData.value?.status === MesProWorkOrderStatusEnum.PREPARE
+  );
+  const canUseAi = computed(
+    () =>
+      formData.value?.id &&
+      (formData.value?.status === MesProWorkOrderStatusEnum.PREPARE ||
+        formData.value?.status === MesProWorkOrderStatusEnum.CONFIRMED)
   );
   const getTitle = computed(() => {
     const isChild = !!formData.value?.parentId;
@@ -99,31 +108,58 @@
   });
 
   /** 閲嶆柊鎸傝浇 schema 骞舵寜琛ㄥ崟鎬佹帶鍒跺簳閮ㄦ寜閽� */
+  const mainActionText = computed(() => {
+    if (isConfirm.value) return '纭';
+    if (isFinish.value) return '瀹屾垚';
+    return '鎻愪氦';
+  });
+
+  const showMainBtn = computed(() => isEditable.value || isConfirm.value || isFinish.value);
+
   function applySchema() {
     formApi.setState({ schema: useFormSchema(formType.value, formApi) });
-    const showBtn = isEditable.value || isConfirm.value || isFinish.value;
-    modalApi.setState({
-      showConfirmButton: showBtn,
-      confirmText: isConfirm.value || canConfirm.value
-        ? '纭'
-        : isFinish.value
-          ? '瀹屾垚'
-          : undefined,
-    });
+    modalApi.setState({ showCancelButton: false, showConfirmButton: false });
+  }
+
+  /** 浠呬繚瀛橈紙涓嶆敼鍙樼姸鎬侊級 */
+  async function handleSave() {
+    const { valid } = await formApi.validate();
+    if (!valid || !formData.value?.id) return;
+    modalApi.lock();
+    try {
+      const data = (await formApi.getValues()) as any;
+      if (Array.isArray(data.feedbackRole)) {
+        data.feedbackRole = data.feedbackRole.join(',');
+      }
+      await updateWorkOrder({ ...formData.value, ...data });
+      if (tempProcessList.value.length > 0) {
+        const processList = tempProcessList.value.map(item => ({
+          ...item,
+          workOrderId: formData.value!.id,
+        }));
+        await batchSaveWorkOrderProcess(processList);
+      }
+      formData.value = { ...formData.value, ...data };
+      originalSnapshot.value = JSON.stringify(await formApi.getValues());
+      emit('success');
+      message.success($t('ui.actionMessage.operationSuccess'));
+    } finally {
+      modalApi.unlock();
+    }
   }
 
   /** 鏌ョ湅璁㈠崟鏉$爜 */
-  function handleBarcode() {
-    if (!formData.value?.id) {
-      return;
-    }
-    barcodeDetailRef.value?.openByBusiness(
-      formData.value.id,
-      BarcodeBizTypeEnum.WORKORDER,
-      formData.value.code,
-      formData.value.name
-    );
-  }
+  // function handleBarcode() {
+  //   if (!formData.value?.id) {
+  //     return;
+  //   }
+  //   barcodeDetailRef.value?.openByBusiness(
+  //     formData.value.id,
+  //     BarcodeBizTypeEnum.WORKORDER,
+  //     formData.value.code,
+  //     formData.value.name
+  //   );
+  // }
 
   /** 宸ュ簭鍒楄〃鍙樺寲鍥炶皟 */
   function handleProcessListChange(list: MesProWorkOrderProcessApi.WorkOrderProcess[]) {
@@ -147,7 +183,10 @@
           if (isEditable.value) {
             const current = JSON.stringify(await formApi.getValues());
             if (current !== originalSnapshot.value) {
-              const data = (await formApi.getValues()) as MesProWorkOrderApi.WorkOrder;
+              const data = (await formApi.getValues()) as any;
+              if (Array.isArray(data.feedbackRole)) {
+                data.feedbackRole = data.feedbackRole.join(',');
+              }
               await updateWorkOrder({ ...formData.value, ...data });
               originalSnapshot.value = current;
             }
@@ -209,7 +248,10 @@
       const { valid } = await formApi.validate();
       if (!valid) return;
       modalApi.lock();
-      const data = (await formApi.getValues()) as MesProWorkOrderApi.WorkOrder;
+      const data = (await formApi.getValues()) as any;
+      if (Array.isArray(data.feedbackRole)) {
+        data.feedbackRole = data.feedbackRole.join(',');
+      }
       try {
         if (formData.value?.id) {
           // 缂栬緫妯″紡
@@ -273,7 +315,11 @@
         modalApi.lock();
         try {
           formData.value = await getWorkOrder(data.id);
-          await formApi.setValues(formData.value);
+          const formValues: any = { ...formData.value };
+          if (formValues.feedbackRole && typeof formValues.feedbackRole === 'string') {
+            formValues.feedbackRole = formValues.feedbackRole.split(',');
+          }
+          await formApi.setValues(formValues);
           currentProductId.value = formData.value.productId;
         } finally {
           modalApi.unlock();
@@ -327,11 +373,36 @@
       </Tabs>
     </template>
     <template #prepend-footer>
-      <Button v-if="formType === 'detail' && formData?.id"
-              @click="handleBarcode">
-        鏌ョ湅鏉$爜
-      </Button>
+      <div class="flex flex-auto flex-col gap-2">
+        <div v-if="canUseAi" class="flex items-center gap-2">
+          <PredictMaterial :work-order-id="formData!.id" />
+          <PredictDuration :work-order-id="formData!.id" />
+          <PredictRisk :work-order-id="formData!.id" />
+          <PredictDelivery :work-order-id="formData!.id" />
+        </div>
+        <div v-if="canUseAi && showMainBtn" class="border-t border-gray-200" />
+        <div class="flex items-center">
+          <Button v-if="showMainBtn"
+                  type="primary"
+                  @click="modalApi.onConfirm()">
+            {{ mainActionText }}
+          </Button>
+        </div>
+      </div>
+    </template>
+    <template #append-footer>
+      <div class="flex gap-2">
+        <Button v-if="canConfirm"
+                @click="handleSave">
+          淇濆瓨淇敼
+        </Button>
+        <!-- <Button v-if="formType === 'detail' && formData?.id"
+                @click="handleBarcode">
+          鏌ョ湅鏉$爜
+        </Button> -->
+        <Button @click="modalApi.close()">鍙栨秷</Button>
+      </div>
     </template>
   </Modal>
-  <BarcodeDetail ref="barcodeDetailRef" />
+  <!-- <BarcodeDetail ref="barcodeDetailRef" /> -->
 </template>

--
Gitblit v1.9.3