diff --git a/apps/web-antdv-next/src/views/crm/receivable/data.ts b/apps/web-antdv-next/src/views/crm/receivable/data.ts index fffa32ca9..96895a784 100644 --- a/apps/web-antdv-next/src/views/crm/receivable/data.ts +++ b/apps/web-antdv-next/src/views/crm/receivable/data.ts @@ -57,12 +57,19 @@ export function useFormSchema(): VbenFormSchema[] { label: '客户名称', component: 'ApiSelect', rules: 'required', - componentProps: { + componentProps: (_values, form) => ({ api: getCustomerSimpleList, labelField: 'name', valueField: 'id', placeholder: '请选择客户', - }, + onChange: () => { + form.setFieldValue('contractId', undefined); + form.setFieldValue('planId', undefined); + form.setFieldValue('price', undefined); + form.setFieldValue('returnTime', undefined); + form.setFieldValue('returnType', undefined); + }, + }), dependencies: { triggerFields: ['id'], disabled: (values) => values.id, @@ -76,21 +83,33 @@ export function useFormSchema(): VbenFormSchema[] { dependencies: { triggerFields: ['customerId'], disabled: (values) => !values.customerId || values.id, - async componentProps(values) { - if (values.customerId) { - if (!values.id) { - // 特殊:只有在【新增】时,才清空合同编号 - values.contractId = undefined; - } - const contracts = await getContractSimpleList(values.customerId); + async componentProps(values, form) { + if (!values.customerId) { return { - options: contracts.map((item) => ({ - label: item.name, - value: item.id, - })), - placeholder: '请选择合同', - } as any; + options: [], + placeholder: '请选择客户', + }; } + const contracts = await getContractSimpleList(values.customerId); + return { + options: contracts.map((item) => ({ + label: item.name, + value: item.id, + })), + placeholder: '请选择合同', + onChange: (value: number) => { + form.setFieldValue('planId', undefined); + form.setFieldValue('returnTime', undefined); + form.setFieldValue('returnType', undefined); + const contract = contracts.find((item) => item.id === value); + form.setFieldValue( + 'price', + contract + ? contract.totalPrice - contract.totalReceivablePrice + : undefined, + ); + }, + } as any; }, }, }, @@ -101,28 +120,38 @@ export function useFormSchema(): VbenFormSchema[] { rules: 'required', dependencies: { triggerFields: ['contractId'], - disabled: (values) => !values.contractId, - async componentProps(values) { - if (values.contractId) { - values.planId = undefined; - const plans = await getReceivablePlanSimpleList( - values.customerId, - values.contractId, - ); + disabled: (values) => !values.contractId || values.id, + async componentProps(values, form) { + if (!values.contractId) { return { - options: plans.map((item) => ({ - label: item.period, - value: item.id, - })), - placeholder: '请选择回款期数', - onChange: async (value: any) => { - const plan = await getReceivablePlan(value); - values.returnTime = plan?.returnTime; - values.price = plan?.price; - values.returnType = plan?.returnType; - }, - } as any; + options: [], + placeholder: '请选择合同', + }; } + const plans = await getReceivablePlanSimpleList( + values.customerId, + values.contractId, + ); + return { + options: plans.map((item) => ({ + disabled: !!item.receivableId, + label: `第 ${item.period} 期`, + value: item.id, + })), + placeholder: '请选择回款期数', + onChange: async (value: any) => { + if (!value) { + form.setFieldValue('returnTime', undefined); + form.setFieldValue('price', undefined); + form.setFieldValue('returnType', undefined); + return; + } + const plan = await getReceivablePlan(value); + form.setFieldValue('returnTime', plan?.returnTime); + form.setFieldValue('price', plan?.price); + form.setFieldValue('returnType', plan?.returnType); + }, + } as any; }, }, }, diff --git a/apps/web-antdv-next/src/views/crm/receivable/modules/form.vue b/apps/web-antdv-next/src/views/crm/receivable/modules/form.vue index 17e32a27d..e1f2ad1a9 100644 --- a/apps/web-antdv-next/src/views/crm/receivable/modules/form.vue +++ b/apps/web-antdv-next/src/views/crm/receivable/modules/form.vue @@ -7,6 +7,7 @@ import { useVbenForm, useVbenModal } from '@vben/common-ui'; import { message } from 'antdv-next'; +import { getContractSimpleList } from '#/api/crm/contract'; import { createReceivable, getReceivable, @@ -16,8 +17,20 @@ import { $t } from '#/locales'; import { useFormSchema } from '../data'; +type ReceivablePrefillData = Partial< + Pick< + CrmReceivableApi.Receivable, + 'contractId' | 'customerId' | 'price' | 'returnType' + > +> & { id?: number }; + +type ReceivableFormModalData = ReceivablePrefillData & { + plan?: ReceivablePrefillData; + receivable?: Pick; +}; + const emit = defineEmits(['success']); -const formData = ref(); +const formData = ref>(); const getTitle = computed(() => { return formData.value?.id ? $t('ui.actionTitle.edit', ['回款']) @@ -36,6 +49,32 @@ const [Form, formApi] = useVbenForm({ showDefaultActions: false, }); +/** 构建新增回款的预填表单 */ +async function buildCreateFormData( + plan: ReceivablePrefillData, +): Promise> { + const values: Partial = { + contractId: plan?.contractId, + customerId: plan?.customerId, + }; + // 从回款计划创建时,直接继承计划的期数、金额和回款方式 + if (plan?.id) { + values.planId = plan.id; + values.price = plan.price; + values.returnType = plan.returnType; + return values; + } + // 从客户/合同详情创建时,没有计划期数,按合同剩余应回款金额预填 + if (values.customerId && values.contractId) { + const contracts = await getContractSimpleList(values.customerId); + const contract = contracts.find((item) => item.id === values.contractId); + if (contract) { + values.price = contract.totalPrice - contract.totalReceivablePrice; + } + } + return values; +} + const [Modal, modalApi] = useVbenModal({ async onConfirm() { const { valid } = await formApi.validate(); @@ -63,31 +102,26 @@ const [Modal, modalApi] = useVbenModal({ return; } // 加载数据 - const data = modalApi.getData(); + formData.value = undefined; + await formApi.resetForm(); + const data = modalApi.getData() as null | ReceivableFormModalData; if (!data) { return; } - const { receivable, plan } = data; + const { receivable } = data; + const plan = + data.plan ?? (data.customerId || data.contractId ? data : undefined); modalApi.lock(); try { - if (receivable) { + if (receivable?.id) { formData.value = await getReceivable(receivable.id!); } else if (plan) { - formData.value = plan.id - ? { - planId: plan.id, - price: plan.price, - returnType: plan.returnType, - customerId: plan.customerId, - contractId: plan.contractId, - } - : ({ - customerId: plan.customerId, - contractId: plan.contractId, - } as any); + formData.value = await buildCreateFormData(plan); + } + if (formData.value) { + // 设置到 values + await formApi.setValues(formData.value as any); } - // 设置到 values - await formApi.setValues(formData.value as any); } finally { modalApi.unlock(); } diff --git a/apps/web-antdv-next/src/views/erp/finance/payment/modules/form.vue b/apps/web-antdv-next/src/views/erp/finance/payment/modules/form.vue index 9bb8a42f1..f92292bb2 100644 --- a/apps/web-antdv-next/src/views/erp/finance/payment/modules/form.vue +++ b/apps/web-antdv-next/src/views/erp/finance/payment/modules/form.vue @@ -176,6 +176,7 @@ const [Modal, modalApi] = useVbenModal({
diff --git a/apps/web-antdv-next/src/views/erp/finance/payment/modules/purchase-in-select.vue b/apps/web-antdv-next/src/views/erp/finance/payment/modules/purchase-in-select.vue index df0c8a677..f7c35f7da 100644 --- a/apps/web-antdv-next/src/views/erp/finance/payment/modules/purchase-in-select.vue +++ b/apps/web-antdv-next/src/views/erp/finance/payment/modules/purchase-in-select.vue @@ -26,7 +26,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, gridOptions: { columns: usePurchaseInGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -95,14 +95,12 @@ defineExpose({ open: openModal }); diff --git a/apps/web-antdv-next/src/views/erp/finance/payment/modules/sale-return-select.vue b/apps/web-antdv-next/src/views/erp/finance/payment/modules/sale-return-select.vue index 7c533292e..584fbe1b2 100644 --- a/apps/web-antdv-next/src/views/erp/finance/payment/modules/sale-return-select.vue +++ b/apps/web-antdv-next/src/views/erp/finance/payment/modules/sale-return-select.vue @@ -26,7 +26,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, gridOptions: { columns: useSaleReturnGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -99,14 +99,12 @@ defineExpose({ open: openModal }); diff --git a/apps/web-antdv-next/src/views/erp/finance/receipt/modules/form.vue b/apps/web-antdv-next/src/views/erp/finance/receipt/modules/form.vue index 16c44e2cc..a5ca1669f 100644 --- a/apps/web-antdv-next/src/views/erp/finance/receipt/modules/form.vue +++ b/apps/web-antdv-next/src/views/erp/finance/receipt/modules/form.vue @@ -190,6 +190,7 @@ const [Modal, modalApi] = useVbenModal({ diff --git a/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-out-select.vue b/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-out-select.vue index fc0a9993e..d74324ec0 100644 --- a/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-out-select.vue +++ b/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-out-select.vue @@ -26,7 +26,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, gridOptions: { columns: useSaleOutGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -91,14 +91,12 @@ defineExpose({ open: openModal }); diff --git a/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-return-select.vue b/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-return-select.vue index 7f19957ce..21254baf3 100644 --- a/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-return-select.vue +++ b/apps/web-antdv-next/src/views/erp/finance/receipt/modules/sale-return-select.vue @@ -26,7 +26,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ }, gridOptions: { columns: useSaleReturnGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -95,14 +95,12 @@ defineExpose({ open: openModal }); diff --git a/apps/web-antdv-next/src/views/erp/purchase/in/modules/form.vue b/apps/web-antdv-next/src/views/erp/purchase/in/modules/form.vue index 3fe78dc94..512e60290 100644 --- a/apps/web-antdv-next/src/views/erp/purchase/in/modules/form.vue +++ b/apps/web-antdv-next/src/views/erp/purchase/in/modules/form.vue @@ -206,6 +206,7 @@ const [Modal, modalApi] = useVbenModal({ diff --git a/apps/web-antdv-next/src/views/erp/purchase/in/modules/purchase-order-select.vue b/apps/web-antdv-next/src/views/erp/purchase/in/modules/purchase-order-select.vue index 925301931..6caf8af76 100644 --- a/apps/web-antdv-next/src/views/erp/purchase/in/modules/purchase-order-select.vue +++ b/apps/web-antdv-next/src/views/erp/purchase/in/modules/purchase-order-select.vue @@ -38,7 +38,7 @@ const [Grid] = useVbenVxeGrid({ }, gridOptions: { columns: useOrderGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -108,12 +108,13 @@ function handleOk() { - + diff --git a/apps/web-antdv-next/src/views/erp/purchase/return/modules/form.vue b/apps/web-antdv-next/src/views/erp/purchase/return/modules/form.vue index 235a09147..ed349a100 100644 --- a/apps/web-antdv-next/src/views/erp/purchase/return/modules/form.vue +++ b/apps/web-antdv-next/src/views/erp/purchase/return/modules/form.vue @@ -206,6 +206,7 @@ const [Modal, modalApi] = useVbenModal({ diff --git a/apps/web-antdv-next/src/views/erp/purchase/return/modules/purchase-order-select.vue b/apps/web-antdv-next/src/views/erp/purchase/return/modules/purchase-order-select.vue index f0cdc5701..c11c1f8e5 100644 --- a/apps/web-antdv-next/src/views/erp/purchase/return/modules/purchase-order-select.vue +++ b/apps/web-antdv-next/src/views/erp/purchase/return/modules/purchase-order-select.vue @@ -38,7 +38,7 @@ const [Grid] = useVbenVxeGrid({ }, gridOptions: { columns: useOrderGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -108,12 +108,13 @@ function handleOk() { - + diff --git a/apps/web-antdv-next/src/views/erp/sale/out/modules/form.vue b/apps/web-antdv-next/src/views/erp/sale/out/modules/form.vue index 06b75feac..8df3a56ba 100644 --- a/apps/web-antdv-next/src/views/erp/sale/out/modules/form.vue +++ b/apps/web-antdv-next/src/views/erp/sale/out/modules/form.vue @@ -201,6 +201,7 @@ const [Modal, modalApi] = useVbenModal({ diff --git a/apps/web-antdv-next/src/views/erp/sale/out/modules/sale-order-select.vue b/apps/web-antdv-next/src/views/erp/sale/out/modules/sale-order-select.vue index 05ddc9d57..90ce5abad 100644 --- a/apps/web-antdv-next/src/views/erp/sale/out/modules/sale-order-select.vue +++ b/apps/web-antdv-next/src/views/erp/sale/out/modules/sale-order-select.vue @@ -38,7 +38,7 @@ const [Grid] = useVbenVxeGrid({ }, gridOptions: { columns: useOrderGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -108,12 +108,13 @@ function handleOk() { - + diff --git a/apps/web-antdv-next/src/views/erp/sale/return/modules/form.vue b/apps/web-antdv-next/src/views/erp/sale/return/modules/form.vue index 69aea9d1a..1d1f39ff0 100644 --- a/apps/web-antdv-next/src/views/erp/sale/return/modules/form.vue +++ b/apps/web-antdv-next/src/views/erp/sale/return/modules/form.vue @@ -206,6 +206,7 @@ const [Modal, modalApi] = useVbenModal({ diff --git a/apps/web-antdv-next/src/views/erp/sale/return/modules/sale-order-select.vue b/apps/web-antdv-next/src/views/erp/sale/return/modules/sale-order-select.vue index daf3f3e90..25b053483 100644 --- a/apps/web-antdv-next/src/views/erp/sale/return/modules/sale-order-select.vue +++ b/apps/web-antdv-next/src/views/erp/sale/return/modules/sale-order-select.vue @@ -38,7 +38,7 @@ const [Grid] = useVbenVxeGrid({ }, gridOptions: { columns: useOrderGridColumns(), - height: 'auto', + height: 520, keepSource: true, proxyConfig: { ajax: { @@ -108,12 +108,13 @@ function handleOk() { - +