From 0c221f3e96cc6aae6b6bcf67e984cb446dcfac87 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期四, 23 七月 2026 09:32:34 +0800
Subject: [PATCH] fix(mes): 解决排产表单工序加载和完成按钮显示问题

---
 src/views/mes/pro/workorder/modules/form.vue |  589 +++++++++++++++++++++++++++++++++-------------------------
 1 files changed, 331 insertions(+), 258 deletions(-)

diff --git a/src/views/mes/pro/workorder/modules/form.vue b/src/views/mes/pro/workorder/modules/form.vue
index d8a1093..bc00c84 100644
--- a/src/views/mes/pro/workorder/modules/form.vue
+++ b/src/views/mes/pro/workorder/modules/form.vue
@@ -1,295 +1,368 @@
 <script lang="ts" setup>
-import type { FormType } from '../data';
+  import type { FormType } from "../data";
 
-import type { MesProWorkOrderApi } from '#/api/mes/pro/workorder';
-import type { MesProWorkOrderBomApi } from '#/api/mes/pro/workorder/bom';
+  import type { MesProWorkOrderApi } from "#/api/mes/pro/workorder";
+  import type { MesProWorkOrderBomApi } from "#/api/mes/pro/workorder/bom";
+  import type { MesProWorkOrderProcessApi } from "#/api/mes/pro/workorder/process";
 
-import { computed, ref } from 'vue';
+  import { computed, ref } from "vue";
 
-import { useVbenModal } from '../../../../../packages/effects/common-ui/src';
-import { BarcodeBizTypeEnum, MesProWorkOrderStatusEnum } from '../../../../../packages/constants/src';
+  import { confirm, useVbenModal } from "@vben/common-ui";
+  import {
+    BarcodeBizTypeEnum,
+    MesProWorkOrderStatusEnum,
+  } from "@vben/constants";
 
-import { Button, message, Popconfirm, Tabs } from 'ant-design-vue';
+  import { Button, message, Tabs } from "ant-design-vue";
 
-import { useVbenForm } from '#/adapter/form';
-import {
-  confirmWorkOrder,
-  createWorkOrder,
-  finishWorkOrder,
-  getWorkOrder,
-  updateWorkOrder,
-} from '#/api/mes/pro/workorder';
-import { $t } from '#/locales';
-import { BarcodeDetail } from '#/views/mes/wm/barcode/components';
+  import { useVbenForm } from "#/adapter/form";
+  import {
+    confirmWorkOrder,
+    createWorkOrder,
+    finishWorkOrder,
+    getWorkOrder,
+    updateWorkOrder,
+  } from "#/api/mes/pro/workorder";
+  import { batchSaveWorkOrderProcess } from "#/api/mes/pro/workorder/process";
+  import { $t } from "#/locales";
+  import { BarcodeDetail } from "#/views/wls/barcode/components";
 
-import { useFormSchema } from '../data';
-import BomList from './bom-list.vue';
-import ItemList from './item-list.vue';
+  import { useFormSchema } from "../data";
+  import BomList from "./bom-list.vue";
+  import ItemList from "./item-list.vue";
+  import ProcessList from "./process-list.vue";
 
-const emit = defineEmits(['success']);
-const formType = ref<FormType>('create');
-const formData = ref<MesProWorkOrderApi.WorkOrder>();
-const originalSnapshot = ref(''); // 琛ㄥ崟鍘熷鏁版嵁蹇収锛岀敤浜庣‘璁ゆ椂璺宠繃鏈彉鏇寸殑淇濆瓨璇锋眰
-const subTabsName = ref('bom'); // 褰撳墠閫変腑鐨勫瓙琛� Tab
-const barcodeDetailRef = ref<InstanceType<typeof BarcodeDetail>>(); // 鏉$爜璇︽儏寮圭獥
+  const emit = defineEmits(["success"]);
+  const formType = ref<FormType>("create");
+  const formData = ref<MesProWorkOrderApi.WorkOrder>();
+  const originalSnapshot = ref("");
+  const subTabsName = ref("bom");
+  const barcodeDetailRef = ref<InstanceType<typeof BarcodeDetail>>();
+  const processListRef = ref<InstanceType<typeof ProcessList>>();
+  const currentProductId = ref<number>(); // 褰撳墠閫変腑鐨勪骇鍝� ID锛堢敤浜庡伐搴忓姞杞斤級
+  const tempProcessList = ref<MesProWorkOrderProcessApi.WorkOrderProcess[]>([]); // 涓存椂宸ュ簭鍒楄〃
 
