前端代码提交

This commit is contained in:
cwchen 2025-10-22 16:13:42 +08:00
parent 7c31fc85a9
commit 2328ab1158
8 changed files with 331 additions and 76 deletions

View File

@ -10,4 +10,16 @@ export function uploadSmallFileByOcr(data) {
},
data: data
})
}
// 上传小文件---5M以上,使用OCR识别
export function uploadLargeFileByOcr(data) {
return request({
url: '/smartBid/commonUpload/uploadLargeFileByOcr',
method: 'post',
headers: {
'Content-Type': 'multipart/form-data'
},
data: data
})
}

View File

@ -226,3 +226,16 @@ export function getNormalPath(p) {
export function blobValidate(data) {
return data.type !== 'application/json'
}
// 将年月日格式转换为yyyy-MM-dd格式
export function formatDate(dateStr) {
if (!dateStr) return '';
// 提取年、月、日
const match = dateStr.match(/(\d{4})年(\d{1,2})月(\d{1,2})日/);
if (!match) return dateStr;
const year = match[1];
const month = match[2].padStart(2, '0'); // 月份补零
const day = match[3].padStart(2, '0'); // 日期补零
return `${year}-${month}-${day}`;
}

View File

@ -41,7 +41,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 30000,
timeout: 60000 * 2,
})
// 判断是否为二进制数据File/Blob

View File

