From 488f43859fe900bbf8e89ed21b5905cce5bf2183 Mon Sep 17 00:00:00 2001
From: zhouxiaofeng <2946471396@qq.com>
Date: Mon, 8 Jun 2026 10:03:15 +0800
Subject: [PATCH] =?UTF-8?q?=E6=8C=89=E9=92=AE=E6=B7=BB=E5=8A=A0modal?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../ContractPartyPlaceholderModal.vue | 4 +-
.../ContractTemplateFillDemoModal.vue | 48 +++-
src/views/contract/launch/index.vue | 224 ++++++++++++------
3 files changed, 203 insertions(+), 73 deletions(-)
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,
});
}