11
This commit is contained in:
@@ -121,6 +121,14 @@ export function mockCollectLaunch(id) {
|
||||
});
|
||||
}
|
||||
|
||||
export function saveContractCollectInfo(id, data) {
|
||||
return request({
|
||||
url: `/contract/launch/${id}/collect/save`,
|
||||
method: "post",
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export function archiveLaunch(id, data = {}) {
|
||||
return request({
|
||||
url: `/contract/launch/${id}/archive`,
|
||||
|
||||
@@ -0,0 +1,348 @@
|
||||
<template>
|
||||
<a-modal
|
||||
v-model:open="visible"
|
||||
title="合同采集"
|
||||
width="800px"
|
||||
:mask-closable="false"
|
||||
:confirm-loading="submitting"
|
||||
ok-text="确认采集"
|
||||
cancel-text="取消"
|
||||
@ok="handleSubmit"
|
||||
>
|
||||
<div class="collect-body">
|
||||
<a-descriptions :column="2" size="small" bordered class="contract-brief">
|
||||
<a-descriptions-item label="合同名称">
|
||||
{{ row?.contractName || "-" }}
|
||||
</a-descriptions-item>
|
||||
<a-descriptions-item label="合同编码">
|
||||
{{ row?.contractCode || "-" }}
|
||||
</a-descriptions-item>
|
||||
</a-descriptions>
|
||||
|
||||
<a-divider style="margin: 16px 0" />
|
||||
|
||||
<a-form layout="vertical">
|
||||
<div class="section-header">
|
||||
<span class="section-title-icon">📜</span>
|
||||
用印信息(c_seal)
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<a-form-item label="是否用印" required class="field-half">
|
||||
<a-radio-group v-model:value="formState.sealIsSeal">
|
||||
<a-radio value="1">是</a-radio>
|
||||
<a-radio value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item
|
||||
label="用印类型"
|
||||
class="field-half"
|
||||
>
|
||||
<a-input
|
||||
:value="sealTypeDisplay"
|
||||
readonly
|
||||
placeholder="沿用合同签订方式"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<a-form-item label="审批是否一致" required class="field-half">
|
||||
<a-radio-group v-model:value="formState.sealApproveSame">
|
||||
<a-radio value="1">是</a-radio>
|
||||
<a-radio value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
<a-form-item label="用印数量" class="field-half">
|
||||
<a-input-number
|
||||
v-model:value="formState.sealQuantity"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
:disabled="formState.sealIsSeal !== '1'"
|
||||
style="width: 100%"
|
||||
placeholder="默认1份"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<a-form-item label="用印时间" required class="field-half">
|
||||
<a-date-picker
|
||||
v-model:value="formState.sealDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
:disabled="formState.sealIsSeal !== '1'"
|
||||
style="width: 100%"
|
||||
placeholder="用印日期"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="section-header" style="margin-top: 20px">
|
||||
<span class="section-title-icon">✍️</span>
|
||||
签订信息(c_sign)
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<a-form-item label="签订日期" required class="field-half">
|
||||
<a-date-picker
|
||||
v-model:value="formState.signDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
placeholder="请选择签订日期"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item label="合同生效日期" required class="field-half">
|
||||
<a-date-picker
|
||||
v-model:value="formState.activeDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
placeholder="必填,且需在合同期限内"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="field-row">
|
||||
<a-form-item label="合同履行执行人" required class="field-half">
|
||||
<a-input
|
||||
v-model:value="formState.executorAccount"
|
||||
placeholder="履行执行人账号"
|
||||
/>
|
||||
</a-form-item>
|
||||
</div>
|
||||
|
||||
<div class="section-header" style="margin-top: 20px">
|
||||
<span class="section-title-icon">📎</span>
|
||||
合同签署文本
|
||||
</div>
|
||||
<a-form-item label="签署文件" required>
|
||||
<a-upload-dragger
|
||||
:file-list="signedFileList"
|
||||
:before-upload="handleSignedFileUpload"
|
||||
:show-upload-list="{ showRemoveIcon: true }"
|
||||
@remove="handleRemoveSignedFile"
|
||||
>
|
||||
<div class="upload-text">
|
||||
点击或拖拽上传签署完成的合同文件
|
||||
</div>
|
||||
<div class="upload-hint">
|
||||
支持 .pdf 格式,当前仅本地上传到业务系统文件服务
|
||||
</div>
|
||||
</a-upload-dragger>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
import {
|
||||
getLaunchDetail,
|
||||
saveContractCollectInfo,
|
||||
mockCollectLaunch,
|
||||
uploadLaunchFile,
|
||||
} from "@/api/launch.js";
|
||||
|
||||
const SUCCESS_CODE = "0000";
|
||||
|
||||
const visible = ref(false);
|
||||
const submitting = ref(false);
|
||||
const row = ref(null);
|
||||
const signedFileList = ref([]);
|
||||
|
||||
const formState = reactive({
|
||||
sealIsSeal: "1",
|
||||
sealApproveSame: "1",
|
||||
sealQuantity: 1,
|
||||
sealDate: "",
|
||||
signDate: "",
|
||||
activeDate: "",
|
||||
executorAccount: "",
|
||||
signedFileName: "",
|
||||
signedFilePath: "",
|
||||
signedFileType: "",
|
||||
signedFileSize: null,
|
||||
});
|
||||
|
||||
const emit = defineEmits(["done"]);
|
||||
|
||||
const sealTypeDisplay = computed(() => {
|
||||
return row.value?.sealTypeLabel || row.value?.sealType || "公章";
|
||||
});
|
||||
|
||||
function resetForm(record) {
|
||||
formState.sealIsSeal = record.sealIsSeal || "1";
|
||||
formState.sealApproveSame = record.sealApproveSame || "1";
|
||||
formState.sealQuantity = record.sealQuantity || 1;
|
||||
formState.sealDate = record.sealDate || "";
|
||||
formState.signDate = record.signDate || "";
|
||||
formState.activeDate = record.activeDate || "";
|
||||
formState.executorAccount = record.executorAccount || record.initiator || "";
|
||||
formState.signedFileName = record.signedFileName || "";
|
||||
formState.signedFilePath = record.signedFilePath || "";
|
||||
formState.signedFileType = record.signedFileType || "";
|
||||
formState.signedFileSize = record.signedFileSize || null;
|
||||
if (record.signedFileName) {
|
||||
signedFileList.value = [
|
||||
{
|
||||
uid: "signed_existing",
|
||||
name: record.signedFileName,
|
||||
status: "done",
|
||||
size: record.signedFileSize || 0,
|
||||
},
|
||||
];
|
||||
} else {
|
||||
signedFileList.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
async function showModal(record) {
|
||||
row.value = record || {};
|
||||
resetForm(record || {});
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
function buildKey(prefix) {
|
||||
return `${prefix}_${Date.now()}_${Math.random().toString(16).slice(2, 8)}`;
|
||||
}
|
||||
|
||||
async function handleSignedFileUpload(file) {
|
||||
const formData = new FormData();
|
||||
formData.append("file", file);
|
||||
try {
|
||||
const res = await uploadLaunchFile(formData);
|
||||
if (String(res?.code || "") !== SUCCESS_CODE) {
|
||||
message.error(res?.message || res?.msg || "签署文件上传失败");
|
||||
return false;
|
||||
}
|
||||
const fileItem = {
|
||||
uid: buildKey("signed"),
|
||||
name: file.name,
|
||||
status: "done",
|
||||
size: file.size,
|
||||
fileName: file.name,
|
||||
filePath: res?.result || "",
|
||||
fileType: file.name.split(".").pop()?.toLowerCase() || "",
|
||||
fileSize: file.size,
|
||||
};
|
||||
signedFileList.value = [fileItem];
|
||||
formState.signedFileName = fileItem.fileName;
|
||||
formState.signedFilePath = fileItem.filePath;
|
||||
formState.signedFileType = fileItem.fileType;
|
||||
formState.signedFileSize = fileItem.fileSize;
|
||||
message.success(`已上传签署文件:${file.name}`);
|
||||
} catch (error) {
|
||||
message.error("签署文件上传失败");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function handleRemoveSignedFile() {
|
||||
signedFileList.value = [];
|
||||
formState.signedFileName = "";
|
||||
formState.signedFilePath = "";
|
||||
formState.signedFileType = "";
|
||||
formState.signedFileSize = null;
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
if (!formState.sealIsSeal) return "请选择是否用印";
|
||||
if (!formState.sealApproveSame) return "请选择审批是否一致";
|
||||
if (formState.sealIsSeal === "1") {
|
||||
if (!formState.sealDate) return "请选择用印时间";
|
||||
if (!formState.sealQuantity || formState.sealQuantity < 1)
|
||||
return "请填写用印数量";
|
||||
}
|
||||
if (!formState.signDate) return "请选择签订日期";
|
||||
if (!formState.activeDate) return "请选择合同生效日期";
|
||||
if (!formState.executorAccount?.trim()) return "请填写合同履行执行人";
|
||||
if (!signedFileList.value.length) return "请上传签署完成的合同文件";
|
||||
return "";
|
||||
}
|
||||
|
||||
async function handleSubmit() {
|
||||
const validateMessage = validateForm();
|
||||
if (validateMessage) {
|
||||
message.warning(validateMessage);
|
||||
return;
|
||||
}
|
||||
submitting.value = true;
|
||||
try {
|
||||
// 1. 保存采集信息到合同记录
|
||||
const saveRes = await saveContractCollectInfo(row.value.id, {
|
||||
sealIsSeal: formState.sealIsSeal,
|
||||
sealApproveSame: formState.sealApproveSame,
|
||||
sealQuantity: formState.sealIsSeal === "1" ? formState.sealQuantity : null,
|
||||
sealDate: formState.sealIsSeal === "1" ? formState.sealDate : null,
|
||||
signDate: formState.signDate,
|
||||
activeDate: formState.activeDate,
|
||||
executorAccount: formState.executorAccount?.trim(),
|
||||
signedFileName: formState.signedFileName,
|
||||
signedFilePath: formState.signedFilePath,
|
||||
signedFileType: formState.signedFileType,
|
||||
signedFileSize: formState.signedFileSize,
|
||||
});
|
||||
if (String(saveRes?.code || "") !== SUCCESS_CODE) {
|
||||
message.error(saveRes?.message || "保存采集信息失败");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 触发采集流转(push to 法务)
|
||||
const collectRes = await mockCollectLaunch(row.value.id);
|
||||
if (String(collectRes?.code || "") !== SUCCESS_CODE) {
|
||||
message.error(collectRes?.message || "合同采集失败");
|
||||
return;
|
||||
}
|
||||
message.success("合同采集完成,已流转到待归档");
|
||||
visible.value = false;
|
||||
emit("done");
|
||||
} catch (error) {
|
||||
message.error("合同采集失败");
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({ showModal });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.collect-body {
|
||||
max-height: 72vh;
|
||||
overflow-y: auto;
|
||||
padding-right: 4px;
|
||||
}
|
||||
.contract-brief {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.field-row {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
.field-half {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
.section-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin: 14px 0 12px;
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
color: #1f2937;
|
||||
}
|
||||
.section-title-icon {
|
||||
font-size: 16px;
|
||||
}
|
||||
.upload-text {
|
||||
color: #374151;
|
||||
font-size: 14px;
|
||||
}
|
||||
.upload-hint {
|
||||
color: #9ca3af;
|
||||
font-size: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
@@ -691,39 +691,7 @@
|
||||
placeholder="选填,用于应收账款提醒"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="签订日期">
|
||||
<a-date-picker
|
||||
v-model:value="detailState.signDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
placeholder="签署完成前需补齐"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="用印时间">
|
||||
<a-date-picker
|
||||
v-model:value="detailState.sealDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
placeholder="签署完成前需补齐"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="合同生效日期">
|
||||
<a-date-picker
|
||||
v-model:value="detailState.activeDate"
|
||||
value-format="YYYY-MM-DD"
|
||||
style="width: 100%"
|
||||
placeholder="必填,且必须在合同期限范围内"
|
||||
/>
|
||||
</a-form-item>
|
||||
<a-form-item class="tight-item" label="用印数量">
|
||||
<a-input-number
|
||||
v-model:value="detailState.sealQuantity"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
style="width: 100%"
|
||||
placeholder="默认1份"
|
||||
/>
|
||||
</a-form-item>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="boolean-grid">
|
||||
@@ -794,20 +762,7 @@
|
||||
<a-radio value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
<div class="boolean-row">
|
||||
<span>是否用印</span>
|
||||
<a-radio-group v-model:value="detailState.sealIsSeal">
|
||||
<a-radio value="1">是</a-radio>
|
||||
<a-radio value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
<div class="boolean-row">
|
||||
<span>审批是否一致</span>
|
||||
<a-radio-group v-model:value="detailState.sealApproveSame">
|
||||
<a-radio value="1">是</a-radio>
|
||||
<a-radio value="0">否</a-radio>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="extra-amount-section">
|
||||
@@ -866,7 +821,7 @@
|
||||
:data-source="detailState.performancePlans"
|
||||
:pagination="false"
|
||||
size="small"
|
||||
:scroll="{ x: 820 }"
|
||||
:scroll="{ x: 780 }"
|
||||
row-key="id"
|
||||
class="plan-table"
|
||||
>
|
||||
@@ -926,27 +881,20 @@
|
||||
/>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column
|
||||
title="所属主体编码"
|
||||
key="planSubjectCode"
|
||||
width="160"
|
||||
>
|
||||
<template #default="{ record }">
|
||||
<a-input
|
||||
v-model:value="record.planSubjectCode"
|
||||
placeholder="所属主体机构编码"
|
||||
/>
|
||||
</template>
|
||||
</a-table-column>
|
||||
<a-table-column
|
||||
title="所属主体"
|
||||
key="planSubjectName"
|
||||
width="180"
|
||||
width="200"
|
||||
>
|
||||
<template #default="{ record }">
|
||||
<a-input
|
||||
<a-select
|
||||
v-model:value="record.planSubjectName"
|
||||
placeholder="所属主体名称"
|
||||
:options="ourParties.map(p => ({ label: `${p.companyName} (${p.subjectCode})`, value: p.companyName, subjectCode: p.subjectCode }))"
|
||||
allow-clear
|
||||
placeholder="从已选我方主体中选择"
|
||||
:disabled="!ourParties.length"
|
||||
style="width: 100%"
|
||||
@change="(value, option) => { record.planSubjectCode = option?.subjectCode || ''; }"
|
||||
/>
|
||||
</template>
|
||||
</a-table-column>
|
||||
@@ -1471,12 +1419,6 @@ function createContractFormData() {
|
||||
yfkAmount: 0,
|
||||
bzjAmount: 0,
|
||||
performancePlans: [],
|
||||
signDate: "",
|
||||
sealDate: "",
|
||||
activeDate: "",
|
||||
sealQuantity: 1,
|
||||
sealIsSeal: "1",
|
||||
sealApproveSame: "1",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1534,11 +1476,8 @@ function copyContractFormData(data = {}) {
|
||||
: null
|
||||
: null;
|
||||
} else if (
|
||||
key === "signDate" ||
|
||||
key === "sealDate" ||
|
||||
key === "invoiceDate" ||
|
||||
key === "receiveDate" ||
|
||||
key === "activeDate"
|
||||
key === "receiveDate"
|
||||
) {
|
||||
form[key] = source[key] ? String(source[key]).slice(0, 10) : form[key];
|
||||
} else if (key === "assistDept") {
|
||||
@@ -2026,7 +1965,7 @@ function handleBodyConfigSave(payload = {}) {
|
||||
syncUploadLists();
|
||||
|
||||
if (modalMode.value === "edit" && detailState.value.id) {
|
||||
const errorMessage = validateState();
|
||||
const errorMessage = validateDraft();
|
||||
if (errorMessage) {
|
||||
message.success(
|
||||
"合同正文配置已保存到当前页面,请继续完善主信息后再保存合同草稿。",
|
||||
@@ -2064,7 +2003,85 @@ function removePerformancePlan(id) {
|
||||
detailState.value.performancePlans.filter((item) => item.id !== id);
|
||||
}
|
||||
|
||||
function validateState() {
|
||||
/** 草稿保存校验(宽松):仅校验必填核心字段 */
|
||||
function validateDraft() {
|
||||
if (
|
||||
!ourParties.value.length ||
|
||||
ourParties.value.some((party) => !party.companyName?.trim())
|
||||
)
|
||||
return "请确认我方信息";
|
||||
if (
|
||||
currentSelfSubjectCode.value &&
|
||||
!ourParties.value.some(
|
||||
(party) =>
|
||||
String(party.subjectCode || "").trim() === currentSelfSubjectCode.value,
|
||||
)
|
||||
) {
|
||||
return "当前登录主体必须包含在我方主体中";
|
||||
}
|
||||
if (
|
||||
isSingleAgreementChecked.value &&
|
||||
currentSelfSubjectCode.value &&
|
||||
ourParties.value.some(
|
||||
(party) =>
|
||||
String(party.subjectCode || "").trim() !== currentSelfSubjectCode.value,
|
||||
)
|
||||
) {
|
||||
return "单方协议仅允许使用当前登录主体";
|
||||
}
|
||||
if (!isSingleAgreementChecked.value && !counterpartyParties.value.length)
|
||||
return "请至少添加一个相对方";
|
||||
if (
|
||||
!isSingleAgreementChecked.value &&
|
||||
counterpartyParties.value.some((party) => !party.companyName?.trim())
|
||||
)
|
||||
return "请选择相对方";
|
||||
if (!detailState.value.contractName?.trim()) return "请填写合同名称";
|
||||
if (!detailState.value.contractTypeCode) return "请选择合同类型";
|
||||
if (
|
||||
detailState.value.contractPeriodType === "0" &&
|
||||
(!detailState.value.effectiveStart || !detailState.value.effectiveEnd)
|
||||
)
|
||||
return "请选择固定期限起止日期";
|
||||
if (
|
||||
detailState.value.contractPeriodType === "1" &&
|
||||
!detailState.value.periodExplain?.trim()
|
||||
)
|
||||
return "请填写期限说明";
|
||||
if (!detailState.value.contractBodyFileName?.trim())
|
||||
return "请先配置合同正文";
|
||||
if (
|
||||
!isSingleAgreementChecked.value &&
|
||||
requiresAuthAttachment.value &&
|
||||
!(detailState.value.authAttachmentList || []).length
|
||||
)
|
||||
return "请上传授权委托书附件";
|
||||
// 履行计划:草稿保存时即要求至少一条且字段完整
|
||||
if (!(detailState.value.performancePlans || []).length)
|
||||
return "请至少添加一条履行计划";
|
||||
for (const plan of detailState.value.performancePlans || []) {
|
||||
if (!plan.planMatter?.trim()) return "请填写履行计划的履行事项";
|
||||
if (!plan.planWhere?.trim()) return "请填写履行计划的履约条件";
|
||||
if (!plan.planTime) return "请选择履行计划的节点日期";
|
||||
if (
|
||||
plan.planDay === null ||
|
||||
plan.planDay === undefined ||
|
||||
plan.planDay === ""
|
||||
)
|
||||
return "请填写履行计划的提醒提前天数";
|
||||
if (
|
||||
!["0", "3"].includes(detailState.value.valuationMode) &&
|
||||
(plan.planMoney === null ||
|
||||
plan.planMoney === undefined ||
|
||||
plan.planMoney === "")
|
||||
)
|
||||
return "请填写履行计划的款项金额";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/** 提交法务校验(严格):补全 pushContract 所有必填项 + 履行计划 */
|
||||
function validateSubmit() {
|
||||
if (
|
||||
!ourParties.value.length ||
|
||||
ourParties.value.some((party) => !party.companyName?.trim())
|
||||
@@ -2143,6 +2160,13 @@ function validateState() {
|
||||
detailState.value.needAmendments === ""
|
||||
)
|
||||
return "请选择是否需修订条款";
|
||||
// 以下为 pushContract 必填项补充校验(接口文档要求)
|
||||
if (detailState.value.isMajorContract === undefined || detailState.value.isMajorContract === null || detailState.value.isMajorContract === "")
|
||||
return "请选择是否重大合同";
|
||||
if (detailState.value.isPublicTender === undefined || detailState.value.isPublicTender === null)
|
||||
return "请选择是否公开招标";
|
||||
if (detailState.value.isInvolveHongKongMacaoTaiwan === undefined || detailState.value.isInvolveHongKongMacaoTaiwan === null)
|
||||
return "请选择是否涉及港澳台";
|
||||
if (!detailState.value.paymentDirection) return "请选择收支方向";
|
||||
if (!detailState.value.contractTypeCode) return "请选择合同类型编码";
|
||||
if (!detailState.value.executorAccount?.trim()) return "请填写合同执行人";
|
||||
@@ -2180,7 +2204,7 @@ function validateState() {
|
||||
}
|
||||
|
||||
function handleSave() {
|
||||
const errorMessage = validateState();
|
||||
const errorMessage = validateDraft();
|
||||
if (errorMessage) {
|
||||
message.warning(errorMessage);
|
||||
return;
|
||||
@@ -2359,14 +2383,8 @@ function buildLaunchRecord() {
|
||||
contractTextFilePath: detailState.value.contractBodyFilePath || "",
|
||||
contractTextFileType: detailState.value.contractBodyFileType || "docx",
|
||||
contractTextFileSize: detailState.value.contractBodyFileSize || null,
|
||||
signDate: formatDateTimeValue(detailState.value.signDate),
|
||||
sealDate: formatDateTimeValue(detailState.value.sealDate),
|
||||
invoiceDate: formatDateTimeValue(detailState.value.invoiceDate),
|
||||
receiveDate: formatDateTimeValue(detailState.value.receiveDate),
|
||||
activeDate: formatDateTimeValue(detailState.value.activeDate),
|
||||
sealQuantity: detailState.value.sealQuantity,
|
||||
sealIsSeal: detailState.value.sealIsSeal || "1",
|
||||
sealApproveSame: detailState.value.sealApproveSame || "1",
|
||||
templateFieldValuesJson: JSON.stringify(
|
||||
detailState.value.templateFieldValues || {},
|
||||
),
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
}}</a
|
||||
>
|
||||
<a v-if="canCollect(row)" @click="handleMockCollect(row)">{{
|
||||
isSingleAgreementRecord(row) ? "测试生效" : "测试采集"
|
||||
isSingleAgreementRecord(row) ? "测试生效" : "合同采集"
|
||||
}}</a>
|
||||
<a v-if="canArchive(row)" @click="handleArchive(row)">{{
|
||||
isSingleAgreementRecord(row) ? "办结" : "归档"
|
||||
@@ -278,6 +278,10 @@
|
||||
ref="contractModalRef"
|
||||
@save="handleModalSave"
|
||||
/>
|
||||
<ContractCollectModal
|
||||
ref="contractCollectModalRef"
|
||||
@done="handleCollectDone"
|
||||
/>
|
||||
<MixedSignModal
|
||||
ref="mixedSignModalRef"
|
||||
@business-updated="handleSignBusinessUpdated"
|
||||
@@ -303,6 +307,7 @@ import {
|
||||
} from "@ant-design/icons-vue";
|
||||
import { Input, message, Modal } from "ant-design-vue";
|
||||
import ContractPartyPlaceholderModal from "./components/ContractPartyPlaceholderModal.vue";
|
||||
import ContractCollectModal from "./components/ContractCollectModal.vue";
|
||||
import MixedSignModal from "./components/mixedSignModal.vue";
|
||||
import UploadSignedModal from "./components/UploadSignedModal.vue";
|
||||
import ContractArchiveModal from "./components/ContractArchiveModal.vue";
|
||||
@@ -318,7 +323,6 @@ import {
|
||||
getLaunchDetail,
|
||||
getLawApproveCallbackSample,
|
||||
mockApproveLaunch,
|
||||
mockCollectLaunch,
|
||||
mockRejectLaunch,
|
||||
finishLaunchSeal,
|
||||
queryApproveViewUrl,
|
||||
@@ -347,6 +351,7 @@ const pageWrapperRef = ref(null);
|
||||
const tableRef = ref(null);
|
||||
const toolbarRef = ref(null);
|
||||
const contractModalRef = ref(null);
|
||||
const contractCollectModalRef = ref(null);
|
||||
const mixedSignModalRef = ref(null);
|
||||
const uploadSignedModalRef = ref(null);
|
||||
const contractArchiveModalRef = ref(null);
|
||||
@@ -699,6 +704,41 @@ function handleChange(row) {
|
||||
|
||||
function handleSubmit(row) {
|
||||
const singleAgreement = isSingleAgreementRecord(row);
|
||||
// 非单方协议:提交法务前校验必填项完整性
|
||||
if (!singleAgreement) {
|
||||
return getLaunchDetail(row.id).then((res) => {
|
||||
if (!isSuccessResponse(res) || !getDataResult(res)) {
|
||||
message.error(getResponseMessage(res, "获取合同详情失败"));
|
||||
return;
|
||||
}
|
||||
const detail = getDataResult(res);
|
||||
const missingFields = [];
|
||||
if (!detail.contractTypeCode) missingFields.push("合同类型");
|
||||
if (!detail.valuationMode) missingFields.push("计价方式");
|
||||
if (!detail.currencyName) missingFields.push("币种");
|
||||
if (!detail.sealType) missingFields.push("签订方式");
|
||||
if (!detail.isElectron) missingFields.push("签署方式");
|
||||
if (!detail.paymentDirection) missingFields.push("收支方向");
|
||||
if (!detail.textSource) missingFields.push("文本来源");
|
||||
if (!detail.contractSource) missingFields.push("合同来源");
|
||||
if (!detail.executorAccount) missingFields.push("合同执行人");
|
||||
if (detail.isMajorContract === null || detail.isMajorContract === undefined) missingFields.push("是否重大合同");
|
||||
if (detail.isOpenBidding === null || detail.isOpenBidding === undefined) missingFields.push("是否公开招标");
|
||||
if (detail.isSgat === null || detail.isSgat === undefined) missingFields.push("是否涉及港澳台");
|
||||
if (!detail.performancePlans || !detail.performancePlans.length) missingFields.push("履行计划");
|
||||
if (!detail.contractTextFileName) missingFields.push("合同正文");
|
||||
if (missingFields.length) {
|
||||
message.warning(`以下必填项不完整,请先在编辑草稿中补全后再提交:\n${missingFields.join("、")}`);
|
||||
return;
|
||||
}
|
||||
showSubmitConfirm(row, detail, false);
|
||||
});
|
||||
}
|
||||
// 单方协议:直接提交内部审批
|
||||
showSubmitConfirm(row, null, true);
|
||||
}
|
||||
|
||||
function showSubmitConfirm(row, detail, singleAgreement) {
|
||||
Modal.confirm({
|
||||
title: singleAgreement ? "确认提交内部审批" : "确认提交法务审批",
|
||||
content: h("div", [
|
||||
@@ -1032,24 +1072,19 @@ function handleModalSave(payload) {
|
||||
}
|
||||
|
||||
function handleMockCollect(row) {
|
||||
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,
|
||||
getLaunchDetail(row.id).then((res) => {
|
||||
if (!isSuccessResponse(res) || !getDataResult(res)) {
|
||||
message.error(getResponseMessage(res, "获取合同详情失败"));
|
||||
return;
|
||||
}
|
||||
contractCollectModalRef.value?.showModal(getDataResult(res));
|
||||
});
|
||||
}
|
||||
|
||||
function handleCollectDone() {
|
||||
getList();
|
||||
}
|
||||
|
||||
function handleArchive(row) {
|
||||
getLaunchDetail(row.id).then((res) => {
|
||||
if (!isSuccessResponse(res) || !getDataResult(res)) {
|
||||
|
||||
Reference in New Issue
Block a user