@ -43,7 +43,7 @@
</template>
<script>
import { uploadSmallFileByOcr } from '@/api/common/uploadFile.js'
import { uploadSmallFileByOcr,uploadLargeFileByOcr } from '@/api/common/uploadFile.js'
export default {
name: 'UploadFile',
props: {
@ -70,7 +70,11 @@ export default {
autoUpload: {
type: Boolean,
default: true
}
},
type: {
type: String,
default: ''
},
},
data() {
return {
@ -79,7 +83,8 @@ export default {
previewImageName: '',
previewFileName: '',
previewFileType: '',
isUploading: false //
isUploading: false, //
defaultFileSize: 1024 * 1024 * 5, // 5MB 5MB
}
},
methods: {
@ -194,14 +199,14 @@ export default {
this.updateFileStatus(file.uid, 'uploading', text, null, 0);
try {
this.$bus.$emit('startUpload', text);
const res = await uploadSmallFileByOcr(formData);
const res = this.defaultFileSize < file.size ? await uploadLargeFileByOcr(formData) : await uploadSmallFileByOcr(formData);
console.log('上传成功:', res);
this.$bus.$emit('endUpload');
// 100
this.updateFileStatus(file.uid, 'success', '', res.data, 100);
console.log('上传成功后的文件列表:', this.files);
//
this.$emit('file-change', this.getCurrentFiles());
this.$emit('file-change', this.getCurrentFiles(),this.type);
} catch (err) {
this.$bus.$emit('endUpload');
//
@ -225,7 +230,7 @@ export default {
this.clearPreview();
//
this.$emit('file-change', this.getCurrentFiles());
this.$emit('file-change', this.getCurrentFiles(),this.type);
}
},
@ -307,9 +312,12 @@ export default {
//
handleExceed(files, fileList) {
console.log('文件超出限制处理');
console.log('文件超出限制处理',files,fileList);
//
if (files.length > 0) {
//
this.$emit('del-file', fileList[0]);
//
this.files = [];
@ -381,7 +389,8 @@ export default {
} else {
this.clearPreview();
}
//
this.$emit('del-file', file);
//
this.$emit('file-change', this.getCurrentFiles());
},

View File

@ -1,6 +1,6 @@
<!-- 企业主体库表单 -->
<template>
<div class="app-container" :class="{ 'no-pointer-events': showUploadAnimation }">
<div class="app-container" :class="{ 'no-pointer-events': showUploadAnimation || showSaveAnimation }">
<!-- 全局上传动画 -->
<div v-if="showUploadAnimation" class="global-upload-animation">
<div class="animation-mask"></div>
@ -11,9 +11,19 @@
</div>
</div>
<!-- 保存动画 -->
<div v-if="showSaveAnimation" class="global-upload-animation">
<div class="animation-mask"></div>
<div class="animation-content">
<div class="spinner"></div>
<div class="animation-text">数据上传中</div>
<div class="animation-subtext">请稍后正在保存数据...</div>
</div>
</div>
<div class="content-header">
<el-button class="reset-btn" @click="handleClose()">返回</el-button>
<el-button class="search-btn" @click="handleSave()">保存</el-button>
<el-button class="search-btn" :loading="isSaving" @click="handleSave()">保存</el-button>
</div>
<div class="content-body">
<el-row :gutter="24" class="content-row">
@ -52,11 +62,15 @@ export default {
id: decryptWithSM4(this.$route.query.id),
type: decryptWithSM4(this.$route.query.type),
showUploadAnimation: false,
showSaveAnimation: false, //
uploadQueue: 0, //
animationText: '识别中'
animationText: '识别中',
isSaving: false // loading
}
},
methods: {
//
handleClose() {
const obj = { path: "/enterpriseLibrary/enterprise" }
@ -64,6 +78,14 @@ export default {
},
//
async handleSave() {
//
if (this.isSaving) {
return
}
this.isSaving = true
this.showSaveAnimation = true
try {
//
const [basicInfoData, legalPersonData, accountData] = await Promise.all([
@ -73,29 +95,57 @@ export default {
])
//
const formData = {
let formData = {
...basicInfoData,
...legalPersonData,
...accountData
...accountData,
allFiles: [...basicInfoData.fileList, ...legalPersonData.fileList, ...legalPersonData.fileList2, ...accountData.fileList],
allFiles: [...basicInfoData.delFileList, ...legalPersonData.delFileList, ...accountData.delFileList]
}
console.log('所有表单校验通过,完整数据:', formData)
//
// await this.saveEnterprise(formData)
//
delete formData.fileList;
delete formData.delFileList;
let allFiles = formData.allFiles.map(file => {
return {
...file.obj,
}
});
formData.allFiles = allFiles;
//
await this.saveEnterprise(formData)
this.$message.success('保存成功')
//
this.handleClose()
} catch (error) {
// console.error(':', error)
this.$message.error(error.message || '请完善表单信息')
console.error('保存失败:', error)
this.$message.error(error.message || '保存失败,请重试')
} finally {
//
this.isSaving = false
this.showSaveAnimation = false
}
},
//
async saveEnterprise(formData) {
//
return new Promise((resolve, reject) => {
setTimeout(() => {
//
// 使 reject(new Error(''))
resolve({ code: 200, message: '保存成功' })
}, 2000) // 2
})
},
//
handleStartUpload(data) {
this.animationText = data
this.uploadQueue++
this.showUploadAnimation = true
},
//
handleEndUpload(data) {
@ -107,8 +157,6 @@ export default {
if (this.uploadQueue === 0) {
this.showUploadAnimation = false
}
}
},
mounted() {
@ -117,7 +165,6 @@ export default {
//
this.$bus.$on('endUpload', this.handleEndUpload)
},
beforeDestroy() {
//
@ -126,8 +173,10 @@ export default {
//
this.showUploadAnimation = false
this.showSaveAnimation = false
this.uploadQueue = 0
this.animationText = '识别中'
this.isSaving = false
}
}
</script>
@ -144,18 +193,10 @@ export default {
&.no-pointer-events {
pointer-events: none;
//
// overflow-y: auto;
//
* {
pointer-events: none;
}
//
// ::-webkit-scrollbar {
// pointer-events: auto;
// }
}
}
@ -246,19 +287,6 @@ export default {
}
}
// 使body
// mounted beforeDestroy /
.global-upload-animation-active {
.app-container {
pointer-events: none !important;
user-select: none !important;
* {
pointer-events: none !important;
}
}
}
.content-body {
margin-top: 20px;
}
@ -306,6 +334,12 @@ export default {
background: #4A8BFF;
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
}
// loading
&.is-loading {
opacity: 0.7;
pointer-events: none;
}
}
.reset-btn {

View File

@ -6,13 +6,14 @@
</div>
<el-form :model="form" :rules="rules" ref="accountOpeningCertificateForm" label-width="110px" label-position="top">
<el-form-item label="开户许可证" prop="fileList">
<UploadFile :fileList="form.fileList"/>
<UploadFile :fileList="form.fileList" :fileUploadRule="fileUploadRule"
@del-file="handleDelFile" @file-change="handleFileChange" type="account_opening_license"/>
</el-form-item>
<el-form-item label="开户银行" prop="openingBank">
<el-input v-model="form.openingBank" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.openingBank" placeholder="自动提取" clearable show-word-limit maxlength="64"></el-input>
</el-form-item>
<el-form-item label="开户账号" prop="openingAccount">
<el-input v-model="form.openingAccount" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.openingAccount" placeholder="自动提取" clearable show-word-limit maxlength="32"></el-input>
</el-form-item>
</el-form>
@ -24,12 +25,23 @@ import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'AccountOpeningCertificate',
components:{UploadFile},
dicts: ['identification_tag'],
data() {
return {
form: {
fileList:[],
openingBank: '',
openingAccount: '',
delFileList: []
},
// OCR
ocrRuleList: ['account_opening_license'],
fileUploadList: [],
// chat_res
ocrResultParams: {
"开户银行": "openingBank",
"账号": "openingAccount",
"开户账号": "openingAccount",
},
rules: {
fileList:[
@ -59,6 +71,66 @@ export default {
})
})
},
// ocr
ocrRule(type) {
const foundItem = this.dict.type.identification_tag.find(item => item.value === type);
const item = foundItem ? {
fileUploadType: foundItem.value,
fields_json: foundItem.raw.remark,
suffix: 'mainDatabase'
} : null;
this.fileUploadList.push(item)
},
// ocr
addOcrRule() {
this.ocrRuleList.forEach(item => {
this.ocrRule(item)
})
},
//
handleFileChange(file) {
this.form.fileList = file;
if (file instanceof Array && file.length > 0 && file[0].response) {
const response = file[0].response;
if (response.ocrResult && response.ocrResult.status_code === 200) {
// ocr
const chat_res = response.ocrResult.data?.chat_res;
if (chat_res && typeof chat_res === 'object') {
// chat_res
Object.keys(chat_res).forEach(key => {
const formField = this.ocrResultParams[key];
if (formField && chat_res[key]) {
this.form[formField] = chat_res[key];
}
});
}
}
//
this.$refs.accountOpeningCertificateForm.validate();
}
},
//
handleDelFile(file) {
console.log(file);
this.form.delFileList.push(file.response.fileRes.uploadPath || file.filePath);
}
},
computed: {
fileUploadRule() {
return this.fileUploadList[0] || {};
}
},
watch: {
//
'dict.type.identification_tag': {
handler(newVal) {
if (newVal && newVal.length > 0) {
this.addOcrRule();
}
},
immediate: true //
}
},
}
</script>

View File

@ -7,25 +7,36 @@
<el-form :model="form" :rules="rules" ref="basicInfoForm" label-width="110px" label-position="top">
<!-- 营业执照 -->
<el-form-item label="营业执照" prop="fileList">
<UploadFile :fileList="form.fileList" :fileUploadRule="fileUploadRule" @file-change="handleFileChange"/>
<UploadFile :fileList="form.fileList" :fileUploadRule="fileUploadRule" @file-change="handleFileChange"
@del-file="handleDelFile" type="business_license" />
</el-form-item>
<el-form-item label="企业名称" prop="enterpriseName">
<el-input v-model="form.enterpriseName" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.enterpriseName" placeholder="自动提取" clearable show-word-limit
maxlength="64"></el-input>
</el-form-item>
<el-form-item label="统一社会信用代码" prop="enterpriseCode">
<el-input v-model="form.enterpriseCode" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.enterpriseCode" placeholder="自动提取" clearable show-word-limit
maxlength="32"></el-input>
</el-form-item>
<el-form-item label="注册资本" prop="registeredCapital">
<el-input v-model="form.registeredCapital" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.registeredCapital" placeholder="自动提取" clearable show-word-limit
maxlength="16"></el-input>
</el-form-item>
<el-form-item label="成立日期" prop="establishedDate">
<el-date-picker class="form-item" v-model="form.establishedDate" placeholder="自动提取"
value-format="yyyy-MM-dd" type="date"></el-date-picker>
</el-form-item>
<el-form-item label="营业期限" prop="businessTerm">
<el-input v-model="form.businessTerm" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.businessTerm" placeholder="自动提取" clearable show-word-limit
maxlength="32"></el-input>
</el-form-item>
<el-form-item label="住所" prop="residence">
<el-input v-model="form.residence" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.residence" placeholder="自动提取" clearable show-word-limit
maxlength="128"></el-input>
</el-form-item>
<el-form-item label="经营范围" prop="businessScope">
<el-input v-model="form.businessScope" placeholder="自动提取"></el-input>
<el-input :autosize="{ minRows: 8, maxRows: 12 }" clearable show-word-limit maxlength="255"
type="textarea" v-model.trim="form.businessScope" placeholder="自动提取"></el-input>
</el-form-item>
</el-form>
</div>
@ -33,6 +44,7 @@
<script>
import UploadFile from '@/views/common/UploadFile.vue'
import { formatDate } from '@/utils/bonus'
export default {
name: 'BasicInfo',
components: {
@ -42,23 +54,25 @@ export default {
data() {
return {
form: {
name: '',
enterpriseName: '',
enterpriseCode: '',
registeredCapital: '',
establishedDate: null,
businessTerm: '',
residence: '',
businessScope: '',
fileList: []
fileList: [],
delFileList: []
},
// OCR
// ocrRuleList: ['business_license', 'face_id_card_portrait', 'national_emblem_id_card', 'account_opening_license'],
ocrRuleList: ['business_license'],
fileUploadList: [],
ocrResult: {
// chat_res
ocrResultParams: {
"企业名称": "enterpriseName",
"统一社会信用代码": "enterpriseCode",
"注册资本": "registeredCapital",
"成立日期": "establishedDate",
"营业期限": "businessTerm",
"住所": "residence",
"经营范围": "businessScope",
@ -76,6 +90,9 @@ export default {
registeredCapital: [
{ required: true, message: '请输入注册资本', trigger: 'blur' }
],
establishedDate: [
{ required: true, message: '请选择注册日期', trigger: 'change' }
],
businessTerm: [
{ required: true, message: '请输入营业期限', trigger: 'blur' }
],
@ -85,12 +102,10 @@ export default {
businessScope: [
{ required: true, message: '请输入经营范围', trigger: 'blur' }
],
}
}
},
created() {
},
methods: {
//
@ -113,7 +128,7 @@ export default {
fields_json: foundItem.raw.remark,
suffix: 'mainDatabase'
} : null;
this.fileUploadList.push(item)
},
// ocr
@ -125,19 +140,33 @@ export default {
//
handleFileChange(file) {
this.form.fileList = file;
console.log(file[0].response);
if(file instanceof Array && file.length > 0){
//
if (file instanceof Array && file.length > 0 && file[0].response) {
const response = file[0].response;
if(response.ocrResult){
if (response.ocrResult && response.ocrResult.status_code === 200) {
// ocr
this.ocrResult.forEach(item => {
this.form[item.value] = response.ocrResult[item.label];
});
const chat_res = response.ocrResult.data?.chat_res;
if (chat_res && typeof chat_res === 'object') {
// chat_res
Object.keys(chat_res).forEach(key => {
const formField = this.ocrResultParams[key];
if (formField && chat_res[key]) {
if (formField === 'establishedDate') {
this.form[formField] = formatDate(chat_res[key]);
} else {
this.form[formField] = chat_res[key];
}
}
});
}
}
//
this.$refs.basicInfoForm.validate();
}
},
//
handleDelFile(file) {
console.log(file);
this.form.delFileList.push(file.response.fileRes.uploadPath || file.filePath);
}
},
computed: {
@ -170,4 +199,8 @@ export default {
font-size: 20px;
}
}
.form-item {
width: 100%;
}
</style>

View File

@ -7,26 +7,28 @@
<el-form :model="form" :rules="rules" ref="legalPersonForm" label-width="110px" label-position="top">
<!-- 身份证人像面 -->
<el-form-item label="身份证人像面" prop="fileList">
<UploadFile :fileList="form.fileList" />
<UploadFile :fileList="form.fileList" :fileUploadRule="fileUploadRule"
@del-file="handleDelFile" @file-change="handleFileChange" type="face_id_card_portrait" />
</el-form-item>
<!-- 身份证国徽面 -->
<el-form-item label="身份证国徽面" prop="fileList2">
<UploadFile :fileList="form.fileList2" />
<UploadFile :fileList="form.fileList2" :fileUploadRule="fileUploadRule2"
@del-file="handleDelFile" @file-change="handleFileChange" type="national_emblem_id_card" />
</el-form-item>
<el-form-item label="法人姓名" prop="legalPersonName">
<el-input v-model="form.legalPersonName" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.legalPersonName" placeholder="自动提取" clearable show-word-limit maxlength="32"></el-input>
</el-form-item>
<el-form-item label="法人身份证号" prop="legalPersonIdCard">
<el-input v-model="form.legalPersonIdCard" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.legalPersonIdCard" placeholder="自动提取" clearable show-word-limit maxlength="32"></el-input>
</el-form-item>
<el-form-item label="身份证有效期" prop="idCardStartDate">
<el-input v-model="form.idCardStartDate" placeholder="自动提取"></el-input>
<el-input v-model.trim="form.idCardStartDate" placeholder="自动提取" clearable show-word-limit maxlength="32"></el-input>
</el-form-item>
<el-form-item label="法人职务" prop="legalPersonPosition">
<el-input v-model="form.legalPersonPosition" placeholder="请输入法人职务"></el-input>
<el-input v-model.trim="form.legalPersonPosition" placeholder="请输入法人职务" clearable show-word-limit maxlength="32"></el-input>
</el-form-item>
<el-form-item label="法人联系方式" prop="legalPersonPhone">
<el-input v-model="form.legalPersonPhone" placeholder="请输入法人联系方式"></el-input>
<el-input v-model.trim="form.legalPersonPhone" placeholder="请输入法人联系方式" clearable show-word-limit maxlength="11"></el-input>
</el-form-item>
</el-form>
</div>
@ -37,6 +39,7 @@ import UploadFile from '@/views/common/UploadFile.vue'
export default {
name: 'LegalPerson',
components: { UploadFile },
dicts: ['identification_tag'],
data() {
return {
form: {
@ -47,6 +50,16 @@ export default {
legalPersonPhone: '',
fileList: [],
fileList2: [],
delFileList: []
},
// OCR
ocrRuleList: ['face_id_card_portrait', 'national_emblem_id_card'],
fileUploadList: [],
// chat_res
ocrResultParams: {
"姓名": "legalPersonName",
"公民身份号码": "legalPersonIdCard",
"有效期限": "idCardStartDate",
},
rules: {
fileList: [
@ -81,6 +94,75 @@ export default {
})
})
},
// ocr
ocrRule(type) {
const foundItem = this.dict.type.identification_tag.find(item => item.value === type);
const item = foundItem ? {
fileUploadType: foundItem.value,
fields_json: foundItem.raw.remark,
suffix: 'mainDatabase'
} : null;
this.fileUploadList.push(item)
},
// ocr
addOcrRule() {
this.ocrRuleList.forEach(item => {
this.ocrRule(item)
})
},
//
handleFileChange(file, type) {
if (file instanceof Array && file.length > 0 && file[0].response) {
const response = file[0].response;
if (response.ocrResult && response.ocrResult.status_code === 200) {
// ocr
const chat_res = response.ocrResult.data?.chat_res;
if (chat_res && typeof chat_res === 'object') {
// chat_res
Object.keys(chat_res).forEach(key => {
const formField = this.ocrResultParams[key];
if (formField && chat_res[key]) {
this.form[formField] = chat_res[key];
}
});
}
}
if (type == 'face_id_card_portrait') {
this.form.fileList = file;
this.$refs.legalPersonForm.validateField(['legalPersonName', 'legalPersonIdCard']);
} else if (type == 'national_emblem_id_card') {
this.form.fileList2 = file;
this.$refs.legalPersonForm.validateField(['idCardStartDate']);
}
}
},
//
handleDelFile(file) {
console.log(file);
this.form.delFileList.push(file.response.fileRes.uploadPath || file.filePath);
}
},
computed: {
fileUploadRule() {
return this.fileUploadList[0] || {};
},
fileUploadRule2() {
return this.fileUploadList[1] || {};
}
},
watch: {
//
'dict.type.identification_tag': {
handler(newVal) {
if (newVal && newVal.length > 0) {
this.addOcrRule();
}
},
immediate: true //
}
},
}
</script>