This commit is contained in:
2026-07-27 17:19:36 +08:00
parent e50d1b8fda
commit 1c7532e0de
132 changed files with 7066 additions and 1241 deletions

View File

@@ -151,11 +151,11 @@
ref="archiveForm"
:model="archiveForm"
:rules="formRules"
label-position="top"
label-position="right"
:disabled="readonly"
class="archive-form"
>
<div class="section-title">基本信息</div>
<div class="section-title dialog-section-title">基本信息</div>
<el-alert
type="warning"
:closable="false"
@@ -164,7 +164,7 @@
class="archive-rule-alert"
/>
<el-row :gutter="18">
<el-col :span="6">
<el-col v-if="readonly" :span="6">
<el-form-item label="客商编号" prop="customerCode">
<el-input v-model="archiveForm.customerCode" disabled placeholder="保存后自动生成" />
</el-form-item>
@@ -221,7 +221,11 @@
v-model="archiveForm.unifiedCreditCode"
maxlength="18"
show-word-limit
@input="archiveForm.unifiedCreditCode = String(archiveForm.unifiedCreditCode || '').toUpperCase()"
@input="
archiveForm.unifiedCreditCode = String(
archiveForm.unifiedCreditCode || ''
).toUpperCase()
"
/>
</el-form-item>
</el-col>
@@ -335,16 +339,23 @@
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="archiveForm.remark" type="textarea" maxlength="500" show-word-limit />
<el-input
v-model="archiveForm.remark"
type="textarea"
maxlength="500"
show-word-limit
/>
</el-form-item>
</el-col>
</el-row>
</el-form>
<div class="section-head">
<div class="section-title">资质附件</div>
<div class="section-title dialog-section-title">资质附件</div>
<div v-if="!readonly" class="section-actions">
<el-button type="primary" icon="el-icon-upload" @click="addAttachment">OCR上传识别</el-button>
<el-button type="primary" icon="el-icon-upload" @click="addAttachment"
>OCR上传识别</el-button
>
<el-button type="primary" icon="el-icon-plus" @click="addAttachment">添加附件</el-button>
<el-button icon="el-icon-download" @click="downloadAttachments">批量下载</el-button>
</div>
@@ -352,7 +363,7 @@
<el-alert
type="info"
:closable="false"
title="支持 JPG、PNG、PDF单文件大小不超过 10MB正式客商需上传公司营业执照、道路运输证等核心材料。"
title="支持 JPG、PNG、PDF、Word、Excel、PPT,单文件大小不超过 10MB正式客商需上传公司营业执照、道路运输证等核心材料。"
class="archive-rule-alert"
/>
<el-alert
@@ -377,7 +388,16 @@
</el-table-column>
<el-table-column label="文件名称" min-width="180">
<template #default="{ row }">
<el-input v-model="row.name" :disabled="readonly" maxlength="100" />
<vehicle-attachment-upload
v-model="row.files"
:readonly="readonly"
:multiple="false"
accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
:max-size="10"
button-text="上传文件"
:show-tip="false"
@success="file => handleQualificationUploadSuccess(file, row)"
/>
</template>
</el-table-column>
<el-table-column label="附件描述" min-width="220">
@@ -387,27 +407,24 @@
</el-table-column>
<el-table-column label="文件大小" min-width="120">
<template #default="{ row }">
<el-input v-model="row.size" :disabled="readonly" maxlength="30" />
<span>{{ row.size || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="上传人" min-width="120">
<template #default="{ row }">
<el-input v-model="row.uploadUserName" :disabled="readonly" maxlength="30" />
<span>{{ row.uploadUserName || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="上传时间" min-width="170">
<template #default="{ row }">
<el-date-picker
v-model="row.uploadTime"
type="datetime"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled="readonly"
/>
<span>{{ row.uploadTime || '-' }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="90" align="center" v-if="!readonly">
<template #default="{ $index }">
<el-button type="danger" text @click="qualificationFiles.splice($index, 1)">删除</el-button>
<el-button type="danger" text @click="qualificationFiles.splice($index, 1)"
>删除</el-button
>
</template>
</el-table-column>
</el-table>
@@ -437,7 +454,12 @@
<el-table-column label="最终得分" prop="finalScore" width="110" align="center" />
<el-table-column label="额度" min-width="150">
<template #default="{ row }">
<el-input-number v-model="row.applyCreditLimit" :min="0" :precision="2" :disabled="readonly" />
<el-input-number
v-model="row.applyCreditLimit"
:min="0"
:precision="2"
:disabled="readonly"
/>
</template>
</el-table-column>
<el-table-column label="信用等级" min-width="130">
@@ -450,8 +472,15 @@
<el-table-column label="操作" width="210" align="center">
<template #default="{ row, $index }">
<el-button type="primary" text @click="openScore(row)">评分明细</el-button>
<el-button type="success" text v-if="!readonly" @click="finishScore(row)">完成评分</el-button>
<el-button type="danger" text v-if="!readonly" @click="archiveForm.scores.splice($index, 1)">
<el-button type="success" text v-if="!readonly" @click="finishScore(row)"
>完成评分</el-button
>
<el-button
type="danger"
text
v-if="!readonly"
@click="archiveForm.scores.splice($index, 1)"
>
删除
</el-button>
</template>
@@ -500,7 +529,13 @@
</template>
</el-dialog>
<el-dialog title="评分明细" append-to-body v-model="scoreBox" width="88%" class="archive-dialog">
<el-dialog
title="评分明细"
append-to-body
v-model="scoreBox"
width="88%"
class="archive-dialog"
>
<el-table :data="currentScore.details" border class="score-detail-table">
<el-table-column label="序号" type="index" width="70" align="center" />
<el-table-column label="评分类目" prop="categoryName" min-width="130" />
@@ -530,7 +565,12 @@
</el-table-column>
<el-table-column label="复评得分" width="130" align="center">
<template #default="{ row }">
<el-input-number v-model="row.reviewScore" :min="0" :precision="2" :disabled="readonly" />
<el-input-number
v-model="row.reviewScore"
:min="0"
:precision="2"
:disabled="readonly"
/>
</template>
</el-table-column>
<el-table-column label="得分说明" prop="scoreDescription" min-width="220" />
@@ -746,7 +786,10 @@ export default {
searchBtnText: '查询',
emptyBtnText: '重置',
searchShow: true,
searchMenuSpan: 6,
searchMenuSpan: 24,
searchIcon: true,
searchIndex: 8,
searchMenuPosition: 'right',
border: true,
index: true,
indexLabel: '序号',
@@ -877,12 +920,20 @@ export default {
},
missingQualificationText() {
if (this.archiveForm.accessType !== 'formal') return '';
const types = this.qualificationFiles.map(item => item.type || item.name).filter(Boolean);
const types = this.qualificationFiles
.filter(item => item.url)
.map(item => item.type || item.name)
.filter(Boolean);
const missing = ['公司营业执照', '道路运输证'].filter(
item => !types.some(type => String(type).includes(item))
);
return missing.length ? `缺失核心资质材料:${missing.join('、')}` : '';
},
uploadHeaders() {
return {
[this.website.tokenHeader]: getToken(),
};
},
},
methods: {
hasPermission(code) {
@@ -902,7 +953,14 @@ export default {
};
},
emptyContact() {
return { contactName: '', contactPhone: '', email: '', positionName: '', isDefault: 0, remark: '' };
return {
contactName: '',
contactPhone: '',
email: '',
positionName: '',
isDefault: 0,
remark: '',
};
},
emptyReceiptAccount() {
return {
@@ -976,16 +1034,26 @@ export default {
if (Array.isArray(value)) return value;
try {
const list = JSON.parse(value);
return Array.isArray(list) ? list : [];
return Array.isArray(list)
? list.map(item => ({
...item,
files: item.url ? [item] : [],
}))
: [];
} catch (error) {
return String(value)
.split(',')
.map(item => ({ name: item.trim(), url: item.trim() }))
.filter(item => item.url);
.filter(item => item.url)
.map(item => ({
...item,
files: [item],
}));
}
},
stringifyAttachments(list) {
const files = (list || [])
.filter(item => item.url)
.map(item => ({
type: String(item.type || '').trim(),
name: String(item.name || '').trim(),
@@ -995,7 +1063,7 @@ export default {
uploadTime: String(item.uploadTime || '').trim(),
url: String(item.url || '').trim(),
}))
.filter(item => item.type || item.name || item.url);
.filter(item => item.url);
return files.length ? JSON.stringify(files) : '';
},
addAttachment() {
@@ -1007,8 +1075,25 @@ export default {
uploadUserName: this.userInfo.realName || this.userInfo.userName || '',
uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss'),
url: '',
files: [],
});
},
formatAttachmentSize(size) {
if (!size) return '';
const byteSize = Number(size);
if (!Number.isFinite(byteSize)) return String(size);
const mb = byteSize / 1024 / 1024;
if (mb >= 1) return `${mb.toFixed(2)} MB`;
return `${(byteSize / 1024).toFixed(2)} KB`;
},
handleQualificationUploadSuccess(file, row) {
row.name = file.name || row.name || '资质附件';
row.size = this.formatAttachmentSize(file.size || row.size);
row.uploadUserName = this.userInfo.realName || this.userInfo.userName || '';
row.uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
row.url = file.url || row.url || '';
row.files = [file];
},
downloadAttachments() {
const files = this.qualificationFiles.filter(item => item.url);
if (!files.length) {
@@ -1051,7 +1136,9 @@ export default {
if (row && row.id) {
getDetail(row.id).then(res => {
this.archiveForm = this.normalizeDetail(res.data.data);
this.qualificationFiles = this.parseAttachments(this.archiveForm.qualificationAttachments);
this.qualificationFiles = this.parseAttachments(
this.archiveForm.qualificationAttachments
);
this.archiveBox = true;
});
return;
@@ -1089,7 +1176,9 @@ export default {
? archive.customerType.join(',')
: archive.customerType;
archive.qualificationAttachments = this.stringifyAttachments(this.qualificationFiles);
archive.contacts = (archive.contacts || []).filter(item => item.contactName || item.contactPhone);
archive.contacts = (archive.contacts || []).filter(
item => item.contactName || item.contactPhone
);
archive.receiptAccounts = (archive.receiptAccounts || []).filter(
item => item.accountName || item.bankAccount
);
@@ -1161,7 +1250,9 @@ export default {
}
},
scoreOptionChange(detail, optionValue) {
const option = this.parseScoreOptions(detail.optionsJson).find(item => item.value === optionValue);
const option = this.parseScoreOptions(detail.optionsJson).find(
item => item.value === optionValue
);
const score = Number(option?.score || 0);
detail.selfScore = score;
detail.reviewScore = score;
@@ -1327,7 +1418,10 @@ export default {
type: 'warning',
}).then(() => {
NProgress.start();
exportBlob('/blade-transport/customer-archive/export-customer-archive', this.buildExportParams())
exportBlob(
'/blade-transport/customer-archive/export-customer-archive',
this.buildExportParams()
)
.then(res => {
downloadXls(res.data, `客商档案${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
})
@@ -1375,6 +1469,10 @@ export default {
align-items: center;
justify-content: space-between;
margin: 18px 0 12px;
.section-title {
margin: 0;
}
}
.section-actions {