smart-bid-web/src/views/enterpriseLibrary/finance/components/child/FinanceReportUpload.vue

278 lines
7.3 KiB
Vue
Raw Normal View History

2025-10-24 18:33:58 +08:00
<template>
<div>
<div class="basic-info-title">
<img src="@/assets/enterpriseLibrary/basic-info.png" alt="财务报告">
<span>财务报告</span>
</div>
<el-form
:model="formData"
:rules="rules"
ref="financeReportForm"
label-width="110px"
label-position="top"
>
<!-- 财务报告上传 -->
<el-form-item label="财务报告附件" prop="fileList">
<UploadFile
:fileList="formData.fileList"
:fileUploadRule="financeReportUploadRule"
@file-change="(files, type) => handleFileChange(files, type)"
@del-file="handleDelFile"
:uploadType="uploadType"
:maxFileTips="maxFileTips"
type="finance_report"
/>
</el-form-item>
<!-- 文件名 -->
<el-form-item label="文件名" prop="fileName">
<el-input
v-model="formData.fileName"
placeholder="请输入文件名OCR识别后自动填充"
class="form-control"
maxlength="100"
></el-input>
</el-form-item>
<!-- 报告年份 -->
<el-form-item label="报告年份" prop="reportYear">
<el-input
v-model="formData.reportYear"
placeholder="请输入报告年份4位数字OCR识别后自动填充"
class="form-control"
maxlength="4"
></el-input>
</el-form-item>
</el-form>
</div>
</template>
<script>
import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'FinanceReportUpload',
components: { UploadFile },
dicts: ['identification_tag'],
data() {
return {
uploadType: 'pdf,doc,docx',
maxFileTips: '100MB',
ocrRuleList: ['finance_report'],
fileUploadList: [],
ocrResultParams: {
"文件名": "fileName",
"报告年份": "reportYear"
},
formData: {
fileList: [], // 带businessType标记的文件列表
fileName: '',
reportYear: '',
delFileList: [] // 记录删除的文件路径
},
rules: {
fileList: [
{ required: true, message: '请上传财务报告附件', trigger: 'change' }
],
fileName: [
{ required: true, message: '请输入文件名', trigger: 'blur' }
],
reportYear: [
{ required: true, message: '请输入报告年份', trigger: 'blur' },
{ pattern: /^\d{4}$/, message: '请输入有效的年份4位数字', trigger: 'blur' }
]
}
}
},
computed: {
financeReportUploadRule() {
return this.fileUploadList[0]
}
},
watch: {
'dict.type.identification_tag': {
handler(newVal) {
if (newVal && newVal.length > 0) {
this.addOcrRule()
}
},
immediate: true
}
},
methods: {
// 接收父组件数据并回显(适配编辑场景)
setFormData(data) {
// 筛选出财务报告类型的文件businessType=finance_report
const reportFiles = Array.isArray(data.fileList)
? data.fileList.filter(file => file && file.businessType === 'finance_report')
: []
this.formData = {
...data,
fileList: reportFiles,
delFileList: [] // 清空删除记录,避免编辑时携带旧数据
}
},
// 处理文件变更
handleFileChange(files, type) {
if (type === 'finance_report') {
// 为新上传文件添加businessType标记
const markedFiles = files.map(file => ({
...file,
businessType: 'finance_report'
}))
this.formData.fileList = markedFiles
this.handleOcrResult(markedFiles)
}
},
// 处理OCR识别结果
handleOcrResult(files) {
if (!files || !Array.isArray(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]) {
// 处理年份字段确保是4位数字
if (formField === 'reportYear') {
const year = chat_res[key].replace(/[^\d]/g, '')
this.formData[formField] = year.length === 4 ? year : ''
} else {
this.formData[formField] = chat_res[key]
}
}
})
this.$message.success('OCR识别成功已自动填充财务报告信息')
this.$refs.financeReportForm.validate()
}
} else {
this.$message.error(`OCR识别失败: ${ocrResult.status_msg || '未知错误'}`)
}
}
} catch (error) {
this.$message.error(`处理识别结果失败: ${error.message}`)
} finally {
// 结束全局上传动画
this.$bus.$emit('endUpload')
}
},
// 处理文件删除
handleDelFile(file) {
const filePath = file.response?.fileRes?.uploadPath || file.filePath
if (filePath && !this.formData.delFileList.includes(filePath)) {
this.formData.delFileList.push(filePath)
}
},
// 表单验证
validate() {
return new Promise((resolve, reject) => {
if (!this.$refs.financeReportForm) {
reject(new Error('表单实例未加载完成'))
return
}
this.$refs.financeReportForm.validate((valid) => {
if (valid) {
resolve(this.formData)
} else {
reject(new Error('财务报告信息填写不完整'))
}
})
})
},
// 重置表单
resetForm() {
if (this.$refs.financeReportForm) {
this.$refs.financeReportForm.resetFields()
}
this.formData = {
fileList: [],
fileName: '',
reportYear: '',
delFileList: []
}
},
// 初始化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
}
const item = {
fileUploadType: foundItem.value,
fields_json: foundItem.raw?.remark,
suffix: 'mainDatabase'
}
this.fileUploadList.push(item)
}
}
}
</script>
<style scoped lang="scss">
.basic-info-title {
display: flex;
align-items: center;
margin: 10px 0;
span {
margin: 0 5px;
font-size: 20px;
}
img {
width: 24px;
height: 24px;
object-fit: contain;
}
}
.el-form {
margin-top: 15px;
padding: 0 15px;
}
.form-control {
width: 100%;
}
.el-form-item {
margin-bottom: 20px;
}
.upload-tip {
color: #909399;
font-size: 12px;
margin-top: 5px;
}
::v-deep .el-form-item__label {
color: #4e5969;
font-weight: 500;
}
</style>