-const isEditable = computed(() =>
-  // 鏄惁涓虹紪杈戞ā寮忥紙鍙繚瀛橈級
-  ['create', 'update'].includes(formType.value),
-);
-const isConfirm = computed(() => formType.value === 'confirm'); // 鏄惁涓虹‘璁ゆā寮�
-const isFinish = computed(() => formType.value === 'finish'); // 鏄惁涓哄畬鎴愭ā寮�
-const canConfirm = computed(
-  () =>
-    // 缂栬緫鎬佽崏绋垮彲纭
-    formType.value === 'update' &&
-    formData.value?.status === MesProWorkOrderStatusEnum.PREPARE,
-);
-const getTitle = computed(() => {
-  const isChild = !!formData.value?.parentId;
-  switch (formType.value) {
-    case 'confirm': {
-      return '纭宸ュ崟';
-    }
-    case 'detail': {
-      return $t('ui.actionTitle.view', ['宸ュ崟']);
-    }
-    case 'finish': {
-      return '瀹屾垚宸ュ崟';
-    }
-    case 'update': {
-      return isChild ? '缂栬緫瀛愬伐鍗�' : $t('ui.actionTitle.edit', ['宸ュ崟']);
-    }
-    default: {
-      return isChild ? '鏂板瀛愬伐鍗�' : $t('ui.actionTitle.create', ['宸ュ崟']);
-    }
-  }
-});
-
-const [Form, formApi] = useVbenForm({
-  commonConfig: {
-    componentProps: {
-      class: 'w-full',
-    },
-    formItemClass: 'col-span-1',
-    labelWidth: 110,
-  },
-  layout: 'horizontal',
-  schema: [],
-  showDefaultActions: false,
-  wrapperClass: 'grid-cols-3',
-});
-
-/** 閲嶆柊鎸傝浇 schema 骞舵寜琛ㄥ崟鎬佹帶鍒跺簳閮ㄧ‘璁ゆ寜閽� */
-function applySchema() {
-  formApi.setState({ schema: useFormSchema(formType.value, formApi) });
-  modalApi.setState({ showConfirmButton: isEditable.value });
-}
-
-/** 鏌ョ湅宸ュ崟鏉$爜 */
-function handleBarcode() {
-  if (!formData.value?.id) {
-    return;
-  }
-  barcodeDetailRef.value?.openByBusiness(
-    formData.value.id,
-    BarcodeBizTypeEnum.WORKORDER,
-    formData.value.code,
-    formData.value.name,
+  const isEditable = computed(() =>
+    ["create", "update"].includes(formType.value)
   );
-}
-
-/** 纭宸ュ崟锛氱紪杈戞�佹湁淇敼鏃跺厛淇濆瓨锛屽啀纭 */
-async function handleConfirm() {
-  const { valid } = await formApi.validate();
-  if (!valid || !formData.value?.id) {
-    return;
-  }
-  modalApi.lock();
-  try {
-    if (isEditable.value) {
-      const current = JSON.stringify(await formApi.getValues());
-      if (current !== originalSnapshot.value) {
-        const data =
-          (await formApi.getValues()) as MesProWorkOrderApi.WorkOrder;
-        await updateWorkOrder({ ...formData.value, ...data });
-        originalSnapshot.value = current;
+  const isConfirm = computed(() => formType.value === "confirm");
+  const isFinish = computed(() => formType.value === "finish");
+  const isCreateMode = computed(() => formType.value === "create");
+  const canConfirm = computed(
+    () =>
+      formType.value === "update" &&
+      formData.value?.status === MesProWorkOrderStatusEnum.PREPARE
+  );
+  const getTitle = computed(() => {
+    const isChild = !!formData.value?.parentId;
+    switch (formType.value) {
+      case "confirm": {
+        return "纭璁㈠崟";
+      }
+      case "detail": {
+        return $t("ui.actionTitle.view", ["璁㈠崟"]);
+      }
+      case "finish": {
+        return "瀹屾垚璁㈠崟";
+      }
+      case "update": {
+        return isChild ? "缂栬緫瀛愯鍗�" : $t("ui.actionTitle.edit", ["璁㈠崟"]);
+      }
+      default: {
+        return isChild ? "鏂板瀛愯鍗�" : $t("ui.actionTitle.create", ["璁㈠崟"]);
       }
     }
-    await confirmWorkOrder(formData.value.id);
-    message.success('宸ュ崟宸茬‘璁�');
-    await modalApi.close();
-    emit('success');
-  } finally {
-    modalApi.unlock();
-  }
-}
-
-/** 瀹屾垚宸ュ崟 */
-async function handleFinish() {
-  if (!formData.value?.id) {
-    return;
-  }
-  modalApi.lock();
-  try {
-    await finishWorkOrder(formData.value.id);
-    message.success('宸ュ崟宸插畬鎴�');
-    await modalApi.close();
-    emit('success');
-  } finally {
-    modalApi.unlock();
-  }
-}
-
-/** 浠� BOM 鐗╂枡琛岄濉瓙宸ュ崟锛氬鐢ㄥ綋鍓嶅伐鍗曚笂涓嬫枃锛岃繘鍏ユ柊澧炴�� */
-async function handleGenerateWorkOrder(
-  bomRow: MesProWorkOrderBomApi.WorkOrderBom,
-) {
-  const current = formData.value;
-  if (!current) {
-    return;
-  }
-  formData.value = undefined;
-  formType.value = 'create';
-  subTabsName.value = 'bom';
-  applySchema();
-  await formApi.resetForm();
-  await formApi.setValues({
-    clientId: current.clientId,
-    name: `${bomRow.itemName}銆�${bomRow.quantity}銆�${bomRow.unitMeasureName || ''}`,
-    orderSourceCode: current.orderSourceCode,
-    orderSourceType: current.orderSourceType,
-    parentId: current.id,
-    productId: bomRow.itemId,
-    quantity: bomRow.quantity,
-    requestDate: current.requestDate,
-    type: current.type,
-    vendorId: current.vendorId,
   });
-  originalSnapshot.value = JSON.stringify(await formApi.getValues());
-  message.info('宸蹭粠 BOM 鐗╂枡棰勫~瀛愬伐鍗曪紝璇疯ˉ鍏呭伐鍗曠紪鐮佺瓑淇℃伅鍚庝繚瀛�');
-}
 
-const [Modal, modalApi] = useVbenModal({
-  async onConfirm() {
-    if (!isEditable.value) {
-      await modalApi.close();
-      return;
-    }
-    const { valid } = await formApi.validate();
-    if (!valid) {
-      return;
-    }
-    modalApi.lock();
-    // 鎻愪氦琛ㄥ崟
-    const data = (await formApi.getValues()) as MesProWorkOrderApi.WorkOrder;
-    try {
-      if (formData.value?.id) {
-        await updateWorkOrder({ ...formData.value, ...data });
-        formData.value = { ...formData.value, ...data };
-      } else {
-        const id = await createWorkOrder(data);
-        formData.value = {
-          ...data,
-          id,
-          status: MesProWorkOrderStatusEnum.PREPARE,
-        };
-        formType.value = 'update';
-        // 鍒涘缓鎴愬姛鍚庡垏鎹㈢紪杈戞�侊紝閲嶆寕 schema 璁┿�屽伐鍗曠姸鎬併�嶅瓧娈垫樉鐜�
-        applySchema();
-        await formApi.setValues(formData.value);
+  // 鍒ゆ柇鏄惁鏄剧ず Tab锛堟柊澧炴ā寮忔垨宸叉湁 ID锛�
+  const showTabs = computed(() => isCreateMode.value || formData.value?.id);
+
+  const [Form, formApi] = useVbenForm({
+    commonConfig: {
+      componentProps: {
+        class: "w-full",
+      },
+      formItemClass: "col-span-1",
+      labelWidth: 110,
+    },
+    layout: "horizontal",
+    schema: [],
+    showDefaultActions: false,
+    wrapperClass: "grid-cols-3",
+    handleValuesChange: (values, fieldsChanged) => {
+      // 浜у搧鍙樻洿鏃讹紝瑙﹀彂宸ュ簭鍔犺浇
+      if (isCreateMode.value && fieldsChanged.includes('productId')) {
+        const newProductId = values.productId;
+        if (newProductId && newProductId !== currentProductId.value) {
+          currentProductId.value = newProductId;
+        }
       }
-      originalSnapshot.value = JSON.stringify(await formApi.getValues());
-      emit('success');
-      message.success($t('ui.actionMessage.operationSuccess'));
-    } finally {
-      modalApi.unlock();
-    }
-  },
-  async onOpenChange(isOpen: boolean) {
-    if (!isOpen) {
-      formData.value = undefined;
-      originalSnapshot.value = '';
+    },
+  });
+
+  /** 閲嶆柊鎸傝浇 schema 骞舵寜琛ㄥ崟鎬佹帶鍒跺簳閮ㄦ寜閽� */
+  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,
+    });
+  }
+
+  /** 鏌ョ湅璁㈠崟鏉$爜 */
+  function handleBarcode() {
+    if (!formData.value?.id) {
       return;
     }
-    // 鍔犺浇鏁版嵁
-    const data = modalApi.getData<{
-      formType: FormType;
-      id?: number;
-      parentRow?: MesProWorkOrderApi.WorkOrder;
-    }>();
-    formType.value = data.formType;
-    subTabsName.value = 'bom';
+    barcodeDetailRef.value?.openByBusiness(
+      formData.value.id,
+      BarcodeBizTypeEnum.WORKORDER,
+      formData.value.code,
+      formData.value.name
+    );
+  }
+
+  /** 浠� BOM 鐗╂枡琛岄濉瓙璁㈠崟 */
+  async function handleGenerateWorkOrder(
+    bomRow: MesProWorkOrderBomApi.WorkOrderBom
+  ) {
+    const current = formData.value;
+    if (!current) {
+      return;
+    }
+    formData.value = undefined;
+    formType.value = "create";
+    subTabsName.value = "bom";
     applySchema();
-    if (data?.id) {
+    await formApi.resetForm();
+    await formApi.setValues({
+      clientId: current.clientId,
+      name: `${bomRow.itemName}銆�${bomRow.quantity}銆�${
+        bomRow.unitMeasureName || ""
+      }`,
+      orderSourceCode: current.orderSourceCode,
+      orderSourceType: current.orderSourceType,
+      parentId: current.id,
+      productId: bomRow.itemId,
+      quantity: bomRow.quantity,
+      requestDate: current.requestDate,
+      type: current.type,
+      vendorId: current.vendorId,
+    });
+    // 璁剧疆褰撳墠浜у搧 ID锛岃Е鍙戝伐搴忓姞杞�
+    currentProductId.value = bomRow.itemId;
+    originalSnapshot.value = JSON.stringify(await formApi.getValues());
+    message.info("宸蹭粠 BOM 鐗╂枡棰勫~瀛愯鍗曪紝璇疯ˉ鍏呰鍗曠紪鐮佺瓑淇℃伅鍚庝繚瀛�");
+  }
+
+  /** 宸ュ簭鍒楄〃鍙樺寲鍥炶皟 */
+  function handleProcessListChange(list: MesProWorkOrderProcessApi.WorkOrderProcess[]) {
+    tempProcessList.value = list;
+  }
+
+  const [Modal, modalApi] = useVbenModal({
+    async onConfirm() {
+      // ---- 纭璁㈠崟妯″紡 ----
+      if (isConfirm.value || canConfirm.value) {
+        const { valid } = await formApi.validate();
+        if (!valid || !formData.value?.id) return;
+        try {
+          await confirm('纭瑕佸畬鎴愯鍗曠紪鍒跺悧锛熺‘璁ゅ悗灏嗕笉鑳芥洿鏀广��');
+        } catch {
+          return;
+        }
+        modalApi.lock();
+        try {
+          // 1. 淇濆瓨宸ュ崟淇℃伅锛堝鏋滄湁鍙樻洿锛�
+          if (isEditable.value) {
+            const current = JSON.stringify(await formApi.getValues());
+            if (current !== originalSnapshot.value) {
+              const data = (await formApi.getValues()) as MesProWorkOrderApi.WorkOrder;
+              await updateWorkOrder({ ...formData.value, ...data });
+              originalSnapshot.value = current;
+            }
+          }
+          // 2. 鎵归噺淇濆瓨宸ュ簭锛堝鏋滄湁锛�
+          if (tempProcessList.value.length > 0) {
+            const processList = tempProcessList.value.map(item => ({
+              ...item,
+              workOrderId: formData.value!.id,
+            }));
+            await batchSaveWorkOrderProcess(processList);
+          }
+          // 3. 纭宸ュ崟
+          await confirmWorkOrder(formData.value.id);
+          message.success('璁㈠崟宸茬‘璁�');
+          await modalApi.close();
+          emit('success');
+        } finally {
+          modalApi.unlock();
+        }
+        return;
+      }
+      // ---- 瀹屾垚璁㈠崟妯″紡 ----
+      if (isFinish.value) {
+        if (!formData.value?.id) return;
+        try {
+          await confirm('纭瑕佸畬鎴愯璁㈠崟鍚楋紵');
+        } catch {
+          return;
+        }
+        modalApi.lock();
+        try {
+          await finishWorkOrder(formData.value.id);
+          message.success('璁㈠崟宸插畬鎴�');
+          await modalApi.close();
+          emit('success');
+        } finally {
+          modalApi.unlock();
+        }
+        return;
+      }
+      // ---- 淇濆瓨锛堟柊澧� / 缂栬緫锛�----
+      if (!isEditable.value) {
+        await modalApi.close();
+        return;
+      }
+      const { valid } = await formApi.validate();
+      if (!valid) return;
       modalApi.lock();
+      const data = (await formApi.getValues()) as MesProWorkOrderApi.WorkOrder;
       try {
-        formData.value = await getWorkOrder(data.id);
-        // 璁剧疆鍒� values
-        await formApi.setValues(formData.value);
+        if (formData.value?.id) {
+          // 缂栬緫妯″紡
+          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 };
+          emit("success");
+          message.success($t("ui.actionMessage.operationSuccess"));
+          await modalApi.close();
+        } else {
+          // 鏂板妯″紡
+          const id = await createWorkOrder(data);
+          // 鎵归噺淇濆瓨宸ュ簭
+          if (tempProcessList.value.length > 0) {
+            const processList = tempProcessList.value.map(item => ({
+              ...item,
+              workOrderId: id,
+            }));
+            await batchSaveWorkOrderProcess(processList);
+          }
+          formData.value = {
+            ...data,
+            id,
+            status: MesProWorkOrderStatusEnum.PREPARE,
+          };
+          formType.value = "update";
+          applySchema();
+          await formApi.setValues(formData.value);
+          emit("success");
+        }
+        originalSnapshot.value = JSON.stringify(await formApi.getValues());
       } finally {
         modalApi.unlock();
       }
-    } else if (data?.parentRow) {
-      // 鏂板瀛愬伐鍗曟椂锛岄濉埗宸ュ崟淇℃伅
-      const parent = data.parentRow;
-      await formApi.setValues({
-        clientId: parent.clientId,
-        orderSourceCode: parent.orderSourceCode,
-        orderSourceType: parent.orderSourceType,
-        parentId: parent.id,
-        requestDate: parent.requestDate,
-        type: parent.type,
-        vendorId: parent.vendorId,
-      });
-    }
-    originalSnapshot.value = JSON.stringify(await formApi.getValues());
-  },
-});
+    },
+    async onOpenChange(isOpen: boolean) {
+      if (!isOpen) {
+        formData.value = undefined;
+        originalSnapshot.value = "";
+        currentProductId.value = undefined;
+        tempProcessList.value = [];
+        return;
+      }
+      const data = modalApi.getData<{
+        formType: FormType;
+        id?: number;
+        parentRow?: MesProWorkOrderApi.WorkOrder;
+      }>();
+      formType.value = data.formType;
+      subTabsName.value = "bom";
+      tempProcessList.value = [];
+      applySchema();
+      if (data?.id) {
+        modalApi.lock();
+        try {
+          formData.value = await getWorkOrder(data.id);
+          await formApi.setValues(formData.value);
+          currentProductId.value = formData.value.productId;
+        } finally {
+          modalApi.unlock();
+        }
+      } else if (data?.parentRow) {
+        const parent = data.parentRow;
+        await formApi.setValues({
+          clientId: parent.clientId,
+          orderSourceCode: parent.orderSourceCode,
+          orderSourceType: parent.orderSourceType,
+          parentId: parent.id,
+          requestDate: parent.requestDate,
+          type: parent.type,
+          vendorId: parent.vendorId,
+        });
+      }
+      originalSnapshot.value = JSON.stringify(await formApi.getValues());
+    },
+  });
 </script>
 
 <template>
-  <Modal :title="getTitle" class="w-3/5">
+  <Modal :title="getTitle"
+         class="w-3/5">
     <Form class="mx-4" />
-    <!-- BOM / 鐗╂枡闇�姹� Tab锛氶潪鏂板缓鎬佸睍绀� -->
-    <template v-if="formData?.id">
-      <Tabs v-model:active-key="subTabsName" class="mx-4">
-        <Tabs.TabPane key="bom" tab="宸ュ崟 BOM">
-          <BomList
+    <!-- BOM / 宸ュ簭 / 鐗╂枡闇�姹� Tab -->
+    <template v-if="showTabs">
+      <Tabs v-model:active-key="subTabsName"
+            class="mx-4">
+        <Tabs.TabPane key="bom"
+                      tab="璁㈠崟 BOM">
+          <BomList v-if="formData?.id"
+                   :form-type="formType"
+                   :work-order="formData"
+                   :work-order-id="formData.id"
+                   @generate-work-order="handleGenerateWorkOrder" />
+          <div v-else class="text-gray-400 text-center py-8">
+            璇峰厛淇濆瓨宸ュ崟鍚庡啀閰嶇疆 BOM
+          </div>
+        </Tabs.TabPane>
+        <Tabs.TabPane key="process"
+                      tab="宸ュ簭">
+          <ProcessList
+            ref="processListRef"
             :form-type="formType"
-            :work-order="formData"
-            :work-order-id="formData.id"
-            @generate-work-order="handleGenerateWorkOrder"
+            :work-order="formData || {}"
+            :work-order-id="formData?.id"
+            :product-id="currentProductId"
+            @process-list-change="handleProcessListChange"
           />
         </Tabs.TabPane>
-        <Tabs.TabPane key="item" tab="鐗╂枡闇�姹�">
-          <ItemList :work-order-id="formData.id" />
+        <Tabs.TabPane key="item"
+                      tab="鐗╂枡闇�姹�">
+          <ItemList v-if="formData?.id"
+                    :work-order-id="formData.id" />
+          <div v-else class="text-gray-400 text-center py-8">
+            璇峰厛淇濆瓨宸ュ崟鍚庡啀鏌ョ湅鐗╂枡闇�姹�
+          </div>
         </Tabs.TabPane>
       </Tabs>
     </template>
     <template #prepend-footer>
-      <div class="flex flex-auto items-center gap-2">
-        <Popconfirm
-          v-if="canConfirm || isConfirm"
-          title="纭瑕佸畬鎴愬伐鍗曠紪鍒跺悧锛熺‘璁ゅ悗灏嗕笉鑳芥洿鏀广��"
-          @confirm="handleConfirm"
-        >
-          <Button type="primary">纭</Button>
-        </Popconfirm>
-        <Popconfirm
-          v-if="isFinish"
-          title="纭瑕佸畬鎴愯宸ュ崟鍚楋紵"
-          @confirm="handleFinish"
-        >
-          <Button type="primary">瀹屾垚</Button>
-        </Popconfirm>
-        <Button
-          v-if="formType === 'detail' && formData?.id"
-          @click="handleBarcode"
-        >
-          鏌ョ湅鏉$爜
-        </Button>
-      </div>
+      <Button v-if="formType === 'detail' && formData?.id"
+              @click="handleBarcode">
+        鏌ョ湅鏉$爜
+      </Button>
     </template>
   </Modal>
   <BarcodeDetail ref="barcodeDetailRef" />

--
Gitblit v1.9.3