From 76c9a49c3ded285857f0c252def2552469b85825 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期一, 10 八月 2026 17:12:26 +0800
Subject: [PATCH] feat(erp): 新增采购发票功能并优化付款流程

---
 src/views/erp/finance/payment/modules/item-form.vue |  175 ++++++++++++++++++---------------------------------------
 1 files changed, 56 insertions(+), 119 deletions(-)

diff --git a/src/views/erp/finance/payment/modules/item-form.vue b/src/views/erp/finance/payment/modules/item-form.vue
index 3aadbe5..6843412 100644
--- a/src/views/erp/finance/payment/modules/item-form.vue
+++ b/src/views/erp/finance/payment/modules/item-form.vue
@@ -1,26 +1,30 @@
 <script lang="ts" setup>
 import type { ErpFinancePaymentApi } from '#/api/erp/finance/payment';
-import type { ErpPurchaseInApi } from '#/api/erp/purchase/in';
-import type { ErpPurchaseReturnApi } from '#/api/erp/purchase/return';
 
 import { computed, nextTick, ref, watch } from 'vue';
 
 import { ErpBizType } from '@vben/constants';
 import { erpPriceInputFormatter } from '@vben/utils';
 
-import { Input, InputNumber, message } from 'ant-design-vue';
+import { Input, InputNumber } from 'ant-design-vue';
 
