From 7a5c5250b66cc6faffbcac9e192073473c50f79f Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 28 八月 2026 17:02:04 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev_pro2.0' into dev_pro2.0

---
 src/views/erp/sale/order/index.vue |  226 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 200 insertions(+), 26 deletions(-)

diff --git a/src/views/erp/sale/order/index.vue b/src/views/erp/sale/order/index.vue
index d72d704..925be2a 100644
--- a/src/views/erp/sale/order/index.vue
+++ b/src/views/erp/sale/order/index.vue
@@ -2,33 +2,45 @@
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
 import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
 
-import { ref } from 'vue';
-import { useRouter } from 'vue-router';
+import { onMounted, ref } from 'vue';
+import { useRoute, useRouter } from 'vue-router';
 
-import { Page, useVbenModal } from '../../../../packages/effects/common-ui/src';
-import { downloadFileFromBlobPart, isEmpty } from '../../../../packages/utils/src';
+import { Page, useVbenModal } from '@vben/common-ui';
+import { downloadFileFromBlobPart, isEmpty } from '@vben/utils';
 
-import { message } from 'ant-design-vue';
+import { message, Tag, Tooltip } from 'ant-design-vue';
 
 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
 import {
+  cancelSaleOrder,
   deleteSaleOrder,
+  enableSaleOrder,
   exportSaleOrder,
+  getSaleOrderApproveProcessList,
   getSaleOrderPage,
-  updateSaleOrderStatus,
+  submitSaleOrder,
 } from '#/api/erp/sale/order';
+import { generateFromSaleOrder } from '#/api/mes/wm/salesnotice';
 import { $t } from '#/locales';
 
 import { useGridColumns, useGridFormSchema } from './data';
 import Form from './modules/form.vue';
+import SaleOrderPrint from './modules/print.vue';
+import SalesNoticeForm from '#/views/wls/salesnotice/modules/form.vue';
 
 /** ERP 閿�鍞鍗曞垪琛� */
 defineOptions({ name: 'ErpSaleOrder' });
 
 const router = useRouter();
+const route = useRoute();
 
 const [FormModal, formModalApi] = useVbenModal({
   connectedComponent: Form,
+  destroyOnClose: true,
+});
+
+const [SalesNoticeFormModal, salesNoticeFormModalApi] = useVbenModal({
+  connectedComponent: SalesNoticeForm,
   destroyOnClose: true,
 });
 
@@ -68,18 +80,61 @@
   }
 }
 
