From 5795a7e3ec71d5ea699c2d344496471b06748127 Mon Sep 17 00:00:00 2001 From: yinq Date: Tue, 9 Jun 2026 15:10:37 +0800 Subject: [PATCH] =?UTF-8?q?1.1.62=20=E8=AE=A2=E5=8D=95=E6=BF=80=E6=B4=BB?= =?UTF-8?q?=E6=97=B6=E6=A0=A1=E9=AA=8C=E5=AE=A2=E6=88=B7=E5=BC=80=E7=A5=A8?= =?UTF-8?q?=E8=B5=84=E6=96=99=EF=BC=8C=E8=8B=A5=E4=B8=BA=E7=A9=BA=E5=88=99?= =?UTF-8?q?=E5=BC=B9=E6=A1=86=E7=BB=B4=E6=8A=A4=E5=AE=A2=E6=88=B7=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/oa/erp/contractOrder/index.ts | 13 +- src/api/oa/erp/contractOrder/types.ts | 12 ++ .../oa/erp/contractInfo/orderActivate.vue | 166 +++++++++++++++++- 3 files changed, 188 insertions(+), 3 deletions(-) diff --git a/src/api/oa/erp/contractOrder/index.ts b/src/api/oa/erp/contractOrder/index.ts index e7536be..3b404b3 100644 --- a/src/api/oa/erp/contractOrder/index.ts +++ b/src/api/oa/erp/contractOrder/index.ts @@ -1,7 +1,7 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; import { ProjectInfoVO, ProjectInfoForm, ProjectInfoQuery } from '@/api/oa/erp/projectInfo/types'; -import { ContractOrderPurchaseMaterialVO } from '@/api/oa/erp/contractOrder/types'; +import { ContractOrderPurchaseMaterialVO, PartyACustomerValidateVO } from '@/api/oa/erp/contractOrder/types'; /** * 查询合同订单列表 @@ -87,3 +87,14 @@ export const getContractOrderPurchaseMaterialList = (projectId: string | number) }); }; +/** + * 订单激活时校验甲方客户基础信息 + * @param contractId 合同ID + */ +export const validPartyACustomerForOrderActivate = (contractId: string | number): AxiosPromise => { + return request({ + url: '/oa/erp/contractOrder/validPartyACustomer/' + contractId, + method: 'get' + }); +}; + diff --git a/src/api/oa/erp/contractOrder/types.ts b/src/api/oa/erp/contractOrder/types.ts index a7e1add..2818875 100644 --- a/src/api/oa/erp/contractOrder/types.ts +++ b/src/api/oa/erp/contractOrder/types.ts @@ -10,3 +10,15 @@ export interface ContractOrderPurchaseMaterialVO { purchasedAmount?: number; unpurchasedAmount?: number; } + +/** 订单激活甲方客户信息校验结果 */ +export interface PartyACustomerValidateVO { + valid: boolean; + oneCustomerId?: string | number; + customerName?: string; + ossIdMissing?: boolean; + taxNumberMissing?: boolean; + bankAccountOpeningMissing?: boolean; + bankNumberMissing?: boolean; + message?: string; +} diff --git a/src/views/oa/erp/contractInfo/orderActivate.vue b/src/views/oa/erp/contractInfo/orderActivate.vue index 0ea9780..0f3c6f0 100644 --- a/src/views/oa/erp/contractInfo/orderActivate.vue +++ b/src/views/oa/erp/contractInfo/orderActivate.vue @@ -10,6 +10,22 @@ > 本合同由合同内容变更生成,激活后将继承原合同关联项目并作废原合同;下方关联项目已预填原合同项目。 + + + + + + + + + + + + + + + + + + + + + + + + + @@ -450,7 +501,8 @@ import { ref, reactive, computed, toRefs, getCurrentInstance, onMounted, nextTic import { useRoute, useRouter } from 'vue-router'; import type { ComponentInternalInstance } from 'vue'; import { getErpProjectInfoList, getProjectInfo } from '@/api/oa/erp/projectInfo'; -import { saveContractOrder, updateContractOrder, submitContractOrderAndFlowStart } from '@/api/oa/erp/contractOrder'; +import { saveContractOrder, updateContractOrder, submitContractOrderAndFlowStart, validPartyACustomerForOrderActivate } from '@/api/oa/erp/contractOrder'; +import type { PartyACustomerValidateVO } from '@/api/oa/erp/contractOrder/types'; import { ProjectInfoForm, ProjectInfoVO } from '@/api/oa/erp/projectInfo/types'; import { getErpProjectContractsList } from '@/api/oa/erp/projectContracts'; import { ProjectContractsVO } from '@/api/oa/erp/projectContracts/types'; @@ -470,7 +522,8 @@ import type { FormInstance } from 'element-plus'; import { getErpProjectPlanStageList, listErpProjectPlanStage } from '@/api/oa/erp/erpProjectPlanStage'; import { ErpProjectPlanStageForm, ErpProjectPlanStageQuery } from '@/api/oa/erp/erpProjectPlanStage/types'; import { listContractInfo, getContractInfo } from '@/api/oa/erp/contractInfo'; -import { getCrmCustomerInfoList } from '@/api/oa/crm/customerInfo'; +import { getCrmCustomerInfoList, getCustomerInfo, updateCustomerInfo } from '@/api/oa/crm/customerInfo'; +import type { CustomerInfoForm } from '@/api/oa/crm/customerInfo/types'; import { getBasePaymentStageList } from '@/api/oa/base/paymentStage'; import { PaymentStageVO } from '@/api/oa/base/paymentStage/types'; import { getInfo } from '@/api/login'; @@ -953,6 +1006,110 @@ const REPAYMENT_RATE_EPSILON = 0.01; /** 是否禁用表单(查看/审批模式) */ const isFormDisabled = computed(() => routeParams.value.type === 'view' || routeParams.value.type === 'approval'); +// --------------------------------------------------------------------------- +// 甲方客户信息校验与维护 +// --------------------------------------------------------------------------- +const partyACustomerValidate = ref(null); +const partyACustomerFormRef = ref(); +const partyACustomerFullData = ref(null); +const partyACustomerDialog = reactive({ + visible: false, + loading: false +}); +const partyACustomerForm = reactive({ + customerName: '', + taxNumber: '', + bankAccountOpening: '', + bankNumber: '', + ossId: undefined as string | number | undefined +}); +const partyACustomerRules = { + taxNumber: [{ required: true, message: '税号不能为空', trigger: 'blur' }], + bankAccountOpening: [{ required: true, message: '开户银行不能为空', trigger: 'blur' }], + bankNumber: [{ required: true, message: '银行账号不能为空', trigger: 'blur' }], + ossId: [{ required: true, message: '请上传开票附件', trigger: 'change' }] +}; + +const partyACustomerOssIdString = computed({ + get() { + const v = partyACustomerForm.ossId; + return v === undefined || v === null ? '' : String(v); + }, + set(val: string) { + partyACustomerForm.ossId = val || undefined; + } +}); + +const partyACustomerMissingText = computed(() => { + const result = partyACustomerValidate.value; + if (!result) return ''; + const labels: string[] = []; + if (result.ossIdMissing) labels.push('附件'); + if (result.taxNumberMissing) labels.push('税号'); + if (result.bankAccountOpeningMissing) labels.push('开户银行'); + if (result.bankNumberMissing) labels.push('银行账号'); + return labels.join('、') || '—'; +}); + +const checkPartyACustomerForOrderActivate = async () => { + const contractId = form.value.contractId || routeParams.value.contractId; + if (!contractId) { + partyACustomerValidate.value = null; + return; + } + try { + const res = await validPartyACustomerForOrderActivate(contractId); + partyACustomerValidate.value = res.data; + } catch (error) { + console.error('校验甲方客户信息失败:', error); + partyACustomerValidate.value = null; + } +}; + +const openPartyACustomerDialog = async () => { + const customerId = partyACustomerValidate.value?.oneCustomerId; + if (!customerId) { + proxy?.$modal.msgWarning('未获取到甲方客户信息'); + return; + } + try { + const res = await getCustomerInfo(customerId); + partyACustomerFullData.value = { ...(res.data || {}) }; + partyACustomerForm.customerName = res.data?.customerName || ''; + partyACustomerForm.taxNumber = res.data?.taxNumber || ''; + partyACustomerForm.bankAccountOpening = res.data?.bankAccountOpening || ''; + partyACustomerForm.bankNumber = res.data?.bankNumber || ''; + partyACustomerForm.ossId = res.data?.ossId; + partyACustomerDialog.visible = true; + } catch (error) { + console.error('加载客户信息失败:', error); + proxy?.$modal.msgError('加载客户信息失败'); + } +}; + +const submitPartyACustomerForm = () => { + partyACustomerFormRef.value?.validate(async (valid: boolean) => { + if (!valid || !partyACustomerFullData.value?.customerId) return; + partyACustomerDialog.loading = true; + try { + await updateCustomerInfo({ + ...partyACustomerFullData.value, + taxNumber: partyACustomerForm.taxNumber, + bankAccountOpening: partyACustomerForm.bankAccountOpening, + bankNumber: partyACustomerForm.bankNumber, + ossId: partyACustomerForm.ossId + }); + proxy?.$modal.msgSuccess('客户信息保存成功'); + partyACustomerDialog.visible = false; + await checkPartyACustomerForOrderActivate(); + } catch (error) { + console.error('保存客户信息失败:', error); + } finally { + partyACustomerDialog.loading = false; + } + }); +}; + /** 附件 ID 与字符串双向转换(供 FileUpload 使用) */ const ossIdString = computed({ get() { @@ -1022,6 +1179,10 @@ function isRepaymentRateTotalValid(): boolean { const submitForm = (status: string, mode: boolean) => { projectInfoFormRef.value?.validate(async (valid: boolean) => { if (!valid) return; + if (!isFormDisabled.value && partyACustomerValidate.value && !partyACustomerValidate.value.valid) { + proxy?.$modal.msgWarning('请先完善合同甲方客户信息(附件、税号、开户银行、银行账号)'); + return; + } if (!isRepaymentRateTotalValid()) { proxy?.$modal.msgWarning('回款信息预计回款比例之和必须为100%'); return; @@ -1254,6 +1415,7 @@ onMounted(async () => { console.error('获取合同信息失败:', error); } } + await checkPartyACustomerForOrderActivate(); proxy?.$modal.closeLoading(); }); });