11
This commit is contained in:
@@ -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>
|
||||
Reference in New Issue
Block a user