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"
|
|
|
|
|
|
>
|
2025-11-17 19:31:42 +08:00
|
|
|
|
<el-row :gutter="24">
|
|
|
|
|
|
<el-col :span="8">
|
|
|
|
|
|
<el-form-item label="财务报告附件" prop="fileList">
|
|
|
|
|
|
<UploadFile
|
2025-11-18 14:52:37 +08:00
|
|
|
|
:fileList="formData.fileList"
|
2025-11-17 19:31:42 +08:00
|
|
|
|
:fileUploadRule="financeReportUploadRule"
|
|
|
|
|
|
@file-change="(files, type) => handleFileChange(files, type)"
|
|
|
|
|
|
@del-file="handleDelFile"
|
|
|
|
|
|
:uploadType="uploadType"
|
|
|
|
|
|
:maxFileTips="maxFileTips"
|
|
|
|
|
|
:limitUploadNum="1"
|
|
|
|
|
|
type="finance_report"
|
|
|
|
|
|
:show-file-list="true"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
2025-10-24 18:33:58 +08:00
|
|
|
|
|
2025-11-17 19:31:42 +08:00
|
|
|
|
<el-row :gutter="24" class="info-row">
|
|
|
|
|
|
<el-col :span="8" class="info-col">
|
|
|
|
|
|
<el-form-item label="文件名" prop="fileName">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="formData.fileName"
|
|
|
|
|
|
placeholder="文件上传后自动提取"
|
|
|
|
|
|
class="form-control"
|
|
|
|
|
|
maxlength="100"
|
|
|
|
|
|
readonly
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
|
|
|
|
<el-col :span="8" class="info-col">
|
|
|
|
|
|
<el-form-item label="报告年份" prop="reportYear">
|
|
|
|
|
|
<el-date-picker
|
|
|
|
|
|
v-model="formData.reportYear"
|
|
|
|
|
|
type="year"
|
|
|
|
|
|
placeholder="选择年份"
|
|
|
|
|
|
class="form-control"
|
|
|
|
|
|
value-format="yyyy"
|
|
|
|
|
|
:disabled-date="disabledFutureYear"
|
|
|
|
|
|
></el-date-picker>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
2025-10-24 18:33:58 +08:00
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import UploadFile from '@/views/common/UploadFile.vue'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'FinanceReportUpload',
|
|
|
|
|
|
components: { UploadFile },
|
|
|
|
|
|
dicts: ['identification_tag'],
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
2025-11-17 19:31:42 +08:00
|
|
|
|
uploadType: 'pdf、doc、docx',
|
2025-10-24 18:33:58 +08:00
|
|
|
|
maxFileTips: '100MB',
|
2025-11-17 19:31:42 +08:00
|
|
|
|
ocrRuleList: ['finance_report'],
|
2025-10-24 18:33:58 +08:00
|
|
|
|
fileUploadList: [],
|
|
|
|
|
|
ocrResultParams: {
|
|
|
|
|
|
"报告年份": "reportYear"
|
|
|
|
|
|
},
|
|
|
|
|
|
formData: {
|
2025-11-18 14:52:37 +08:00
|
|
|
|
fileList: [],
|
2025-10-24 18:33:58 +08:00
|
|
|
|
fileName: '',
|
2025-11-18 14:52:37 +08:00
|
|
|
|
reportYear: '',
|
|
|
|
|
|
delFileList: []
|
2025-10-24 18:33:58 +08:00
|
|
|
|
},
|
|
|
|
|
|
rules: {
|
|
|
|
|
|
fileList: [
|
|
|
|
|
|
{ required: true, message: '请上传财务报告附件', trigger: 'change' }
|
|
|
|
|
|
],
|
|
|
|
|
|
fileName: [
|
2025-11-03 13:48:00 +08:00
|
|
|
|
{ required: true, message: '文件名需等待文件上传后自动提取', trigger: 'blur' }
|
2025-10-24 18:33:58 +08:00
|
|
|
|
],
|
|
|
|
|
|
reportYear: [
|
2025-11-17 19:31:42 +08:00
|
|
|
|
{ required: true, message: '请选择报告年份', trigger: 'change' }
|
2025-10-24 18:33:58 +08:00
|
|
|
|
]
|
2025-11-18 14:52:37 +08:00
|
|
|
|
},
|
|
|
|
|
|
isReplacingFile: false // 新增:标记是否正在替换文件
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
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) {
|
2025-11-18 14:52:37 +08:00
|
|
|
|
// 财务报告文件:不手动生成uid
|
2025-11-17 19:31:42 +08:00
|
|
|
|
const financeFiles = Array.isArray(data.fileList)
|
2025-10-24 18:33:58 +08:00
|
|
|
|
? data.fileList.filter(file => file && file.businessType === 'finance_report')
|
2025-11-18 14:52:37 +08:00
|
|
|
|
.map(file => ({
|
|
|
|
|
|
name: file.name || file.fileName || '未知文件',
|
|
|
|
|
|
filePath: file.filePath,
|
|
|
|
|
|
lsFilePath: file.lsFilePath,
|
|
|
|
|
|
fileType: file.fileType || '2',
|
|
|
|
|
|
businessType: 'finance_report'
|
|
|
|
|
|
}))
|
|
|
|
|
|
: [];
|
2025-10-24 18:33:58 +08:00
|
|
|
|
|
|
|
|
|
|
this.formData = {
|
2025-11-18 14:52:37 +08:00
|
|
|
|
...(data || {}),
|
2025-11-17 19:31:42 +08:00
|
|
|
|
fileList: financeFiles,
|
|
|
|
|
|
fileName: financeFiles.length > 0 ? this.getFileName(financeFiles[0]) : '',
|
2025-11-03 13:48:00 +08:00
|
|
|
|
delFileList: []
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-17 19:31:42 +08:00
|
|
|
|
getFileName(file) {
|
2025-11-18 14:52:37 +08:00
|
|
|
|
const fullName = file.name || file.fileName || '未知文件'
|
2025-11-17 19:31:42 +08:00
|
|
|
|
const lastDotIndex = fullName.lastIndexOf('.')
|
2025-11-18 14:52:37 +08:00
|
|
|
|
return lastDotIndex > 0 ? fullName.substring(0, lastDotIndex) : fullName
|
2025-11-17 19:31:42 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getFileExt(file) {
|
|
|
|
|
|
if (!file) return ''
|
|
|
|
|
|
const fileName = file.name || file.fileName || ''
|
|
|
|
|
|
const extMatch = fileName.match(/\.([a-zA-Z0-9]+)$/)
|
|
|
|
|
|
return extMatch ? extMatch[1].toLowerCase() : ''
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-10-24 18:33:58 +08:00
|
|
|
|
handleFileChange(files, type) {
|
2025-11-18 14:52:37 +08:00
|
|
|
|
if (type === 'finance_report' && files instanceof Array) {
|
|
|
|
|
|
// 处理文件替换逻辑
|
|
|
|
|
|
if (files.length > 0 && files[0].response) { // 验证上传成功
|
|
|
|
|
|
// 标记为已完成替换
|
|
|
|
|
|
this.isReplacingFile = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 处理旧文件删除
|
|
|
|
|
|
if (this.formData.fileList.length > 0) {
|
|
|
|
|
|
const oldFile = this.formData.fileList[0];
|
|
|
|
|
|
const delPath = oldFile?.response?.fileRes?.filePath || oldFile?.filePath || null;
|
|
|
|
|
|
if (delPath && !this.formData.delFileList.includes(delPath)) {
|
|
|
|
|
|
this.formData.delFileList.push(delPath);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-03 13:48:00 +08:00
|
|
|
|
|
2025-11-18 14:52:37 +08:00
|
|
|
|
const markedFiles = files.map(file => ({
|
|
|
|
|
|
...file,
|
|
|
|
|
|
businessType: 'finance_report'
|
|
|
|
|
|
})).slice(-1);
|
|
|
|
|
|
|
|
|
|
|
|
this.formData.fileList = markedFiles;
|
|
|
|
|
|
|
|
|
|
|
|
// 提取文件名逻辑不变
|
|
|
|
|
|
if (markedFiles.length > 0) {
|
|
|
|
|
|
const originalFileName = this.getFileName(markedFiles[0])
|
|
|
|
|
|
const safeFileName = originalFileName.replace(/--+/g, '-')
|
|
|
|
|
|
this.formData.fileName = safeFileName
|
|
|
|
|
|
this.$refs.financeReportForm.validateField('fileName')
|
|
|
|
|
|
}
|
|
|
|
|
|
this.handleOcrResult(markedFiles)
|
|
|
|
|
|
} else if (!this.isReplacingFile) {
|
|
|
|
|
|
// 只有非替换操作才清空文件列表
|
|
|
|
|
|
this.formData.fileList = [];
|
|
|
|
|
|
this.formData.fileName = '';
|
|
|
|
|
|
}
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-17 19:31:42 +08:00
|
|
|
|
handleDelFile(file) {
|
2025-11-18 14:52:37 +08:00
|
|
|
|
// 标记为替换操作,保留文件列表结构等待新文件
|
|
|
|
|
|
this.isReplacingFile = true;
|
|
|
|
|
|
|
|
|
|
|
|
const delPath = file?.response?.fileRes?.filePath || file?.filePath || null;
|
|
|
|
|
|
if (delPath && !this.formData.delFileList.includes(delPath)) {
|
|
|
|
|
|
this.formData.delFileList.push(delPath);
|
2025-11-17 19:31:42 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-10-24 18:33:58 +08:00
|
|
|
|
handleOcrResult(files) {
|
|
|
|
|
|
if (!files || !Array.isArray(files) || files.length === 0) return
|
|
|
|
|
|
|
2025-11-17 19:31:42 +08:00
|
|
|
|
this.$bus.$emit('startUpload', '正在识别报告年份')
|
2025-10-24 18:33:58 +08:00
|
|
|
|
|
|
|
|
|
|
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]
|
2025-11-03 13:48:00 +08:00
|
|
|
|
if (formField === 'reportYear' && chat_res[key]) {
|
|
|
|
|
|
const year = chat_res[key].replace(/[^\d]/g, '')
|
|
|
|
|
|
this.formData[formField] = year.length === 4 ? year : ''
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
2025-11-03 13:48:00 +08:00
|
|
|
|
this.$message.success('OCR识别成功,已自动填充报告年份')
|
|
|
|
|
|
this.$refs.financeReportForm.validateField('reportYear')
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
} else {
|
2025-11-03 13:48:00 +08:00
|
|
|
|
this.$message.error(`年份识别失败: ${ocrResult.status_msg || '未知错误'}`)
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
2025-11-03 13:48:00 +08:00
|
|
|
|
this.$message.error(`处理年份结果失败: ${error.message}`)
|
2025-10-24 18:33:58 +08:00
|
|
|
|
} finally {
|
|
|
|
|
|
this.$bus.$emit('endUpload')
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-17 19:31:42 +08:00
|
|
|
|
disabledFutureYear(date) {
|
|
|
|
|
|
return date > new Date(new Date().getFullYear(), 11, 31)
|
2025-10-24 18:33:58 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
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: []
|
|
|
|
|
|
}
|
2025-11-18 14:52:37 +08:00
|
|
|
|
this.isReplacingFile = false;
|
2025-10-24 18:33:58 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
addOcrRule() {
|
|
|
|
|
|
this.ocrRuleList.forEach(item => {
|
|
|
|
|
|
this.ocrRule(item)
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
2025-11-03 13:48:00 +08:00
|
|
|
|
line-height: 1.5;
|
2025-10-24 18:33:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-form-item__label {
|
|
|
|
|
|
color: #4e5969;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
2025-11-03 13:48:00 +08:00
|
|
|
|
|
|
|
|
|
|
::v-deep .el-input.is-readonly .el-input__inner {
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
cursor: default;
|
|
|
|
|
|
}
|
2025-11-17 19:31:42 +08:00
|
|
|
|
|
|
|
|
|
|
::v-deep .upload-container {
|
|
|
|
|
|
::v-deep .el-upload-dragger {
|
|
|
|
|
|
height: 180px;
|
|
|
|
|
|
transition: border-color 0.3s;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-upload-list__item {
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-upload-list__item-name {
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
max-width: 80%;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
text-overflow: ellipsis;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-10-24 18:33:58 +08:00
|
|
|
|
</style>
|