-import { TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import { useVbenVxeGrid } from '#/adapter/vxe-table';
 
 import { useFormItemColumns } from '../data';
-import PurchaseInSelect from './purchase-in-select.vue';
-import SaleReturnSelect from './sale-return-select.vue';
+
+interface InvoiceForItem {
+  id?: number;
+  no?: string;
+  price?: number;
+  remainingInvoicePrice?: number;
+}
 
 interface Props {
   items?: ErpFinancePaymentApi.FinancePaymentItem[];
   supplierId?: number;
   disabled?: boolean;
   discountPrice?: number;
+  invoice?: InvoiceForItem;
 }
 
 const props = withDefaults(defineProps<Props>(), {
@@ -28,6 +32,7 @@
   supplierId: undefined,
   disabled: false,
   discountPrice: 0,
+  invoice: undefined,
 });
 
 const emit = defineEmits([
@@ -37,6 +42,9 @@
 ]);
 
 const tableData = ref<ErpFinancePaymentApi.FinancePaymentItem[]>([]); // 琛ㄦ牸鏁版嵁
+
+/** 宸叉牴鎹鏉ョエ鐢熸垚鐨勬槑缁嗭紝閬垮厤閲嶅鐢熸垚 */
+const generatedInvoiceId = ref<number | undefined>();
 
 /** 鑾峰彇琛ㄦ牸鍚堣鏁版嵁 */
 const summaries = computed(() => {
@@ -59,7 +67,7 @@
 /** 琛ㄦ牸閰嶇疆 */
 const [Grid, gridApi] = useVbenVxeGrid({
   gridOptions: {
-    columns: useFormItemColumns(props.disabled),
+    columns: useFormItemColumns(),
     data: tableData.value,
     minHeight: 250,
     autoResize: true,
@@ -85,11 +93,44 @@
       return;
     }
     tableData.value = [...items];
+    // 缂栬緫鍥炴樉鏃讹紝鏍囪宸叉牴鎹綋鍓嶆潵绁ㄧ敓鎴愯繃锛岄伩鍏嶉噸澶嶇敓鎴�
+    generatedInvoiceId.value = props.invoice?.id;
     await nextTick(); // 鐗规畩锛氫繚璇� gridApi 宸茬粡鍒濆鍖�
     await gridApi.grid.reloadData(tableData.value);
   },
   {
     immediate: true,
+  },
+);
+
+/** 鍏宠仈鏉ョエ鍙樺寲鏃讹紝鑷姩鐢熸垚鍞竴鐨勪粯娆炬槑缁嗭紙浠樻鍩轰簬鏉ョエ锛� */
+watch(
+  () => props.invoice?.id,
+  async (newId) => {
+    if (!newId || !props.invoice) {
+      return;
+    }
+    if (generatedInvoiceId.value === newId) {
+      return;
+    }
+    generatedInvoiceId.value = newId;
+    const invoice = props.invoice;
+    const price = invoice.price ?? 0;
+    const remaining = invoice.remainingInvoicePrice ?? price;
+    tableData.value = [
+      {
+        bizId: invoice.id ?? 0,
+        bizType: ErpBizType.PURCHASE_INVOICE,
+        bizNo: invoice.no ?? '',
+        totalPrice: price,
+        paidPrice: price - remaining,
+        paymentPrice: remaining,
+        remark: '',
+      },
+    ];
+    await nextTick();
+    await gridApi.grid.reloadData(tableData.value);
+    emit('update:items', [...tableData.value]);
   },
 );
 
@@ -116,74 +157,6 @@
   { deep: true },
 );
 
-/** 娣诲姞閲囪喘鍏ュ簱鍗� */
-const purchaseInSelectRef = ref();
-const handleOpenPurchaseIn = () => {
-  if (!props.supplierId) {
-    message.error('璇烽�夋嫨渚涘簲鍟�');
-    return;
-  }
-  purchaseInSelectRef.value?.open(props.supplierId);
-};
-
-const handleAddPurchaseIn = (rows: ErpPurchaseInApi.PurchaseIn[]) => {
-  rows.forEach((row) => {
-    const totalPrice = row.totalPrice ?? 0;
-    const paidPrice = row.paymentPrice ?? 0;
-    const newItem: ErpFinancePaymentApi.FinancePaymentItem = {
-      bizId: row.id ?? 0,
-      bizType: ErpBizType.PURCHASE_IN,
-      bizNo: row.no ?? '',
-      totalPrice,
-      paidPrice,
-      paymentPrice: totalPrice - paidPrice,
-      remark: undefined,
-    };
-    tableData.value.push(newItem);
-  });
-  emit('update:items', [...tableData.value]);
-};
-
-/** 娣诲姞閲囪喘閫�璐у崟 */
-const saleReturnSelectRef = ref();
-const handleOpenSaleReturn = () => {
-  if (!props.supplierId) {
-    message.error('璇烽�夋嫨渚涘簲鍟�');
-    return;
-  }
-  saleReturnSelectRef.value?.open(props.supplierId);
-};
-
-const handleAddSaleReturn = (rows: ErpPurchaseReturnApi.PurchaseReturn[]) => {
-  rows.forEach((row) => {
-    const totalPrice = row.totalPrice ?? 0;
-    const refundPrice = row.refundPrice ?? 0;
-    const newItem: ErpFinancePaymentApi.FinancePaymentItem = {
-      bizId: row.id ?? 0,
-      bizType: ErpBizType.PURCHASE_RETURN,
-      bizNo: row.no ?? '',
-      totalPrice: -totalPrice,
-      paidPrice: -refundPrice,
-      paymentPrice: -totalPrice + refundPrice,
-      remark: undefined,
-    };
-    tableData.value.push(newItem);
-  });
-  emit('update:items', [...tableData.value]);
-};
-
-/** 鍒犻櫎琛� */
-const handleDelete = async (row: any) => {
-  const index = tableData.value.findIndex(
-    (item) => item.bizId === row.bizId && item.bizType === row.bizType,
-  );
-  if (index !== -1) {
-    tableData.value.splice(index, 1);
-  }
-  // 閫氱煡鐖剁粍浠舵洿鏂�
-  emit('update:items', [...tableData.value]);
-};
-
 /** 澶勭悊琛屾暟鎹彉鏇� */
 const handleRowChange = (row: any) => {
   const index = tableData.value.findIndex(
@@ -201,7 +174,7 @@
 const validate = () => {
   // 妫�鏌ユ槸鍚︽湁鏄庣粏
   if (tableData.value.length === 0) {
-    throw new Error('璇锋坊鍔犱粯娆炬槑缁�');
+    throw new Error('璇峰厛閫夋嫨鍏宠仈鏉ョエ');
   }
   // 妫�鏌ユ瘡琛岀殑浠樻閲戦
   for (let i = 0; i < tableData.value.length; i++) {
@@ -236,21 +209,6 @@
           @change="handleRowChange(row)"
         />
       </template>
-      <template #actions="{ row }">
-        <TableAction
-          :actions="[
-            {
-              label: '鍒犻櫎',
-              type: 'link',
-              danger: true,
-              popConfirm: {
-                title: '纭鍒犻櫎璇ヤ粯娆炬槑缁嗗悧锛�',
-                confirm: handleDelete.bind(null, row),
-              },
-            },
-          ]"
-        />
-      </template>
 
       <template #bottom>
         <div class="mt-2 rounded border border-border bg-muted p-2">
@@ -258,7 +216,7 @@
             <span class="font-medium text-foreground">鍚堣锛�</span>
             <div class="flex space-x-4">
               <span>
-                鍚堣浠樻锛歿{ erpPriceInputFormatter(summaries.totalPrice) }}
+                搴斾粯閲戦锛歿{ erpPriceInputFormatter(summaries.totalPrice) }}
               </span>
               <span>
                 宸蹭粯閲戦锛歿{ erpPriceInputFormatter(summaries.paidPrice) }}
@@ -270,34 +228,13 @@
             </div>
           </div>
         </div>
-        <TableAction
-          v-if="!disabled"
-          class="mt-2 flex justify-center"
-          :actions="[
-            {
-              label: '娣诲姞閲囪喘鍏ュ簱鍗�',
-              type: 'default',
-              onClick: handleOpenPurchaseIn,
-            },
-            {
-              label: '娣诲姞閲囪喘閫�璐у崟',
-              type: 'default',
-              onClick: handleOpenSaleReturn,
-            },
-          ]"
-        />
+        <div
+          v-if="!invoice && !disabled"
+          class="mt-2 flex justify-center text-sm text-muted-foreground"
+        >
+          璇峰厛鍦ㄤ笂鏂硅〃鍗曢�夋嫨鍏宠仈鏉ョエ锛岀郴缁熷皢鑷姩鐢熸垚浠樻鏄庣粏
+        </div>
       </template>
     </Grid>
-
-    <!-- 閲囪喘鍏ュ簱鍗曢�夋嫨缁勪欢 -->
-    <PurchaseInSelect
-      ref="purchaseInSelectRef"
-      @success="handleAddPurchaseIn"
-    />
-    <!-- 閲囪喘閫�璐у崟閫夋嫨缁勪欢 -->
-    <SaleReturnSelect
-      ref="saleReturnSelectRef"
-      @success="handleAddSaleReturn"
-    />
   </div>
 </template>

--
Gitblit v1.9.3