From 564653e1e0d40a9a3145bed8e2331827ec8c5d5d Mon Sep 17 00:00:00 2001 From: yinq Date: Tue, 28 Apr 2026 16:11:30 +0800 Subject: [PATCH] =?UTF-8?q?1.1.27=201=E3=80=81=E5=90=88=E5=90=8C=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=97=B6=E6=B7=BB=E5=8A=A0=E5=8B=BE=E9=80=89=E6=A1=86?= =?UTF-8?q?=20=E5=B7=B2=E7=94=9F=E6=95=88=E5=AE=A2=E6=88=B7=E8=AE=A2?= =?UTF-8?q?=E5=8D=95=EF=BC=8C=E8=8B=A5=E5=8B=BE=E9=80=89=E5=90=8E=E6=8A=8A?= =?UTF-8?q?=E5=90=88=E5=90=8C=E9=99=84=E4=BB=B6=E8=87=AA=E5=8A=A8=E5=B8=A6?= =?UTF-8?q?=E5=88=B0=E7=BB=88=E7=89=88=E5=90=88=E5=90=8C=E9=99=84=E4=BB=B6?= =?UTF-8?q?=E3=80=82=202=E3=80=81=E5=90=88=E5=90=8C=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=97=B6=E6=B7=BB=E5=8A=A0=20=E5=90=88=E5=90=8C=E5=B1=9E?= =?UTF-8?q?=E5=9C=B0=E6=A0=87=E8=AF=86=E3=80=81=E5=90=88=E5=90=8C=E5=B1=9E?= =?UTF-8?q?=E5=9C=B0=E5=9B=BD=E5=AE=B6/=E5=9C=B0=E5=8C=BA=E3=80=81?= =?UTF-8?q?=E7=BB=93=E7=AE=97=E5=B8=81=E7=A7=8D=EF=BC=8C=E5=90=88=E5=90=8C?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=8F=B0=E8=B4=A6=E6=B7=BB=E5=8A=A0=E6=AD=A4?= =?UTF-8?q?=E4=B8=89=E4=B8=AA=E5=AD=97=E6=AE=B5=E3=80=82=E5=90=88=E5=90=8C?= =?UTF-8?q?=E5=B1=9E=E5=9C=B0=E6=A0=87=E8=AF=86=E6=98=AF=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E7=9A=84=E7=A8=8E=E7=8E=87=E9=BB=98=E8=AE=A40=E3=80=82=203?= =?UTF-8?q?=E3=80=81=E5=90=88=E5=90=8C=E6=BF=80=E6=B4=BB=E6=97=B6=E9=9D=9E?= =?UTF-8?q?=E5=A4=A7=E9=99=86=E5=90=88=E5=90=8C=E6=B7=BB=E5=8A=A0=E5=AF=B9?= =?UTF-8?q?=E4=BA=BA=E6=B0=91=E5=B8=81=E6=B1=87=E7=8E=87=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/oa/erp/contractInfo/types.ts | 75 +++++++++ src/api/oa/erp/contractLedgerReport/index.ts | 3 + src/views/oa/erp/contractInfo/edit.vue | 158 ++++++++++++++++-- src/views/oa/erp/contractInfo/index.vue | 33 +++- .../oa/erp/contractInfo/orderActivate.vue | 49 ++++++ .../oa/erp/contractLedgerReport/index.vue | 19 ++- 6 files changed, 319 insertions(+), 18 deletions(-) diff --git a/src/api/oa/erp/contractInfo/types.ts b/src/api/oa/erp/contractInfo/types.ts index 61e5674..3ca2f64 100644 --- a/src/api/oa/erp/contractInfo/types.ts +++ b/src/api/oa/erp/contractInfo/types.ts @@ -49,6 +49,31 @@ export interface ContractInfoVO { */ contractDate: string; + /** + * 合同属地标识(1中国大陆 2其他) + */ + contractTerritorialFlag?: string; + + /** + * 合同属地国家/地区(字典) + */ + contractTerritorialCountry?: string; + + /** + * 结算币种(CNY/USD/EUR) + */ + settlementCurrency?: string; + + /** + * 对人民币汇率 + */ + rmbExchangeRate?: number; + + /** + * 已生效客户订单标识(1是 0否) + */ + effectiveCustomerOrderFlag?: string; + /** * 合同总价 */ @@ -307,6 +332,31 @@ export interface ContractInfoForm extends BaseEntity { */ contractDate?: string; + /** + * 合同属地标识(1中国大陆 2其他) + */ + contractTerritorialFlag?: string; + + /** + * 合同属地国家/地区(字典) + */ + contractTerritorialCountry?: string; + + /** + * 结算币种(CNY/USD/EUR) + */ + settlementCurrency?: string; + + /** + * 对人民币汇率 + */ + rmbExchangeRate?: number; + + /** + * 已生效客户订单标识(1是 0否) + */ + effectiveCustomerOrderFlag?: string; + /** * 合同总价 */ @@ -563,6 +613,31 @@ export interface ContractInfoQuery extends PageQuery { */ contractDate?: string; + /** + * 合同属地标识(1中国大陆 2其他) + */ + contractTerritorialFlag?: string; + + /** + * 合同属地国家/地区(字典) + */ + contractTerritorialCountry?: string; + + /** + * 结算币种(CNY/USD/EUR) + */ + settlementCurrency?: string; + + /** + * 对人民币汇率 + */ + rmbExchangeRate?: number; + + /** + * 已生效客户订单标识(1是 0否) + */ + effectiveCustomerOrderFlag?: string; + /** * 合同总价 */ diff --git a/src/api/oa/erp/contractLedgerReport/index.ts b/src/api/oa/erp/contractLedgerReport/index.ts index a867bef..c3688e6 100644 --- a/src/api/oa/erp/contractLedgerReport/index.ts +++ b/src/api/oa/erp/contractLedgerReport/index.ts @@ -18,6 +18,9 @@ export interface ContractLedgerReportVO { externalContractCode: string; customerContractCode: string; contractDate: string; + contractTerritorialFlag: string; + contractTerritorialCountry: string; + settlementCurrency: string; orderContractCode: string; projectContractCode: string; customerName: string; diff --git a/src/views/oa/erp/contractInfo/edit.vue b/src/views/oa/erp/contractInfo/edit.vue index c24547e..d3e3f54 100644 --- a/src/views/oa/erp/contractInfo/edit.vue +++ b/src/views/oa/erp/contractInfo/edit.vue @@ -116,6 +116,46 @@ + + +
+ + {{ dict.label }} + + + + +
+
+
+ + + + + + + + - - +
+ +
+ +
+
+ + 已生效客户订单 + +
+ (无需盖章或签字,即刻生效的客户订单) +
+
+
@@ -400,7 +457,7 @@ @@ -723,7 +780,10 @@ const { contract_status, material_flag, contract_template_flag, - is_framework_contract + is_framework_contract, + contract_territorial_flag, + country_region, + currency_type } = toRefs( proxy?.useDict( 'contract_category', @@ -734,7 +794,10 @@ const { 'contract_status', 'material_flag', 'contract_template_flag', - 'is_framework_contract' + 'is_framework_contract', + 'contract_territorial_flag', + 'country_region', + 'currency_type' ) ); @@ -858,6 +921,7 @@ const materialDialog = reactive({ visible: false, title: '' }); +const editingMaterialIndex = ref(null); // 合同物料表单数据 const initMaterialFormData: ContractMaterialForm = { @@ -1011,6 +1075,11 @@ const initFormData: ContractInfoFormEx = { businessDirection: undefined, contractDeptId: undefined, contractDate: undefined, + contractTerritorialFlag: '1', + contractTerritorialCountry: undefined, + settlementCurrency: 'CNY', + rmbExchangeRate: 1, + effectiveCustomerOrderFlag: '0', totalPrice: 0, oneCustomerId: undefined, oneRepresent: undefined, @@ -1058,6 +1127,33 @@ const data = reactive<{ form: ContractInfoFormEx; rules: any }>({ contractName: [{ required: true, message: '合同名称不能为空', trigger: 'blur' }], businessDirection: [{ required: true, message: '业务方向不能为空', trigger: 'blur' }], contractManagerId: [{ required: true, message: '合同负责人不能为空', trigger: 'blur' }], + contractTerritorialFlag: [{ required: true, message: '合同属地标识不能为空', trigger: 'change' }], + contractTerritorialCountry: [ + { + validator: (_rule: any, _value: any, callback: (err?: Error) => void) => { + if (form.value.contractTerritorialFlag === '2' && !form.value.contractTerritorialCountry) { + callback(new Error('合同属地标识为“其他”时,国家/地区不能为空')); + return; + } + callback(); + }, + trigger: 'change' + } + ], + settlementCurrency: [{ required: true, message: '结算币种不能为空', trigger: 'change' }], + rmbExchangeRate: [{ required: true, message: '对人民币汇率不能为空', trigger: 'blur' }], + ossId: [ + { + validator: (_rule: any, _value: any, callback: (err?: Error) => void) => { + if (form.value.effectiveCustomerOrderFlag === '1' && !form.value.ossId) { + callback(new Error('已生效客户订单必须上传附件')); + return; + } + callback(); + }, + trigger: 'change' + } + ], contractTemplateFlag: [{ required: true, message: '合同模板标识不能为空', trigger: 'blur' }], isFrameworkContract: [{ required: true, message: '请选择关联框架合同', trigger: 'change' }], frameworkValidPeriod: [ @@ -1130,6 +1226,30 @@ watch( } ); +watch( + () => form.value.contractTerritorialFlag, + (newVal) => { + // 合同属地标识为“其他”时,新增物料默认税率为0 + initMaterialFormData.taxRate = newVal === '2' ? 0 : 13; + if (newVal === '2') { + materialForm.value.taxRate = 0; + } else { + form.value.contractTerritorialCountry = undefined; + } + }, + { immediate: true } +); + +watch( + () => form.value.settlementCurrency, + (newVal) => { + if (newVal === 'CNY') { + form.value.rmbExchangeRate = 1 as any; + } + }, + { immediate: true } +); + // 生成合同编号 const generateContractCode = async () => { if (isCodeGenerated.value) return; // 如果已经生成过,直接返回 @@ -1292,14 +1412,16 @@ const submitOss = () => { // 新增物料(新增合同时也可添加,不依赖contractId) const handleAddMaterial = () => { resetMaterialForm(); + editingMaterialIndex.value = null; materialForm.value.contractId = form.value.contractId; materialDialog.visible = true; materialDialog.title = '新增合同物料'; }; // 编辑物料 -const handleEditMaterial = (row: ContractMaterialVO) => { +const handleEditMaterial = (row: ContractMaterialVO, rowIndex: number) => { resetMaterialForm(); + editingMaterialIndex.value = rowIndex; materialForm.value = { ...row }; materialDialog.visible = true; materialDialog.title = '编辑合同物料'; @@ -1333,11 +1455,14 @@ const handleDeleteMaterial = async (row: ContractMaterialVO) => { const resetMaterialForm = () => { materialForm.value = { ...initMaterialFormData }; materialFormRef.value?.resetFields(); + // 合同属地标识=2 物料税率默认0 + materialForm.value.taxRate = form.value.contractTerritorialFlag === '2' ? 0 : 13; }; // 取消物料编辑 const cancelMaterial = () => { resetMaterialForm(); + editingMaterialIndex.value = null; materialDialog.visible = false; }; @@ -1490,7 +1615,11 @@ const submitMaterialForm = () => { unitName: unitName }; - if (materialForm.value.contractMaterialId) { + const editIndex = editingMaterialIndex.value; + if (editIndex !== null && editIndex >= 0 && editIndex < (form.value as any).contractMaterialList.length) { + // 优先按行索引回写,兼容框架合同带出但无主键ID的物料 + (form.value as any).contractMaterialList[editIndex] = materialData; + } else if (materialForm.value.contractMaterialId) { // 编辑模式:更新现有物料 const index = (form.value as any).contractMaterialList.findIndex( (item: any) => item.contractMaterialId === materialForm.value.contractMaterialId @@ -1511,6 +1640,7 @@ const submitMaterialForm = () => { calculateTotalPrice(); proxy?.$modal.msgSuccess('操作成功'); + editingMaterialIndex.value = null; materialDialog.visible = false; } }); diff --git a/src/views/oa/erp/contractInfo/index.vue b/src/views/oa/erp/contractInfo/index.vue index d9af35f..ea7fe2e 100644 --- a/src/views/oa/erp/contractInfo/index.vue +++ b/src/views/oa/erp/contractInfo/index.vue @@ -195,6 +195,22 @@ {{ parseTime(scope.row.frameworkValidPeriod, '{y}-{m}-{d}') }} + + + + + + + + + +