-/** 瀹℃壒/鍙嶅鎵规搷浣� */
-async function handleUpdateStatus(
-  row: ErpSaleOrderApi.SaleOrder,
-  status: number,
-) {
+/** 鎻愪氦閿�鍞鍗曞鎵癸紙鍗忓悓鍔炲叕锛� */
+async function handleSubmit(row: ErpSaleOrderApi.SaleOrder) {
+  // 鑾峰彇鍙敤鐨勫鎵规祦绋嬪畾涔�
+  const processList = await getSaleOrderApproveProcessList();
+  if (isEmpty(processList)) {
+    message.error('閿�鍞鍗曞鎵规祦绋嬫湭閰嶇疆锛岃鍏堝湪銆屽崗鍚屽姙鍏啋娴佺▼绠$悊銆嶄腑鍒涘缓骞跺彂甯冮攢鍞鍗曞鎵规祦绋�');
+    return;
+  }
   const hideLoading = message.loading({
-    content: `纭畾${status === 20 ? '瀹℃壒' : '鍙嶅鎵�'}璇ヨ鍗曞悧锛焋,
+    content: '姝e湪鎻愪氦瀹℃壒...',
     duration: 0,
   });
   try {
-    await updateSaleOrderStatus(row.id!, status);
-    message.success(`${status === 20 ? '瀹℃壒' : '鍙嶅鎵�'}鎴愬姛`);
+    await submitSaleOrder(row.id!, processList[0].key);
+    message.success('鎻愪氦瀹℃壒鎴愬姛锛岃鍒板崗鍚屽姙鍏腑澶勭悊');
+    handleRefresh();
+  } finally {
+    hideLoading();
+  }
+}
+
+/** 鏌ョ湅瀹℃壒杩涘害锛堣烦杞崗鍚屽姙鍏祦绋嬭鎯咃紝鍙妯″紡锛屼笉鏄剧ず瀹℃壒鎿嶄綔锛� */
+function handleViewApproval(row: ErpSaleOrderApi.SaleOrder) {
+  if (row.processInstanceId) {
+    router.push({
+      name: 'BpmProcessInstanceDetail',
+      query: { id: row.processInstanceId, viewOnly: '1' },
+    });
+  }
+}
+
+/** 浣滃簾閿�鍞鍗� */
+async function handleCancel(row: ErpSaleOrderApi.SaleOrder) {
+  const hideLoading = message.loading({
+    content: '姝e湪浣滃簾璇ヨ鍗�...',
+    duration: 0,
+  });
+  try {
+    await cancelSaleOrder(row.id!);
+    message.success('浣滃簾鎴愬姛');
+    handleRefresh();
+  } finally {
+    hideLoading();
+  }
+}
+
+/** 鍚敤閿�鍞鍗曪紙鎭㈠宸蹭綔搴熻鍗曪級 */
+async function handleEnable(row: ErpSaleOrderApi.SaleOrder) {
+  const hideLoading = message.loading({
+    content: '姝e湪鍚敤璇ヨ鍗�...',
+    duration: 0,
+  });
+  try {
+    await enableSaleOrder(row.id!);
+    message.success('鍚敤鎴愬姛');
     handleRefresh();
   } finally {
     hideLoading();
@@ -100,13 +155,33 @@
   formModalApi.setData({ formType: 'detail', id: row.id }).open();
 }
 
+/** 鎵撳嵃/瀵煎嚭閿�鍞鍗曡鎯咃紝渚涗紒涓氱洊绔犵暀瀛� */
+const printRef = ref<InstanceType<typeof SaleOrderPrint>>();
+function handlePrint(row: ErpSaleOrderApi.SaleOrder) {
+  printRef.value?.print(row.id!);
+}
+
 /** 鏌ョ湅鍏宠仈鍚堝悓 */
 function handleViewContract(row: ErpSaleOrderApi.SaleOrder) {
   if (row.contractId) {
     router.push({
-      path: '/crm/contract/detail',
-      query: { id: row.contractId },
+      path: `/crm/contract/detail/${row.contractId}`,
     });
+  }
+}
+
+/** 鐢熸垚鍙戣揣閫氱煡鍗� */
+async function handleGenerateNotice(row: ErpSaleOrderApi.SaleOrder) {
+  try {
+    const noticeId = await generateFromSaleOrder(row.id!);
+    message.success('鐢熸垚鍙戣揣閫氱煡鍗曟垚鍔�');
+    handleRefresh();
+    // 鐩存帴鎵撳紑鍙戣揣閫氱煡鍗曡鎯呭脊妗�
+    salesNoticeFormModalApi
+      .setData({ formType: 'detail', id: noticeId })
+      .open();
+  } catch (e) {
+    console.error(e);
   }
 }
 
@@ -121,10 +196,19 @@
     proxyConfig: {
       ajax: {
         query: async ({ page }, formValues) => {
+          // 鐢熶骇鐘舵�佹悳绱㈠弬鏁拌浆鎹細-1(鏃犻渶鐢熶骇) 鈫� needProduction=0
+          const { productionStatus, ...rest } = formValues;
+          const params: Record<string, any> = { ...rest };
+          if (productionStatus === -1) {
+            params.needProduction = 0;
+          } else if (productionStatus != null) {
+            params.productionStatus = productionStatus;
+            params.needProduction = 1;
+          }
           return await getSaleOrderPage({
             pageNo: page.currentPage,
             pageSize: page.pageSize,
-            ...formValues,
+            ...params,
           });
         },
       },
@@ -143,10 +227,21 @@
     checkboxChange: handleRowCheckboxChange,
   },
 });
+
+/** 澶勭悊浠庡悎鍚岃烦杞繃鏉ョ殑鏌ヨ鍙傛暟 */
+onMounted(() => {
+  const orderId = route.query.id;
+  if (orderId) {
+    formModalApi.setData({ formType: 'detail', id: Number(orderId) }).open();
+  }
+});
 </script>
 
 <template>
-  <Page auto-content-height><FormModal @success="handleRefresh" />
+  <Page auto-content-height>
+    <FormModal @success="handleRefresh" />
+    <SalesNoticeFormModal />
+    <SaleOrderPrint ref="printRef" />
     <Grid table-title="閿�鍞鍗曞垪琛�">
       <template #toolbar-tools>
         <TableAction
@@ -180,11 +275,47 @@
           ]"
         />
       </template>
+      <template #no="{ row }">
+        <Tooltip v-if="row.status === 30" title="璇ヨ鍗曞凡浣滃簾锛岃鍗曞凡澶辨晥">
+          <span class="text-red-500 cursor-pointer" @click="handleDetail(row)">
+            {{ row.no }}
+          </span>
+        </Tooltip>
+        <a v-else class="text-primary cursor-pointer" @click="handleDetail(row)">
+          {{ row.no }}
+        </a>
+      </template>
       <template #contractNo="{ row }">
         <a v-if="row.contractId" class="text-primary cursor-pointer" @click="handleViewContract(row)">
           {{ row.contractNo }}
         </a>
         <span v-else>-</span>
+      </template>
+      <template #status="{ row }">
+        <Tag v-if="row.status === 0" color="default">鏈彁浜�</Tag>
+        <Tag v-if="row.status === 15" color="processing">瀹℃壒涓�</Tag>
+        <Tag v-if="row.status === 20" color="success">宸插鏍�</Tag>
+        <Tag v-if="row.status === 35" color="warning">宸查┏鍥�</Tag>
+        <Tag v-if="row.status === 30" color="error">宸蹭綔搴�</Tag>
+      </template>
+      <template #needProduction="{ row }">
+        <Tag v-if="row.needProduction === 1" color="success">鏄�</Tag>
+        <Tag v-else color="default">鍚�</Tag>
+      </template>
+      <template #outStatus="{ row }">
+        <Tag v-if="row.outStatus === 0" color="default">鏈嚭搴�</Tag>
+        <Tag v-else-if="row.outStatus === 1" color="processing">宸查鐣�</Tag>
+        <Tag v-else-if="row.outStatus === 2" color="warning">閮ㄥ垎鍑哄簱</Tag>
+        <Tag v-else-if="row.outStatus === 3" color="success">鍏ㄩ儴鍑哄簱</Tag>
+      </template>
+      <template #productionStatus="{ row }">
+        <template v-if="row.needProduction !== 1">
+          <Tag color="default">鏃犻渶鐢熶骇</Tag>
+        </template>
+        <template v-else>
+          <Tag v-if="row.productionStatus === 0" color="warning">鏈畬鎴�</Tag>
+          <Tag v-else-if="row.productionStatus === 1" color="success">宸插畬鎴�</Tag>
+        </template>
       </template>
       <template #actions="{ row }">
         <TableAction
@@ -197,26 +328,68 @@
               onClick: handleDetail.bind(null, row),
             },
             {
+              label: '鎵撳嵃',
+              type: 'link',
+              icon: 'lucide:printer',
+              auth: ['erp:sale-order:query'],
+              onClick: handlePrint.bind(null, row),
+            },
+            {
               label: $t('common.edit'),
               type: 'link',
               icon: ACTION_ICON.EDIT,
               auth: ['erp:sale-order:update'],
-              ifShow: () => row.status !== 20,
+              ifShow: () => row.status === 0 || row.status === 35,
               onClick: handleEdit.bind(null, row),
             },
             {
-              label: row.status === 10 ? '瀹℃壒' : '鍙嶅鎵�',
+              label: '鎻愪氦瀹℃壒',
               type: 'link',
               icon: ACTION_ICON.AUDIT,
               auth: ['erp:sale-order:update-status'],
+              ifShow: () => row.status === 0 || row.status === 35,
               popConfirm: {
-                title: `纭${row.status === 10 ? '瀹℃壒' : '鍙嶅鎵�'}${row.no}鍚楋紵`,
-                confirm: handleUpdateStatus.bind(
-                  null,
-                  row,
-                  row.status === 10 ? 20 : 10,
-                ),
+                title: `纭鎻愪氦${row.no}鐨勫鎵瑰悧锛熸彁浜ゅ悗瀹℃壒灏嗗湪鍗忓悓鍔炲叕涓畬鎴恅,
+                confirm: handleSubmit.bind(null, row),
               },
+            },
+            {
+              label: '瀹℃壒杩涘害',
+              type: 'link',
+              icon: 'lucide:file-clock',
+              auth: ['erp:sale-order:query'],
+              ifShow: () => row.status === 15 && !!row.processInstanceId,
+              onClick: handleViewApproval.bind(null, row),
+            },
+            {
+              label: '浣滃簾',
+              type: 'link',
+              icon: 'ant-design:stop-outlined',
+              auth: ['erp:sale-order:cancel'],
+              ifShow: () => row.status === 20,
+              popConfirm: {
+                title: `纭浣滃簾${row.no}鍚楋紵浣滃簾鍚庝笉鍙仮澶嶏紒`,
+                confirm: handleCancel.bind(null, row),
+              },
+            },
+            {
+              label: '鍚敤',
+              type: 'link',
+              icon: 'ant-design:check-circle-outlined',
+              auth: ['erp:sale-order:enable'],
+              ifShow: () => row.status === 30,
+              popConfirm: {
+                title: `纭鍚敤${row.no}鍚楋紵`,
+                confirm: handleEnable.bind(null, row),
+              },
+            },
+            {
+              label: '鐢熸垚鍙戣揣閫氱煡鍗�',
+              type: 'link',
+              icon: 'ant-design:file-protect-outlined',
+              auth: ['mes:wm-sales-notice:create'],
+              ifShow: () => row.status === 20 && !!row.canCreateSalesNotice,
+              onClick: handleGenerateNotice.bind(null, row),
             },
             {
               label: $t('common.delete'),
@@ -224,6 +397,7 @@
               danger: true,
               icon: ACTION_ICON.DELETE,
               auth: ['erp:sale-order:delete'],
+              ifShow: () => row.status === 0 || row.status === 35,
               popConfirm: {
                 title: $t('ui.actionMessage.deleteConfirm', [row.no]),
                 confirm: handleDelete.bind(null, [row.id!]),

--
Gitblit v1.9.3