smart-bid-web/src/views/enterpriseLibrary/qualification/components/child/QualificationFormChild.vue

421 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="qualification-form">
<el-form
:model="formData"
:rules="rules"
ref="qualificationForm"
label-width="110px"
label-position="top"
class="form-wrapper"
>
<!-- 资质证书上传 -->
<el-form-item label="资质证书附件" prop="files">
<UploadFile
ref="uploadFileComp"
:fileList="formData.files"
:fileUploadRule="qualificationUploadRule"
@file-change="handleFileChange"
@del-file="handleDelFile"
:uploadType="uploadType"
:maxFileTips="maxFileTips"
type="qualification_certificate"
/>
</el-form-item>
<!-- 证书名称 -->
<el-form-item label="证书名称" prop="certificateName">
<el-input
v-model="formData.certificateName"
placeholder="文件上传后自动提取"
class="form-control"
maxlength="50"
></el-input>
</el-form-item>
<!-- 证书编号 -->
<el-form-item label="证书编号" prop="certificateCode">
<el-input
v-model="formData.certificateCode"
placeholder="文件上传后自动提取"
class="form-control"
maxlength="32"
></el-input>
</el-form-item>
<!-- 发证日期 -->
<el-form-item label="发证日期" prop="certificateDate">
<el-date-picker
v-model="formData.certificateDate"
type="date"
placeholder="文件上传后自动提取"
value-format="yyyy-MM-dd"
class="form-control"
/>
</el-form-item>
<!-- 证书有效截止日期 -->
<el-form-item label="证书有效截止日期" prop="certificateEndDate">
<el-date-picker
v-model="formData.certificateEndDate"
type="date"
placeholder="文件上传后自动提取"
value-format="yyyy-MM-dd"
class="form-control"
/>
</el-form-item>
<!-- 发证机构 -->
<el-form-item label="发证机构" prop="certificateInstitution">
<el-input
v-model="formData.certificateInstitution"
placeholder="文件上传后自动提取"
class="form-control"
maxlength="64"
></el-input>
</el-form-item>
<!-- 资质类型 -->
<el-form-item label="资质类型" prop="qualificationType">
<el-select
v-model="formData.qualificationType"
placeholder="请选择资质类型"
clearable
class="form-control"
>
<el-option
v-for="item in qualificationTypeOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
</div>
</template>
<script>
import UploadFile from '@/views/common/UploadFile.vue'
// 工具函数:安全获取数组
const safeGetArray = (value) => Array.isArray(value) ? value : []
export default {
name: 'QualificationFormChild',
components: { UploadFile },
dicts: ['identification_tag'],
data() {
return {
uploadType: 'jpg、png、pdf',
maxFileTips: '100MB',
ocrRuleList: ['qualification_certificate'], // 资质证书OCR识别规则
fileUploadList: [],
// OCR识别结果映射关系
ocrResultParams: {
"证书名称": "certificateName",
"证书编号": "certificateCode",
"发证日期": "certificateDate",
"证书有效截止日期": "certificateEndDate",
"发证机构": "certificateInstitution"
},
formData: {
files: [], // 证书文件列表
certificateName: '',
certificateCode: '',
certificateDate: '',
certificateEndDate: '',
certificateInstitution: '',
qualificationType: '',
delFileList: [] // 被删除的文件路径列表(关键:记录替换/删除的文件)
},
qualificationTypeOptions: [],
rules: {
files: [
{ required: true, message: '请上传资质证书附件', trigger: 'change' }
],
certificateName: [
{ required: true, message: '请输入证书名称', trigger: 'blur' }
],
certificateCode: [
{ required: true, message: '请输入证书编号', trigger: 'blur' }
],
certificateDate: [
{ required: true, message: '请选择发证日期', trigger: 'change' }
],
certificateEndDate: [
{ required: true, message: '请选择有效截止日期', trigger: 'change' }
],
qualificationType: [
{ required: true, message: '请选择资质类型', trigger: 'change' }
]
}
};
},
computed: {
qualificationUploadRule() {
return this.fileUploadList[0] || {};
}
},
watch: {
'dict.type.identification_tag': {
handler(newVal) {
if (newVal && newVal.length > 0) {
this.addOcrRule();
}
},
immediate: true
}
},
methods: {
// 加载资质类型字典
loadQualificationTypeDict() {
this.getDicts('qualification_type').then(response => {
this.qualificationTypeOptions = response.data.map(item => ({
label: item.dictLabel,
value: item.dictValue
}));
}).catch(error => {
console.error('加载资质类型字典失败:', error);
});
},
// 接收父组件数据并回显(优化:确保文件路径完整)
setFormData(data) {
// 1. 过滤“资质证书类型”的文件
const qualificationFiles = safeGetArray(data.fileList)
.filter(file => file && file.businessType === 'qualification_certificate')
.map(file => ({
...file,
uid: file.uid || Date.now() + Math.random().toString(36).substr(2, 9), // 唯一ID
name: file.fileName || file.name || '未命名文件',
lsFilePath: file.lsFilePath || file.fileUrl || '', // 预览路径
filePath: file.filePath || file.uploadPath || '', // 存储路径(用于删除)
status: 'success', // 标记为已上传
// 补充上传组件所需的响应结构(删除时需要)
response: {
fileRes: {
uploadPath: file.filePath || file.uploadPath || '',
filePath: file.filePath || file.uploadPath || ''
}
}
}));
// 2. 赋值表单数据
this.formData = {
...data,
files: qualificationFiles,
delFileList: [] // 重置删除列表
};
// 3. 触发上传组件刷新
this.$nextTick(() => {
if (this.$refs.uploadFileComp?.updatePreview) {
this.$refs.uploadFileComp.updatePreview(qualificationFiles);
}
});
},
// 处理文件变更(新增/替换文件时触发)
handleFileChange(files) {
// 标记文件业务类型
const markedFiles = files.map(file => ({
...file,
businessType: 'qualification_certificate'
}));
this.formData.files = markedFiles;
// 处理替换场景:当上传新文件时,旧文件会被自动删除,需记录旧文件路径
this.handleReplaceFile(markedFiles);
// 触发OCR识别
this.handleOcrResult(markedFiles);
},
// 关键:处理文件替换场景(新文件上传时,旧文件需加入删除列表)
handleReplaceFile(newFiles) {
// 新文件的唯一标识uid集合
const newUids = newFiles.map(file => file.uid);
// 旧文件中不在新文件列表的,即为被替换的文件
const replacedFiles = this.formData.files.filter(oldFile =>
!newUids.includes(oldFile.uid)
);
// 将被替换的文件路径加入删除列表(去重)
replacedFiles.forEach(file => {
const filePath = file.response?.fileRes?.uploadPath || file.filePath;
if (filePath && !this.formData.delFileList.includes(filePath)) {
this.formData.delFileList.push(filePath);
}
});
},
// 处理文件删除(用户主动删除时触发)
handleDelFile(file) {
const filePath = file.response?.fileRes?.uploadPath || file.filePath;
if (filePath && !this.formData.delFileList.includes(filePath)) {
this.formData.delFileList.push(filePath);
}
// 删除文件后清空关联字段
if (this.formData.files.length === 0) {
this.formData.certificateName = '';
this.formData.certificateCode = '';
this.formData.certificateDate = '';
this.formData.certificateEndDate = '';
this.formData.certificateInstitution = '';
}
},
// 表单验证
validate() {
return new Promise((resolve, reject) => {
if (!this.$refs.qualificationForm) {
reject(new Error('表单实例未加载完成'));
return;
}
this.$refs.qualificationForm.validate((valid) => {
if (valid) {
resolve(this.formData); // 返回包含delFileList的完整数据
} else {
reject(new Error('资质证书信息填写不完整'));
}
});
});
},
// 重置表单(优化:确保删除列表被清空)
resetForm() {
this.$nextTick(async () => {
// 清空上传组件的文件
if (this.$refs.uploadFileComp) {
this.$refs.uploadFileComp.clearFiles();
}
// 重置表单字段
if (this.$refs.qualificationForm) {
this.$refs.qualificationForm.resetFields();
}
// 清空删除列表和文件列表
this.formData = {
...this.formData,
files: [],
delFileList: [],
certificateName: '',
certificateCode: '',
certificateDate: '',
certificateEndDate: '',
certificateInstitution: '',
qualificationType: ''
};
});
},
// 初始化OCR识别规则
addOcrRule() {
this.ocrRuleList.forEach(item => this.ocrRule(item));
},
// 获取OCR识别规则
ocrRule(type) {
const foundItem = this.dict.type.identification_tag?.find(item => item.value === type);
if (!foundItem) {
this.$message.warning(`未找到${type}的识别规则配置`);
return;
}
this.fileUploadList.push({
fileUploadType: foundItem.value,
fields_json: foundItem.raw?.remark,
suffix: 'mainDatabase'
});
},
// 处理OCR识别结果
handleOcrResult(files) {
if (!files || files.length === 0) return;
this.$bus.$emit('startUpload', '正在识别证书信息');
try {
const firstFile = files[0];
if (firstFile.response?.ocrResult) {
const ocrResult = firstFile.response.ocrResult;
if (ocrResult.status_code === 200) {
const chat_res = ocrResult.data?.chat_res;
if (chat_res && typeof chat_res === 'object') {
// 映射识别结果到表单字段
Object.keys(chat_res).forEach(key => {
const formField = this.ocrResultParams[key];
if (formField && chat_res[key]) {
this.formData[formField] = chat_res[key];
}
});
this.$message.success('OCR识别成功已自动填充证书信息');
// 触发表单验证
Object.keys(this.ocrResultParams).forEach(key => {
const formField = this.ocrResultParams[key];
this.$refs.qualificationForm.validateField(formField);
});
}
} else {
this.$message.error(`识别失败: ${ocrResult.status_msg || '未知错误'}`);
}
}
} catch (error) {
this.$message.error(`处理识别结果失败: ${error.message}`);
} finally {
this.$bus.$emit('endUpload');
}
}
},
created() {
this.loadQualificationTypeDict();
}
};
</script>
<style scoped lang="scss">
.basic-info-title {
display: flex;
align-items: center;
margin: 0 0 20px 0;
span {
margin: 0 5px;
font-size: 20px;
color: #333;
}
img {
width: 24px;
height: 24px;
object-fit: contain;
}
}
.qualification-form {
padding: 0;
}
.el-form {
margin-top: 15px;
}
.form-control {
width: 100%;
}
.el-form-item {
margin-bottom: 20px;
}
::v-deep .el-form-item__label {
color: #4e5969;
font-weight: 500;
}
.form-wrapper {
padding: 24px;
background: #fff;
}
</style>