350 lines
10 KiB
Vue
350 lines
10 KiB
Vue
<template>
|
||
<a-modal
|
||
v-model:open="visible"
|
||
title="合同采集"
|
||
width="800px"
|
||
:mask-closable="false"
|
||
:confirm-loading="submitting"
|
||
ok-text="确认采集"
|
||
cancel-text="取消"
|
||
@ok="handleSubmit"
|
||
centered
|
||
>
|
||
<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>
|