diff --git a/src/views/contract/launch/components/ContractPartyPlaceholderModal.vue b/src/views/contract/launch/components/ContractPartyPlaceholderModal.vue index 55e66d9..38c8816 100644 --- a/src/views/contract/launch/components/ContractPartyPlaceholderModal.vue +++ b/src/views/contract/launch/components/ContractPartyPlaceholderModal.vue @@ -1353,6 +1353,7 @@ function createPerformancePlan() { planMoney: "", planSubjectCode: "", planSubjectName: "", + executorUnitId: null, planDetail: "", }; } @@ -2229,7 +2230,7 @@ function buildLaunchRecord() { selfCode: detailState.value.selfCode || "", mainContractCode: detailState.value.mainContractCode || "", dateType: detailState.value.dateType || "0", - isAddit: 2, + isAddit: detailState.value.mainContractCode ? 1 : 2, isElectron: detailState.value.isElectron || "1", paymentDirection: detailState.value.paymentDirection || "0", isMajorContract: detailState.value.isMajorContract ? 1 : 0, @@ -2267,6 +2268,7 @@ function buildLaunchRecord() { planMoney: item.planMoney, planSubjectCode: item.planSubjectCode, planSubjectName: item.planSubjectName, + executorUnitId: item.executorUnitId || null, planDetail: item.planDetail, planStatus: "0", })), diff --git a/src/views/contract/launch/components/ContractTemplateFillDemoModal.vue b/src/views/contract/launch/components/ContractTemplateFillDemoModal.vue index d0e910f..6cd0027 100644 --- a/src/views/contract/launch/components/ContractTemplateFillDemoModal.vue +++ b/src/views/contract/launch/components/ContractTemplateFillDemoModal.vue @@ -879,8 +879,54 @@ const launchFieldList = computed(() => { })); }); +/** 模板字段中与合同主信息同名的直接映射字段 */ +const CONTRACT_DIRECT_FIELDS = [ + 'contractName', 'contractCode', 'contractType', + 'effectiveStart', 'effectiveEnd', + 'paymentMethod', 'primaryContent', 'amountExplain', + 'businessRemark', 'contractSubject', +] + function getLaunchFieldValue(fieldKey) { - return contractDetailState.value.templateFieldValues?.[fieldKey] ?? ""; + // 1. 优先返回用户在"模板信息录入"中自定义的值 + const templateVal = contractDetailState.value.templateFieldValues?.[fieldKey] + if (templateVal !== undefined && templateVal !== null && templateVal !== '') { + return templateVal + } + + // 2. 若字段与合同主信息直接同名,自动带入主信息的值 + if (CONTRACT_DIRECT_FIELDS.includes(fieldKey)) { + return contractDetailState.value[fieldKey] ?? '' + } + + // 3. 特殊计算字段 + if (fieldKey === 'contractAmountDisplay') { + return formatContractAmount(contractDetailState.value.contractAmount) + } + if (fieldKey === 'effectivePeriod') { + return [contractDetailState.value.effectiveStart, contractDetailState.value.effectiveEnd].filter(Boolean).join(' 至 ') + } + if (fieldKey === 'templateLabel') { + return activeTemplate.value?.templateName || '' + } + if (fieldKey === 'signDate') { + return contractDetailState.value.signDate || dayjs().format('YYYY-MM-DD') + } + if (fieldKey === 'counterpartySummary') { + return getPartySummary(contractDetailState.value.partyState) + } + if (fieldKey === 'attachmentSummary') { + return formatFileSummary(contractDetailState.value.otherAttachmentList) + } + + // 4. 合同方名称字段 + if (/^party[A-F]Name$/.test(fieldKey)) { + const roleCode = fieldKey.replace('party', '').replace('Name', '') + const party = getPartyList(contractDetailState.value.partyState).find((item) => item.roleCode === roleCode) + return party?.companyName ?? '' + } + + return '' } function setLaunchFieldValue(fieldKey, value) { diff --git a/src/views/contract/launch/index.vue b/src/views/contract/launch/index.vue index ca3726b..5019064 100644 --- a/src/views/contract/launch/index.vue +++ b/src/views/contract/launch/index.vue @@ -106,12 +106,12 @@
查看 复制 - 变更 + 变更 编辑 提交法务 审批记录 测试通过 - 在线签订 + 在线签订 下载签署文件 上传已签署版本 测试签署完成 @@ -294,6 +294,11 @@ function canSubmit(row) { return ["draft", "rejected"].includes(row.status); } +function canChange(row) { + // 变更/补充协议:仅已完成/待采集/待归档的合同允许基于它发起变更 + return ["completed", "pending_archive", "pending_collect"].includes(row.status); +} + function canMockApprove(row) { return row.status === "reviewing"; } @@ -303,7 +308,8 @@ function canMockReject(row) { } function canOnlineSign(row) { - return ["pending_sign", "signing", "completed"].includes(row.status); + // 签署中也可以再次调起签署(续签/补签),已完成则不能再签 + return ["pending_sign", "signing"].includes(row.status); } function canMockFinishSign(row) { @@ -421,39 +427,69 @@ function handleEdit(row) { } function handleCopy(row) { - copyLaunchDraft(row.id).then((res) => { - if (!isSuccessResponse(res) || !getDataResult(res)) { - message.error(getResponseMessage(res, "复制合同失败")); - return; - } - const copiedRecord = getDataResult(res); - message.success("合同已复制为新草稿,请继续完善后保存"); - getList(); - contractModalRef.value?.showModal(copiedRecord, "edit"); + Modal.confirm({ + title: "确认复制合同", + content: `将复制合同【${row.contractName}】生成一份新草稿,复制后自动进入编辑状态。`, + okText: "确认复制", + cancelText: "取消", + onOk: () => + copyLaunchDraft(row.id).then((res) => { + if (!isSuccessResponse(res) || !getDataResult(res)) { + message.error(getResponseMessage(res, "复制合同失败")); + return; + } + const copiedRecord = getDataResult(res); + message.success("合同已复制为新草稿,请继续完善后保存"); + getList(); + contractModalRef.value?.showModal(copiedRecord, "edit"); + }), + icon: null, }); } function handleChange(row) { - createLaunchChangeDraft(row.id).then((res) => { - if (!isSuccessResponse(res) || !getDataResult(res)) { - message.error(getResponseMessage(res, "发起变更合同失败")); - return; - } - const changedRecord = getDataResult(res); - message.success("已生成变更草稿,并自动关联主合同编码"); - getList(); - contractModalRef.value?.showModal(changedRecord, "edit"); + Modal.confirm({ + title: "确认发起变更合同", + content: h("div", [ + h("p", `将基于【${row.contractName}】发起一份变更/补充协议,`), + h("p", "自动关联主合同编码,生成新草稿。原合同不受影响。"), + ]), + okText: "确认变更", + cancelText: "取消", + onOk: () => + createLaunchChangeDraft(row.id).then((res) => { + if (!isSuccessResponse(res) || !getDataResult(res)) { + message.error(getResponseMessage(res, "发起变更合同失败")); + return; + } + const changedRecord = getDataResult(res); + message.success("已生成变更草稿,并自动关联主合同编码"); + getList(); + contractModalRef.value?.showModal(changedRecord, "edit"); + }), + icon: null, }); } function handleSubmit(row) { - submitLaunchRecord(row.id).then((res) => { - if (!isSuccessResponse(res)) { - message.error(getResponseMessage(res, "提交法务失败")); - return; - } - message.success("已提交法务,当前为测试环境,后续可由法务系统真实审批"); - getList(); + Modal.confirm({ + title: "确认提交法务审批", + content: h("div", [ + h("p", `确定将合同【${row.contractName}】提交法务系统审批吗?`), + h("p", { style: { color: "#999", fontSize: "12px" } }, "提交后合同进入「审批中」状态,审批完成前不可编辑。"), + ]), + okText: "确认提交", + cancelText: "取消", + onOk: () => + submitLaunchRecord(row.id).then((res) => { + if (!isSuccessResponse(res)) { + message.error(getResponseMessage(res, "提交法务失败")); + return; + } + message.success("已提交法务,等待审批"); + getList(); + }), + icon: null, }); } @@ -481,43 +517,70 @@ function handleViewApprove(row) { } function handleMockApprove(row) { - mockApproveLaunch(row.id, {}).then((res) => { - if (!isSuccessResponse(res)) { - message.error(getResponseMessage(res, "模拟审批通过失败")); - return; - } - message.success("测试审批通过完成,合同已流转到待签署"); - getList(); + Modal.confirm({ + title: "测试操作:模拟审批通过", + content: `模拟法务审批通过合同【${row.contractName}】,状态将变为「待签署」。`, + okText: "确认模拟", + cancelText: "取消", + onOk: () => + mockApproveLaunch(row.id, {}).then((res) => { + if (!isSuccessResponse(res)) { + message.error(getResponseMessage(res, "模拟审批通过失败")); + return; + } + message.success("测试审批通过完成,合同已流转到待签署"); + getList(); + }), + icon: null, }); } function handleMockReject(row) { - mockRejectLaunch(row.id, {}).then((res) => { - if (!isSuccessResponse(res)) { - message.error(getResponseMessage(res, "模拟审批驳回失败")); - return; - } - message.success("测试审批驳回完成,合同已流转到审批驳回"); - getList(); + Modal.confirm({ + title: "测试操作:模拟审批驳回", + content: h("div", [ + h("p", `模拟法务审批驳回合同【${row.contractName}】,状态将回到「已驳回」。`), + h("p", { style: { color: "#999", fontSize: "12px" } }, "驳回后可重新编辑再提交。"), + ]), + okText: "确认驳回", + cancelText: "取消", + onOk: () => + mockRejectLaunch(row.id, {}).then((res) => { + if (!isSuccessResponse(res)) { + message.error(getResponseMessage(res, "模拟审批驳回失败")); + return; + } + message.success("测试审批驳回完成,合同已流转到审批驳回"); + getList(); + }), + icon: null, }); } function handleMockFinishSign(row) { - finishLaunchSeal(row.id, { - sealContractId: row.sealContractId || `TEST-SEAL-${row.id}`, - sealContractStatus: 2000, - signedFileName: `${row.contractName || "合同"}-测试已签署.pdf`, - signedFilePath: row.contractTextFilePath || `mock-signed/${row.id}.pdf`, - signedFileType: "pdf", - signedFileSize: row.contractTextFileSize || null, - signedOfflineReason: "测试按钮模拟签署完成,真实签章接入后可删除此按钮", - }).then((res) => { - if (!isSuccessResponse(res)) { - message.error(getResponseMessage(res, "测试签署完成失败")); - return; - } - message.success("测试签署完成,合同已流转到待采集"); - getList(); + Modal.confirm({ + title: "测试操作:模拟签署完成", + content: `模拟合同【${row.contractName}】签署完成,状态将变为「待采集」。`, + okText: "确认模拟", + cancelText: "取消", + onOk: () => + finishLaunchSeal(row.id, { + sealContractId: row.sealContractId || `TEST-SEAL-${row.id}`, + sealContractStatus: 2000, + signedFileName: `${row.contractName || "合同"}-测试已签署.pdf`, + signedFilePath: row.contractTextFilePath || `mock-signed/${row.id}.pdf`, + signedFileType: "pdf", + signedFileSize: row.contractTextFileSize || null, + signedOfflineReason: "测试按钮模拟签署完成,真实签章接入后可删除此按钮", + }).then((res) => { + if (!isSuccessResponse(res)) { + message.error(getResponseMessage(res, "测试签署完成失败")); + return; + } + message.success("测试签署完成,合同已流转到待采集"); + getList(); + }), + icon: null, }); } @@ -581,24 +644,43 @@ function handleModalSave(payload) { } function handleMockCollect(row) { - mockCollectLaunch(row.id).then((res) => { - if (!isSuccessResponse(res)) { - message.error(getResponseMessage(res, "模拟合同采集失败")); - return; - } - message.success("测试合同采集完成,合同已流转到待归档"); - getList(); + Modal.confirm({ + title: "测试操作:模拟合同采集", + content: `模拟将合同【${row.contractName}】信息采集同步至法务系统,状态将变为「待归档」。`, + okText: "确认模拟", + cancelText: "取消", + onOk: () => + mockCollectLaunch(row.id).then((res) => { + if (!isSuccessResponse(res)) { + message.error(getResponseMessage(res, "模拟合同采集失败")); + return; + } + message.success("测试合同采集完成,合同已流转到待归档"); + getList(); + }), + icon: null, }); } function handleArchive(row) { - archiveLaunch(row.id, {}).then((res) => { - if (!isSuccessResponse(res)) { - message.error(getResponseMessage(res, "测试归档失败")); - return; - } - message.success("测试归档完成,合同已流转到已完成"); - getList(); + Modal.confirm({ + title: "确认归档合同", + content: h("div", [ + h("p", `确认将合同【${row.contractName}】归档?`), + h("p", { style: { color: "#999", fontSize: "12px" } }, "归档后合同进入「已完成」状态,全生命周期结束。"), + ]), + okText: "确认归档", + cancelText: "取消", + onOk: () => + archiveLaunch(row.id, {}).then((res) => { + if (!isSuccessResponse(res)) { + message.error(getResponseMessage(res, "测试归档失败")); + return; + } + message.success("测试归档完成,合同已流转到已完成"); + getList(); + }), + icon: null, }); }