From 14dd95b9150c7d8f76bb35e62169f92d125523b6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 5 Oct 2025 10:52:13 +0800 Subject: [PATCH] =?UTF-8?q?feat=EF=BC=9A=E3=80=90antd=E3=80=91=E3=80=90erp?= =?UTF-8?q?=20=E7=B3=BB=E7=BB=9F=E3=80=91finance/payment=20=E7=9A=84?= =?UTF-8?q?=E8=BF=81=E7=A7=BB=204/4=EF=BC=88form=20=E9=83=A8=E5=88=86?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/erp/finance/payment/data.ts | 190 ++++++++++++++++++ .../erp/finance/payment/modules/form.vue | 28 ++- .../erp/finance/payment/modules/item-form.vue | 37 +++- .../payment/modules/purchase-in-select.vue | 93 +-------- .../payment/modules/sale-return-select.vue | 125 +----------- 5 files changed, 251 insertions(+), 222 deletions(-) diff --git a/apps/web-antd/src/views/erp/finance/payment/data.ts b/apps/web-antd/src/views/erp/finance/payment/data.ts index d804e90ee..f174beca9 100644 --- a/apps/web-antd/src/views/erp/finance/payment/data.ts +++ b/apps/web-antd/src/views/erp/finance/payment/data.ts @@ -407,3 +407,193 @@ export function useGridColumns(): VxeTableGridOptions['columns'] { }, ]; } + +4; /** 采购入库单选择表单的配置项 */ +export function usePurchaseInGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '入库单号', + component: 'Input', + componentProps: { + placeholder: '请输入入库单号', + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '已自动选择供应商', + }, + }, + { + fieldName: 'paymentStatus', + label: '付款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未付款', value: 0 }, + { label: '部分付款', value: 1 }, + { label: '全部付款', value: 2 }, + ], + placeholder: '请选择付款状态', + allowClear: true, + }, + }, + ]; +} + +/** 采购入库单选择列表的字段 */ +export function usePurchaseInGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '入库单号', + width: 200, + fixed: 'left', + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'inTime', + title: '入库时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'totalPrice', + title: '应付金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'paymentPrice', + title: '已付金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unPaymentPrice', + title: '未付金额', + formatter: ({ row }) => { + return erpPriceInputFormatter(row.totalPrice - row.paymentPrice || 0); + }, + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + ]; +} + +/** 采购退货单选择表单的配置项 */ +export function useSaleReturnGridFormSchema(): VbenFormSchema[] { + return [ + { + fieldName: 'no', + label: '退货单号', + component: 'Input', + componentProps: { + placeholder: '请输入退货单号', + allowClear: true, + }, + }, + { + fieldName: 'supplierId', + label: '供应商', + component: 'Input', + componentProps: { + disabled: true, + placeholder: '已自动选择供应商', + }, + }, + { + fieldName: 'refundStatus', + label: '退款状态', + component: 'Select', + componentProps: { + options: [ + { label: '未退款', value: 0 }, + { label: '部分退款', value: 1 }, + { label: '全部退款', value: 2 }, + ], + placeholder: '请选择退款状态', + allowClear: true, + }, + }, + ]; +} + +/** 采购退货单选择列表的字段 */ +export function useSaleReturnGridColumns(): VxeTableGridOptions['columns'] { + return [ + { + type: 'checkbox', + width: 50, + fixed: 'left', + }, + { + field: 'no', + title: '退货单号', + width: 200, + fixed: 'left', + }, + { + field: 'supplierName', + title: '供应商', + minWidth: 120, + }, + { + field: 'returnTime', + title: '退货时间', + width: 160, + formatter: 'formatDate', + }, + { + field: 'totalPrice', + title: '应退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'refundPrice', + title: '已退金额', + formatter: 'formatAmount2', + minWidth: 120, + }, + { + field: 'unRefundPrice', + title: '未退金额', + formatter: ({ row }) => { + return erpPriceInputFormatter(row.totalPrice - row.refundPrice || 0); + }, + minWidth: 120, + }, + { + field: 'status', + title: '状态', + minWidth: 100, + cellRender: { + name: 'CellDict', + props: { type: DICT_TYPE.ERP_AUDIT_STATUS }, + }, + }, + ]; +} diff --git a/apps/web-antd/src/views/erp/finance/payment/modules/form.vue b/apps/web-antd/src/views/erp/finance/payment/modules/form.vue index 97934ce28..14ef85e8e 100644 --- a/apps/web-antd/src/views/erp/finance/payment/modules/form.vue +++ b/apps/web-antd/src/views/erp/finance/payment/modules/form.vue @@ -85,20 +85,23 @@ const handleUpdateItems = ( items: ErpFinancePaymentApi.FinancePaymentItem[], ) => { formData.value.items = items; - // 重新计算合计付款 - const totalPrice = items.reduce( - (prev, curr) => prev + (curr.totalPrice || 0), - 0, - ); - const paymentPrice = items.reduce( - (prev, curr) => prev + (curr.paymentPrice || 0), - 0, - ); - formData.value.totalPrice = totalPrice; - formData.value.paymentPrice = paymentPrice - formData.value.discountPrice; formApi.setValues({ items, + }); +}; + +/** 更新总金额 */ +const handleUpdateTotalPrice = (totalPrice: number) => { + formData.value.totalPrice = totalPrice; + formApi.setValues({ totalPrice: formData.value.totalPrice, + }); +}; + +/** 更新付款金额 */ +const handleUpdatePaymentPrice = (paymentPrice: number) => { + formData.value.paymentPrice = paymentPrice; + formApi.setValues({ paymentPrice: formData.value.paymentPrice, }); }; @@ -180,7 +183,10 @@ const [Modal, modalApi] = useVbenModal({ :items="formData?.items ?? []" :supplier-id="formData?.supplierId" :disabled="formType === 'detail'" + :discount-price="formData?.discountPrice ?? 0" @update:items="handleUpdateItems" + @update:total-price="handleUpdateTotalPrice" + @update:payment-price="handleUpdatePaymentPrice" /> diff --git a/apps/web-antd/src/views/erp/finance/payment/modules/item-form.vue b/apps/web-antd/src/views/erp/finance/payment/modules/item-form.vue index 476b8e27a..937586aac 100644 --- a/apps/web-antd/src/views/erp/finance/payment/modules/item-form.vue +++ b/apps/web-antd/src/views/erp/finance/payment/modules/item-form.vue @@ -20,15 +20,21 @@ interface Props { items?: ErpFinancePaymentApi.FinancePaymentItem[]; supplierId?: number; disabled?: boolean; + discountPrice?: number; } const props = withDefaults(defineProps(), { items: () => [], supplierId: undefined, disabled: false, + discountPrice: 0, }); -const emit = defineEmits(['update:items']); +const emit = defineEmits([ + 'update:items', + 'update:total-price', + 'update:payment-price', +]); const tableData = ref([]); // 表格数据 @@ -78,7 +84,6 @@ watch( if (!items) { return; } - items.forEach((item) => initRow(item)); tableData.value = [...items]; await nextTick(); // 特殊:保证 gridApi 已经初始化 await gridApi.grid.reloadData(tableData.value); @@ -91,6 +96,29 @@ watch( }, ); +/** 计算 totalPrice、paymentPrice 价格 */ +watch( + () => [tableData.value, props.discountPrice], + () => { + if (!tableData.value || tableData.value.length === 0) { + return; + } + const totalPrice = tableData.value.reduce( + (prev, curr) => prev + (curr.totalPrice || 0), + 0, + ); + const paymentPrice = tableData.value.reduce( + (prev, curr) => prev + (curr.paymentPrice || 0), + 0, + ); + const finalPaymentPrice = paymentPrice - (props.discountPrice || 0); + // 通知父组件更新 + emit('update:total-price', totalPrice); + emit('update:payment-price', finalPaymentPrice); + }, + { deep: true }, +); + /** 添加采购入库单 */ const purchaseInSelectRef = ref(); const handleOpenPurchaseIn = () => { @@ -168,11 +196,6 @@ const handleRowChange = (row: any) => { emit('update:items', [...tableData.value]); }; -/** 初始化行数据 */ -const initRow = (item: any) => { - // 不需要特殊初始化 -}; - /** 表单校验 */ const validate = () => { // 检查是否有明细 diff --git a/apps/web-antd/src/views/erp/finance/payment/modules/purchase-in-select.vue b/apps/web-antd/src/views/erp/finance/payment/modules/purchase-in-select.vue index f66f02634..efcea61fc 100644 --- a/apps/web-antd/src/views/erp/finance/payment/modules/purchase-in-select.vue +++ b/apps/web-antd/src/views/erp/finance/payment/modules/purchase-in-select.vue @@ -9,6 +9,8 @@ import { message, Modal } from 'ant-design-vue'; import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { getPurchaseInPage } from '#/api/erp/purchase/in'; +import { usePurchaseInGridColumns, usePurchaseInGridFormSchema } from '../data'; + const emit = defineEmits<{ success: [rows: ErpPurchaseInApi.PurchaseIn[]]; }>(); @@ -20,97 +22,10 @@ const selectedRows = ref([]); // 选中的行 /** 表格配置 */ const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { - schema: [ - { - fieldName: 'no', - label: '入库单号', - component: 'Input', - componentProps: { - placeholder: '请输入入库单号', - allowClear: true, - }, - }, - { - fieldName: 'supplierId', - label: '供应商', - component: 'Input', - componentProps: { - disabled: true, - placeholder: '已自动选择供应商', - }, - }, - { - fieldName: 'paymentStatus', - label: '付款状态', - component: 'Select', - componentProps: { - options: [ - { label: '未付款', value: 0 }, - { label: '部分付款', value: 1 }, - { label: '全部付款', value: 2 }, - ], - placeholder: '请选择付款状态', - allowClear: true, - }, - }, - ], + schema: usePurchaseInGridFormSchema(), }, gridOptions: { - columns: [ - { - type: 'checkbox', - width: 50, - fixed: 'left', - }, - { - field: 'no', - title: '入库单号', - width: 200, - fixed: 'left', - }, - { - field: 'supplierName', - title: '供应商', - minWidth: 120, - }, - { - field: 'inTime', - title: '入库时间', - width: 160, - formatter: 'formatDate', - }, - { - field: 'totalPrice', - title: '应付金额', - formatter: 'formatAmount2', - minWidth: 120, - }, - { - field: 'paymentPrice', - title: '已付金额', - formatter: 'formatAmount2', - minWidth: 120, - }, - { - field: 'unPaymentPrice', - title: '未付金额', - // TODO @AI:芋艿,后续统一改; - formatter: ({ row }) => { - const unPaymentPrice = row.totalPrice - row.paymentPrice; - return `${unPaymentPrice?.toFixed(2) || '0.00'}元`; - }, - minWidth: 120, - }, - { - field: 'status', - title: '状态', - minWidth: 100, - cellRender: { - name: 'CellDict', - props: { type: 'ERP_AUDIT_STATUS' }, - }, - }, - ], + columns: usePurchaseInGridColumns(), height: 'auto', keepSource: true, proxyConfig: { diff --git a/apps/web-antd/src/views/erp/finance/payment/modules/sale-return-select.vue b/apps/web-antd/src/views/erp/finance/payment/modules/sale-return-select.vue index d03fb806c..e7100ad35 100644 --- a/apps/web-antd/src/views/erp/finance/payment/modules/sale-return-select.vue +++ b/apps/web-antd/src/views/erp/finance/payment/modules/sale-return-select.vue @@ -9,6 +9,8 @@ import { message, Modal } from 'ant-design-vue'; import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { getPurchaseReturnPage } from '#/api/erp/purchase/return'; +import { useSaleReturnGridColumns, useSaleReturnGridFormSchema } from '../data'; + const emit = defineEmits<{ success: [rows: ErpPurchaseReturnApi.PurchaseReturn[]]; }>(); @@ -20,96 +22,10 @@ const selectedRows = ref([]); // 选中 /** 表格配置 */ const [Grid, gridApi] = useVbenVxeGrid({ formOptions: { - schema: [ - { - fieldName: 'no', - label: '退货单号', - component: 'Input', - componentProps: { - placeholder: '请输入退货单号', - allowClear: true, - }, - }, - { - fieldName: 'supplierId', - label: '供应商', - component: 'Input', - componentProps: { - disabled: true, - placeholder: '已自动选择供应商', - }, - }, - { - fieldName: 'refundStatus', - label: '退款状态', - component: 'Select', - componentProps: { - options: [ - { label: '未退款', value: 0 }, - { label: '部分退款', value: 1 }, - { label: '全部退款', value: 2 }, - ], - placeholder: '请选择退款状态', - allowClear: true, - }, - }, - ], + schema: useSaleReturnGridFormSchema(), }, gridOptions: { - columns: [ - { - type: 'checkbox', - width: 50, - fixed: 'left', - }, - { - field: 'no', - title: '退货单号', - width: 200, - fixed: 'left', - }, - { - field: 'supplierName', - title: '供应商', - minWidth: 120, - }, - { - field: 'returnTime', - title: '退货时间', - width: 160, - formatter: 'formatDate', - }, - { - field: 'totalPrice', - title: '应退金额', - formatter: 'formatAmount2', - minWidth: 120, - }, - { - field: 'refundPrice', - title: '已退金额', - formatter: 'formatAmount2', - minWidth: 120, - }, - { - field: 'unRefundPrice', - title: '未退金额', - formatter: ({ row }) => { - const unRefundPrice = row.totalPrice - row.refundPrice; - return `${unRefundPrice?.toFixed(2) || '0.00'}元`; - }, - minWidth: 120, - }, - { - field: 'status', - title: '状态', - minWidth: 100, - cellRender: { - name: 'CellDict', - props: { type: 'ERP_AUDIT_STATUS' }, - }, - }, - ], + columns: useSaleReturnGridColumns(), height: 'auto', keepSource: true, proxyConfig: { @@ -158,16 +74,14 @@ const [Grid, gridApi] = useVbenVxeGrid({ /** 打开弹窗 */ const openModal = (id: number) => { + // 重置数据 supplierId.value = id; open.value = true; selectedRows.value = []; - // 重置表单并设置供应商ID + // 查询列表 gridApi.formApi?.resetForm(); gridApi.formApi?.setValues({ supplierId: id }); - // 延迟查询,确保表单值已设置 - setTimeout(() => { - gridApi.query(); - }, 100); + gridApi.query(); }; /** 确认选择 */ @@ -176,25 +90,7 @@ const handleOk = () => { message.warning('请选择要添加的采购退货单'); return; } - - // 过滤已全部退款的单据 - const validRows = selectedRows.value.filter((row) => { - const unRefundPrice = row.totalPrice - row.refundPrice; - return unRefundPrice > 0; - }); - - if (validRows.length === 0) { - message.warning('所选的退货单已全部退款,无需再付款'); - return; - } - - if (validRows.length < selectedRows.value.length) { - message.warning( - `已过滤${selectedRows.value.length - validRows.length}个已全部退款的退货单`, - ); - } - - emit('success', validRows); + emit('success', selectedRows.value); open.value = false; }; @@ -203,14 +99,13 @@ defineExpose({ open: openModal });