Merge remote-tracking branch 'origin/master'

This commit is contained in:
2026-08-11 12:15:15 +08:00
21 changed files with 408 additions and 107 deletions
+1
View File
@@ -170,6 +170,7 @@ Avue 表格/表单配置独立存放于 `src/option/` 目录,与 `views` 和 `
- 表格操作列同时展示“查看、编辑、删除”等三个按钮时,操作列宽度统一不小于 `220px`;操作列最大按钮数量超过 3 个时,操作列宽度统一加宽到不小于 `320px`;最大按钮数量超过 4 个时,仍按 `320px` 保持列宽,并从第 5 个按钮开始换行展示,禁止出现按钮裁切或显示不全。 - 表格操作列同时展示“查看、编辑、删除”等三个按钮时,操作列宽度统一不小于 `220px`;操作列最大按钮数量超过 3 个时,操作列宽度统一加宽到不小于 `320px`;最大按钮数量超过 4 个时,仍按 `320px` 保持列宽,并从第 5 个按钮开始换行展示,禁止出现按钮裁切或显示不全。
- 表格操作列按钮统一仅展示文字,禁止配置 `icon` / `:icon` 或在操作按钮、操作下拉项中嵌入图标;顶部工具栏按钮不受此条限制。 - 表格操作列按钮统一仅展示文字,禁止配置 `icon` / `:icon` 或在操作按钮、操作下拉项中嵌入图标;顶部工具栏按钮不受此条限制。
- 纯文字操作入口统一使用 `<el-link>`,禁止使用带 `text` 属性的 `<el-button>`;提交、确认、上传等具有明确命令语义或需要加载状态的按钮可继续使用 `<el-button>` - 纯文字操作入口统一使用 `<el-link>`,禁止使用带 `text` 属性的 `<el-button>`;提交、确认、上传等具有明确命令语义或需要加载状态的按钮可继续使用 `<el-button>`
- 所有“删除”“作废”操作入口必须使用危险色红色文字:表格操作链接统一配置 `type="danger"`,配置化操作必须设置 `type: 'danger'`;顶部批量删除按钮统一使用 `type="danger"`
- 所有表格操作列中的文字链接统一保持 `8px` 间距;操作按钮超过操作列可用宽度时必须自动换行,禁止链接连续粘连或被裁切。Avue 自定义 `#menu` 插槽和手写 `el-table-column` 操作列均适用。 - 所有表格操作列中的文字链接统一保持 `8px` 间距;操作按钮超过操作列可用宽度时必须自动换行,禁止链接连续粘连或被裁切。Avue 自定义 `#menu` 插槽和手写 `el-table-column` 操作列均适用。
- `.avue-crud__header` 顶部间距统一为 `12px` - `.avue-crud__header` 顶部间距统一为 `12px`
- 分页组件整体靠右展示,必须展示接口返回的数据总条数,`X条/页` 的页容量选择器必须放在总条数右侧。 - 分页组件整体靠右展示,必须展示接口返回的数据总条数,`X条/页` 的页容量选择器必须放在总条数右侧。
+12
View File
@@ -22,6 +22,18 @@ export const getDetail = id => {
}); });
}; };
export const getChangeRecordList = (customerId, current, size) => {
return request({
url: '/blade-transport/customer-archive/change-record/list',
method: 'get',
params: {
customerId,
current,
size,
},
});
};
export const submit = row => { export const submit = row => {
return request({ return request({
url: '/blade-transport/customer-archive/submit', url: '/blade-transport/customer-archive/submit',
@@ -12,6 +12,7 @@
:show-file-list="showFileList" :show-file-list="showFileList"
:on-success="handleSuccess" :on-success="handleSuccess"
:on-error="handleError" :on-error="handleError"
:on-change="handleChange"
:on-remove="handleRemove" :on-remove="handleRemove"
:on-preview="handlePreview" :on-preview="handlePreview"
:before-upload="beforeUpload" :before-upload="beforeUpload"
@@ -25,6 +26,9 @@
</div> </div>
</template> </template>
</el-upload> </el-upload>
<span v-if="showUploading && uploadingCount" class="vehicle-attachment-upload__uploading">
上传中{{ uploadingCount }}
</span>
<span v-if="readonly && fileList.length === 0" class="vehicle-attachment-upload__empty"> <span v-if="readonly && fileList.length === 0" class="vehicle-attachment-upload__empty">
- -
</span> </span>
@@ -165,6 +169,10 @@ export default {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
showUploading: {
type: Boolean,
default: false,
},
}, },
emits: ['update:modelValue', 'change', 'success'], emits: ['update:modelValue', 'change', 'success'],
data() { data() {
@@ -209,10 +217,15 @@ export default {
const sizeText = this.maxSize > 0 ? `,单文件不超过 ${this.maxSize}MB` : ''; const sizeText = this.maxSize > 0 ? `,单文件不超过 ${this.maxSize}MB` : '';
return `支持上传 ${typeText}${sizeText}`; return `支持上传 ${typeText}${sizeText}`;
}, },
uploadingCount() {
return this.fileList.filter(file => ['ready', 'uploading'].includes(file.status)).length;
},
}, },
watch: { watch: {
modelValue: { modelValue: {
handler(value) { handler(value) {
// Keep pending uploads in Element Plus' internal list until every selected file settles.
if (this.fileList.some(file => ['ready', 'uploading'].includes(file.status))) return;
this.fileList = this.toUploadList(value); this.fileList = this.toUploadList(value);
}, },
immediate: true, immediate: true,
@@ -224,10 +237,12 @@ export default {
const list = this.parseValue(value); const list = this.parseValue(value);
return list.map((item, index) => { return list.map((item, index) => {
const url = this.getFileUrl(item); const url = this.getFileUrl(item);
const originalName = item.originalName || item.name || this.getFileName(url) || '附件';
return { return {
...item, ...item,
uid: item.uid || `${url || item.name || 'file'}-${index}`, uid: item.uid || `${url || originalName || 'file'}-${index}`,
name: item.name || this.getFileName(url) || '附件', originalName,
name: originalName,
url, url,
status: 'success', status: 'success',
}; };
@@ -297,6 +312,9 @@ export default {
this.$emit('success', this.normalizeUploadFile(file)); this.$emit('success', this.normalizeUploadFile(file));
this.$message.success('上传成功'); this.$message.success('上传成功');
}, },
handleChange(file, files) {
this.fileList = files || [];
},
handleError() { handleError() {
this.$message.error('上传失败'); this.$message.error('上传失败');
}, },
@@ -316,12 +334,14 @@ export default {
normalizeUploadFile(file) { normalizeUploadFile(file) {
const data = (file.response && file.response.data) || file.data || file; const data = (file.response && file.response.data) || file.data || file;
const url = data.link || data.url || data.domain || file.url || ''; const url = data.link || data.url || data.domain || file.url || '';
const name = data.name || data.originalName || file.name || this.getFileName(url) || '附件'; const originalName =
const extension = this.getExtension({ name, url }); data.originalName || file.originalName || data.name || file.name || this.getFileName(url) || '附件';
const extension = this.getExtension({ name: originalName, url });
return { return {
...data, ...data,
uid: file.uid || data.uid, uid: file.uid || data.uid,
name, originalName,
name: originalName,
url, url,
link: data.link || url, link: data.link || url,
size: data.size || data.attachSize || file.size || '', size: data.size || data.attachSize || file.size || '',
@@ -360,6 +380,12 @@ export default {
&__empty { &__empty {
color: #909399; color: #909399;
} }
&__uploading {
margin-left: 8px;
color: #409eff;
font-size: 13px;
}
} }
:global(.vehicle-attachment-upload__viewer-dialog .el-dialog__body) { :global(.vehicle-attachment-upload__viewer-dialog .el-dialog__body) {
+4 -3
View File
@@ -145,7 +145,8 @@ export const option = {
dicData: processStatusOptions, dicData: processStatusOptions,
slot: true, slot: true,
hide: true, hide: true,
fixed: false, fixed: 'right',
minWidth: 100,
addDisplay: false, addDisplay: false,
editDisplay: false, editDisplay: false,
}, },
@@ -174,8 +175,8 @@ export const option = {
hide: true, hide: true,
}, },
]), ]),
saveBtnText: '保存', saveBtn: false,
updateBtnText: '保存', updateBtn: false,
dialogTop: '10px', dialogTop: '10px',
dialogWidth: '96%', dialogWidth: '96%',
menuWidth: 220, menuWidth: 220,
@@ -271,6 +271,6 @@ export const option = {
}, },
...auditColumns.map(column => ({ ...column, hide: true })), ...auditColumns.map(column => ({ ...column, hide: true })),
]), ]),
dialogWidth: 1010, dialogWidth: 1280,
index: false, index: false,
}; };
+3
View File
@@ -194,9 +194,12 @@
} }
.avue-crud__dialog .avue-dialog__footer { .avue-crud__dialog .avue-dialog__footer {
position: relative;
z-index: 2;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
background: #fff;
} }
.avue-crud__dialog .avue-dialog__footer--left { .avue-crud__dialog .avue-dialog__footer--left {
+1 -1
View File
@@ -95,7 +95,7 @@
> >
编辑 编辑
</el-link> </el-link>
<el-link type="primary" v-if="permission.cargo_type_delete" @click="rowDel(row)"> <el-link type="danger" v-if="permission.cargo_type_delete" @click="rowDel(row)">
删除 删除
</el-link> </el-link>
</template> </template>
+1 -1
View File
@@ -68,7 +68,7 @@
编辑 编辑
</el-link> </el-link>
<el-link <el-link
type="primary" type="danger"
v-if="hasPermission('common_address_delete') && !row.readonly" v-if="hasPermission('common_address_delete') && !row.readonly"
@click="rowDel(row)" @click="rowDel(row)"
> >
+1 -1
View File
@@ -59,7 +59,7 @@
</el-button> </el-button>
<el-button <el-button
v-if="permission.region_delete" v-if="permission.region_delete"
type="primary" type="danger"
icon="el-icon-delete" icon="el-icon-delete"
@click="handleDelete" @click="handleDelete"
>删除 >删除
+1 -1
View File
@@ -163,7 +163,7 @@
编辑 编辑
</el-link> </el-link>
<el-link <el-link
type="primary" type="danger"
v-if="hasPermission('common_cargo_delete') && !row.readonly" v-if="hasPermission('common_cargo_delete') && !row.readonly"
@click="rowDel(row)" @click="rowDel(row)"
> >
+1 -1
View File
@@ -132,7 +132,7 @@
编辑 编辑
</el-link> </el-link>
<el-link <el-link
type="primary" type="danger"
v-if="hasPermission('common_route_delete') && !row.readonly" v-if="hasPermission('common_route_delete') && !row.readonly"
@click="rowDel(row)" @click="rowDel(row)"
> >
@@ -564,7 +564,7 @@
</el-link> </el-link>
<el-link <el-link
v-if="!dialogReadonly" v-if="!dialogReadonly"
type="primary" type="danger"
@click="removeTransportCargoRow($index)" @click="removeTransportCargoRow($index)"
> >
删除 删除
@@ -1378,7 +1378,7 @@
</el-link> </el-link>
<el-link <el-link
v-if="!dialogReadonly" v-if="!dialogReadonly"
type="primary" type="danger"
@click="removeTransportCargoRow($index)" @click="removeTransportCargoRow($index)"
> >
删除 删除
@@ -1627,8 +1627,21 @@
button-text="上传附件" button-text="上传附件"
@change="handleContractFileChange" @change="handleContractFileChange"
/> />
<el-button
type="primary"
:disabled="!contractFileRows.length"
@click="handleContractFileBatchDownload"
>
批量下载
</el-button>
</div> </div>
<el-table :data="contractFileRows" border class="business-crud-page__attachment-table"> <el-table
:data="contractFileRows"
border
class="business-crud-page__attachment-table"
@selection-change="handleContractFileSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="70" align="center" /> <el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column label="文件名" min-width="240" align="center" show-overflow-tooltip> <el-table-column label="文件名" min-width="240" align="center" show-overflow-tooltip>
<template #default="{ row }">{{ row.originalName || row.name }}</template> <template #default="{ row }">{{ row.originalName || row.name }}</template>
@@ -1638,11 +1651,11 @@
</el-table-column> </el-table-column>
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" /> <el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
<el-table-column prop="uploadTime" label="上传时间" width="170" align="center" sortable/> <el-table-column prop="uploadTime" label="上传时间" width="170" align="center" sortable/>
<el-table-column label="操作" width="120" align="center"> <el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-link <el-link
v-if="!dialogReadonly" v-if="!dialogReadonly"
type="primary" type="danger"
@click="removeContractFile($index)" @click="removeContractFile($index)"
> >
删除 删除
@@ -1687,14 +1700,14 @@
align="center" align="center"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column label="操作" width="180" align="center"> <el-table-column label="操作" width="180" align="center" fixed="right">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-link type="primary" @click="openBillingPlan(row, $index)"> <el-link type="primary" @click="openBillingPlan(row, $index)">
编辑 编辑
</el-link> </el-link>
<el-link <el-link
v-if="!dialogReadonly" v-if="!dialogReadonly"
type="primary" type="danger"
@click="removeBillingPlan($index)" @click="removeBillingPlan($index)"
> >
删除 删除
@@ -1882,7 +1895,13 @@
批量下载 批量下载
</el-button> </el-button>
</div> </div>
<el-table :data="attachmentRows" border class="business-crud-page__attachment-table"> <el-table
:data="attachmentRows"
border
class="business-crud-page__attachment-table"
@selection-change="handleAttachmentSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="70" align="center" /> <el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column label="文件名" min-width="200" align="center" show-overflow-tooltip> <el-table-column label="文件名" min-width="200" align="center" show-overflow-tooltip>
<template #default="{ row }">{{ row.originalName || row.name }}</template> <template #default="{ row }">{{ row.originalName || row.name }}</template>
@@ -1901,11 +1920,11 @@
</el-table-column> </el-table-column>
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" /> <el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
<el-table-column prop="uploadTime" label="上传时间" width="160" align="center" sortable/> <el-table-column prop="uploadTime" label="上传时间" width="160" align="center" sortable/>
<el-table-column label="操作" width="100" align="center"> <el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-link <el-link
v-if="!dialogReadonly" v-if="!dialogReadonly"
type="primary" type="danger"
@click="removeAttachment($index)" @click="removeAttachment($index)"
> >
删除 删除
@@ -1937,7 +1956,7 @@
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column prop="statusName" label="状态" min-width="140" align="center" /> <el-table-column prop="statusName" label="状态" min-width="140" align="center" />
<el-table-column label="操作" width="120" align="center"> <el-table-column label="操作" width="120" align="center" fixed="right">
<template #default="{ row }"> <template #default="{ row }">
<el-link type="primary" @click="handleChangeRecordFlow(row)"> 流程 </el-link> <el-link type="primary" @click="handleChangeRecordFlow(row)"> 流程 </el-link>
</template> </template>
@@ -2095,7 +2114,7 @@
> >
{{ operation.label }} {{ operation.label }}
</el-link> </el-link>
<el-link type="primary" v-if="canDelete(row)" @click="rowDel(row)"> <el-link type="danger" v-if="canDelete(row)" @click="rowDel(row)">
删除 删除
</el-link> </el-link>
</template> </template>
@@ -3124,7 +3143,9 @@
:data="dispatchItemAttachmentRows" :data="dispatchItemAttachmentRows"
border border
class="business-crud-page__attachment-table" class="business-crud-page__attachment-table"
@selection-change="handleDispatchItemAttachmentSelectionChange"
> >
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="70" align="center" /> <el-table-column type="index" label="序号" width="70" align="center" />
<el-table-column label="文件名" min-width="200" align="center" show-overflow-tooltip> <el-table-column label="文件名" min-width="200" align="center" show-overflow-tooltip>
<template #default="{ row }">{{ row.originalName || row.name }}</template> <template #default="{ row }">{{ row.originalName || row.name }}</template>
@@ -3139,7 +3160,7 @@
</el-table-column> </el-table-column>
<el-table-column prop="uploadUserName" label="上传人" width="140" align="center" /> <el-table-column prop="uploadUserName" label="上传人" width="140" align="center" />
<el-table-column prop="uploadTime" label="上传时间" width="160" align="center" sortable/> <el-table-column prop="uploadTime" label="上传时间" width="160" align="center" sortable/>
<el-table-column label="操作" width="100" align="center"> <el-table-column label="操作" width="100" align="center" fixed="right">
<template #default="{ $index }"> <template #default="{ $index }">
<el-link type="danger" @click="removeDispatchItemAttachment($index)">删除</el-link> <el-link type="danger" @click="removeDispatchItemAttachment($index)">删除</el-link>
</template> </template>
@@ -3364,7 +3385,7 @@
</el-link> </el-link>
<el-button <el-button
v-if="canEditBillingLimit(row) && getBillingLimitRanges(row).length > 1" v-if="canEditBillingLimit(row) && getBillingLimitRanges(row).length > 1"
type="primary" type="danger"
text text
@click="removeBillingLimitRange(row, rangeIndex)" @click="removeBillingLimitRange(row, rangeIndex)"
> >
@@ -3409,7 +3430,7 @@
</el-link> </el-link>
<el-link <el-link
v-if="!dialogReadonly" v-if="!dialogReadonly"
type="primary" type="danger"
@click="removeBillingRule($index)" @click="removeBillingRule($index)"
> >
删除 删除
@@ -4304,8 +4325,11 @@ export default {
dispatchItemIndex: -1, dispatchItemIndex: -1,
dispatchItemForm: defaultDispatchRow(), dispatchItemForm: defaultDispatchRow(),
dispatchItemAttachmentRows: [], dispatchItemAttachmentRows: [],
selectedDispatchItemAttachmentRows: [],
attachmentRows: [], attachmentRows: [],
selectedAttachmentRows: [],
contractFileRows: [], contractFileRows: [],
selectedContractFileRows: [],
transportCargoRows: [], transportCargoRows: [],
shippingTemplateFreight: defaultShippingTemplateFreight(), shippingTemplateFreight: defaultShippingTemplateFreight(),
shippingTemplateCurrencyOptions: [], shippingTemplateCurrencyOptions: [],
@@ -5107,6 +5131,7 @@ export default {
this.form.planName = this.form.planName || this.form.templateName || ''; this.form.planName = this.form.planName || this.form.templateName || '';
this.selectedProjectId = this.form.projectId || ''; this.selectedProjectId = this.form.projectId || '';
this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson); this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson);
this.selectedAttachmentRows = [];
if (this.contractSelectEnabled) { if (this.contractSelectEnabled) {
this.syncCurrentContractOption(); this.syncCurrentContractOption();
this.loadContractOptionsForProject(); this.loadContractOptionsForProject();
@@ -5810,7 +5835,9 @@ export default {
this.selectedProjectId = ''; this.selectedProjectId = '';
this.selectedOrganizationId = ''; this.selectedOrganizationId = '';
this.attachmentRows = []; this.attachmentRows = [];
this.selectedAttachmentRows = [];
this.contractFileRows = []; this.contractFileRows = [];
this.selectedContractFileRows = [];
this.shippingPlanOptions = []; this.shippingPlanOptions = [];
if (this.contractSelectEnabled) { if (this.contractSelectEnabled) {
this.contractOptions = []; this.contractOptions = [];
@@ -5861,7 +5888,9 @@ export default {
this.selectedProjectId = this.form.projectId || ''; this.selectedProjectId = this.form.projectId || '';
this.selectedOrganizationId = this.form.organizationId || ''; this.selectedOrganizationId = this.form.organizationId || '';
this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson); this.attachmentRows = this.parseJsonArray(this.form.attachmentsJson);
this.selectedAttachmentRows = [];
this.contractFileRows = this.parseJsonArray(this.form.contractFileJson); this.contractFileRows = this.parseJsonArray(this.form.contractFileJson);
this.selectedContractFileRows = [];
this.initTransportPlanFormRows(); this.initTransportPlanFormRows();
this.billingPlanRows = this.parseJsonArray(this.form.billingPlanJson); this.billingPlanRows = this.parseJsonArray(this.form.billingPlanJson);
this.settlementRuleForm = this.normalizeSettlementRule({ this.settlementRuleForm = this.normalizeSettlementRule({
@@ -7630,10 +7659,17 @@ export default {
uploadUserName: item.uploadUserName || userName, uploadUserName: item.uploadUserName || userName,
uploadTime: item.uploadTime || uploadTime, uploadTime: item.uploadTime || uploadTime,
})); }));
this.selectedAttachmentRows = [];
this.form.attachmentsJson = JSON.stringify(this.attachmentRows); this.form.attachmentsJson = JSON.stringify(this.attachmentRows);
}, },
handleAttachmentSelectionChange(rows) {
this.selectedAttachmentRows = rows || [];
},
removeAttachment(index) { removeAttachment(index) {
this.attachmentRows.splice(index, 1); this.attachmentRows.splice(index, 1);
this.selectedAttachmentRows = this.selectedAttachmentRows.filter(item =>
this.attachmentRows.includes(item)
);
this.form.attachmentsJson = JSON.stringify(this.attachmentRows); this.form.attachmentsJson = JSON.stringify(this.attachmentRows);
}, },
formatFileSize(size) { formatFileSize(size) {
@@ -7652,7 +7688,10 @@ export default {
downloadFileByUrl(url, row.originalName || row.name || '附件'); downloadFileByUrl(url, row.originalName || row.name || '附件');
}, },
handleBatchDownload() { handleBatchDownload() {
this.attachmentRows.forEach(row => this.downloadAttachment(row)); const rows = this.selectedAttachmentRows.length
? this.selectedAttachmentRows
: this.attachmentRows;
rows.forEach(row => this.downloadAttachment(row));
}, },
handleDispatchItemAttachmentChange(list) { handleDispatchItemAttachmentChange(list) {
const userName = this.userInfo?.realName || this.userInfo?.userName || ''; const userName = this.userInfo?.realName || this.userInfo?.userName || '';
@@ -7663,12 +7702,22 @@ export default {
uploadUserName: item.uploadUserName || userName, uploadUserName: item.uploadUserName || userName,
uploadTime: item.uploadTime || uploadTime, uploadTime: item.uploadTime || uploadTime,
})); }));
this.selectedDispatchItemAttachmentRows = [];
}, },
removeDispatchItemAttachment(index) { removeDispatchItemAttachment(index) {
this.dispatchItemAttachmentRows.splice(index, 1); this.dispatchItemAttachmentRows.splice(index, 1);
this.selectedDispatchItemAttachmentRows = this.selectedDispatchItemAttachmentRows.filter(item =>
this.dispatchItemAttachmentRows.includes(item)
);
}, },
handleDispatchItemBatchDownload() { handleDispatchItemBatchDownload() {
this.dispatchItemAttachmentRows.forEach(row => this.downloadAttachment(row)); const rows = this.selectedDispatchItemAttachmentRows.length
? this.selectedDispatchItemAttachmentRows
: this.dispatchItemAttachmentRows;
rows.forEach(row => this.downloadAttachment(row));
},
handleDispatchItemAttachmentSelectionChange(rows) {
this.selectedDispatchItemAttachmentRows = rows || [];
}, },
handleContractFileChange(list) { handleContractFileChange(list) {
const userName = this.userInfo?.realName || this.userInfo?.userName || ''; const userName = this.userInfo?.realName || this.userInfo?.userName || '';
@@ -7678,12 +7727,25 @@ export default {
uploadUserName: item.uploadUserName || userName, uploadUserName: item.uploadUserName || userName,
uploadTime: item.uploadTime || uploadTime, uploadTime: item.uploadTime || uploadTime,
})); }));
this.selectedContractFileRows = [];
this.form.contractFileJson = JSON.stringify(this.contractFileRows); this.form.contractFileJson = JSON.stringify(this.contractFileRows);
}, },
handleContractFileSelectionChange(rows) {
this.selectedContractFileRows = rows || [];
},
removeContractFile(index) { removeContractFile(index) {
this.contractFileRows.splice(index, 1); this.contractFileRows.splice(index, 1);
this.selectedContractFileRows = this.selectedContractFileRows.filter(item =>
this.contractFileRows.includes(item)
);
this.form.contractFileJson = JSON.stringify(this.contractFileRows); this.form.contractFileJson = JSON.stringify(this.contractFileRows);
}, },
handleContractFileBatchDownload() {
const rows = this.selectedContractFileRows.length
? this.selectedContractFileRows
: this.contractFileRows;
rows.forEach(row => this.downloadAttachment(row));
},
cloneData(data) { cloneData(data) {
return JSON.parse(JSON.stringify(data)); return JSON.parse(JSON.stringify(data));
}, },
@@ -8999,6 +9061,7 @@ export default {
this.dispatchItemIndex = -1; this.dispatchItemIndex = -1;
this.dispatchItemForm = defaultDispatchRow(); this.dispatchItemForm = defaultDispatchRow();
this.dispatchItemAttachmentRows = []; this.dispatchItemAttachmentRows = [];
this.selectedDispatchItemAttachmentRows = [];
}, },
buildDispatchRows(plan = {}) { buildDispatchRows(plan = {}) {
const goodsRows = this.parseJsonArray(plan.goodsJson); const goodsRows = this.parseJsonArray(plan.goodsJson);
@@ -9128,6 +9191,7 @@ export default {
this.dispatchItemAttachmentRows = this.parseJsonArray( this.dispatchItemAttachmentRows = this.parseJsonArray(
index >= 0 ? row.attachmentsJson : this.dispatchRow.attachmentsJson index >= 0 ? row.attachmentsJson : this.dispatchRow.attachmentsJson
); );
this.selectedDispatchItemAttachmentRows = [];
this.dispatchItemBox = true; this.dispatchItemBox = true;
}, },
handleDispatchCarrierTypeChange(value) { handleDispatchCarrierTypeChange(value) {
@@ -9219,11 +9283,13 @@ export default {
this.dispatchItemIndex = -1; this.dispatchItemIndex = -1;
this.dispatchItemForm = defaultDispatchRow(); this.dispatchItemForm = defaultDispatchRow();
this.dispatchItemAttachmentRows = []; this.dispatchItemAttachmentRows = [];
this.selectedDispatchItemAttachmentRows = [];
}, },
resetDispatchItemDialog() { resetDispatchItemDialog() {
this.dispatchItemIndex = -1; this.dispatchItemIndex = -1;
this.dispatchItemForm = defaultDispatchRow(); this.dispatchItemForm = defaultDispatchRow();
this.dispatchItemAttachmentRows = []; this.dispatchItemAttachmentRows = [];
this.selectedDispatchItemAttachmentRows = [];
}, },
removeDispatchRow(index) { removeDispatchRow(index) {
this.$confirm('确定删除该调度明细?', '提示', { this.$confirm('确定删除该调度明细?', '提示', {
+1 -1
View File
@@ -318,7 +318,7 @@
<el-link <el-link
v-for="action in rowActions(row)" v-for="action in rowActions(row)"
:key="action.type" :key="action.type"
type="primary" :type="action.type === 'delete' ? 'danger' : 'primary'"
@click="handleRowAction(action.type, row)" @click="handleRowAction(action.type, row)"
>{{ action.label }}</el-link> >{{ action.label }}</el-link>
</div> </div>
+33 -3
View File
@@ -46,6 +46,27 @@
</el-button> </el-button>
</template> </template>
<template #menu-form-before="{ disabled }">
<template v-if="!dialogReadonly">
<el-button
plain
:loading="disabled"
:disabled="disabled"
@click="handleProcessConfigSave('draft')"
>
保存草稿
</el-button>
<el-button
type="primary"
:loading="disabled"
:disabled="disabled"
@click="handleProcessConfigSave('enabled')"
>
保存并启用
</el-button>
</template>
</template>
<template #status="{ row }"> <template #status="{ row }">
<el-tag :type="statusTagType(row.status)"> <el-tag :type="statusTagType(row.status)">
{{ row.statusName || displayStatus(row.status) }} {{ row.statusName || displayStatus(row.status) }}
@@ -382,7 +403,7 @@
停用 停用
</el-link> </el-link>
<el-link <el-link
type="primary" type="danger"
v-if="canDelete(row)" v-if="canDelete(row)"
@click="rowDel(row)" @click="rowDel(row)"
> >
@@ -502,6 +523,7 @@ export default {
total: 0, total: 0,
}, },
selectionList: [], selectionList: [],
submitStatus: 1,
}; };
}, },
computed: { computed: {
@@ -870,9 +892,10 @@ export default {
} }
); );
}, },
submitRow(row, done, loading) { submitRow(row, done, loading, status = this.submitStatus) {
this.submitStatus = 1;
this.syncNodeFields(); this.syncNodeFields();
const submitRow = this.normalizeRow(row); const submitRow = this.normalizeRow({ ...row, status });
if (!this.validateRow(submitRow)) { if (!this.validateRow(submitRow)) {
this.stopSubmitLoading(loading); this.stopSubmitLoading(loading);
return; return;
@@ -897,6 +920,12 @@ export default {
rowUpdate(row, index, done, loading) { rowUpdate(row, index, done, loading) {
this.submitRow(row, done, loading); this.submitRow(row, done, loading);
}, },
handleProcessConfigSave(mode) {
this.submitStatus = mode === 'draft' ? 2 : 1;
if (this.$refs.crud && typeof this.$refs.crud.rowSave === 'function') {
this.$refs.crud.rowSave();
}
},
rowDel(row) { rowDel(row) {
this.$confirm('确定将选择数据删除?', { this.$confirm('确定将选择数据删除?', {
confirmButtonText: '确定', confirmButtonText: '确定',
@@ -941,6 +970,7 @@ export default {
}, },
beforeOpen(done, type) { beforeOpen(done, type) {
this.dialogReadonly = type === 'view'; this.dialogReadonly = type === 'view';
this.submitStatus = 1;
if (type === 'add') { if (type === 'add') {
this.form = { this.form = {
configName: '', configName: '',
+20 -6
View File
@@ -78,7 +78,7 @@
> >
{{ operation.label }} {{ operation.label }}
</el-link> </el-link>
<el-link type="primary" v-if="canDelete(row)" @click="rowDel(row)"> 删除 </el-link> <el-link type="danger" v-if="canDelete(row)" @click="rowDel(row)"> 删除 </el-link>
</template> </template>
</avue-crud> </avue-crud>
@@ -481,7 +481,13 @@
show-icon show-icon
:title="`缺少必需材料:${missingRequiredAttachmentTypes.join('、')}`" :title="`缺少必需材料:${missingRequiredAttachmentTypes.join('、')}`"
/> />
<el-table :data="attachmentRows" border class="project-apply-form__material-table"> <el-table
:data="attachmentRows"
border
class="project-apply-form__material-table"
@selection-change="handleAttachmentSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column type="index" label="序号" width="80" align="center" /> <el-table-column type="index" label="序号" width="80" align="center" />
<el-table-column label="附件类型" min-width="160" align="center"> <el-table-column label="附件类型" min-width="160" align="center">
<template #default="{ row }"> <template #default="{ row }">
@@ -515,7 +521,7 @@
<el-table-column label="操作" width="110" align="center"> <el-table-column label="操作" width="110" align="center">
<template #default="{ row, $index }"> <template #default="{ row, $index }">
<el-link type="primary" @click="downloadAttachment(row)">下载</el-link> <el-link type="primary" @click="downloadAttachment(row)">下载</el-link>
<el-link v-if="!dialogReadonly" type="primary" @click="removeAttachment($index)" <el-link v-if="!dialogReadonly" type="danger" @click="removeAttachment($index)"
>删除</el-link >删除</el-link
> >
</template> </template>
@@ -910,11 +916,9 @@ export default {
}, },
], ],
changeContent: [ changeContent: [
{ required: true, message: '请输入变更内容', trigger: 'blur' },
{ max: 2000, message: '变更内容不能超过2000个字符', trigger: 'blur' }, { max: 2000, message: '变更内容不能超过2000个字符', trigger: 'blur' },
], ],
changeReason: [ changeReason: [
{ required: true, message: '请输入变更原因', trigger: 'blur' },
{ max: 2000, message: '变更原因不能超过2000个字符', trigger: 'blur' }, { max: 2000, message: '变更原因不能超过2000个字符', trigger: 'blur' },
], ],
}, },
@@ -937,6 +941,7 @@ export default {
customerRows: [], customerRows: [],
carrierRows: [], carrierRows: [],
attachmentRows: [], attachmentRows: [],
selectedAttachmentRows: [],
attachmentFileTypes: [ attachmentFileTypes: [
'pdf', 'pdf',
'bmp', 'bmp',
@@ -1285,6 +1290,7 @@ export default {
this.customerRows = []; this.customerRows = [];
this.carrierRows = []; this.carrierRows = [];
this.attachmentRows = []; this.attachmentRows = [];
this.selectedAttachmentRows = [];
this.changeRows = []; this.changeRows = [];
this.selectedCustomerId = []; this.selectedCustomerId = [];
this.selectedCarrierIds = []; this.selectedCarrierIds = [];
@@ -1324,6 +1330,7 @@ export default {
this.customerRows = customerRows; this.customerRows = customerRows;
this.carrierRows = carrierRows; this.carrierRows = carrierRows;
this.attachmentRows = this.parseJsonArray(displayRow.attachmentsJson); this.attachmentRows = this.parseJsonArray(displayRow.attachmentsJson);
this.selectedAttachmentRows = [];
this.changeRows = this.buildChangeRows(displayRow); this.changeRows = this.buildChangeRows(displayRow);
this.selectedCustomerId = this.customerRows this.selectedCustomerId = this.customerRows
.map(item => this.getCustomerRowId(item)) .map(item => this.getCustomerRowId(item))
@@ -1791,6 +1798,10 @@ export default {
uploadUserName: item.uploadUserName || userName, uploadUserName: item.uploadUserName || userName,
uploadTime: item.uploadTime || uploadTime, uploadTime: item.uploadTime || uploadTime,
})); }));
this.selectedAttachmentRows = [];
},
handleAttachmentSelectionChange(rows) {
this.selectedAttachmentRows = rows || [];
}, },
removeAttachment(index) { removeAttachment(index) {
this.attachmentRows.splice(index, 1); this.attachmentRows.splice(index, 1);
@@ -1811,7 +1822,10 @@ export default {
downloadFileByUrl(url, row.originalName || row.name || '附件'); downloadFileByUrl(url, row.originalName || row.name || '附件');
}, },
handleBatchDownload() { handleBatchDownload() {
this.attachmentRows.forEach(row => this.downloadAttachment(row)); const rows = this.selectedAttachmentRows.length
? this.selectedAttachmentRows
: this.attachmentRows;
rows.forEach(row => this.downloadAttachment(row));
}, },
handleChangeRecordAction() { handleChangeRecordAction() {
this.$message.info('变更记录详情由后端明细能力生成后展示'); this.$message.info('变更记录详情由后端明细能力生成后展示');
+1 -1
View File
@@ -36,7 +36,7 @@
>流程图 >流程图
</el-link> </el-link>
<el-link <el-link
type="primary" type="danger"
v-if="permission.flow_manager_remove" v-if="permission.flow_manager_remove"
@click.stop="handleSlotDelete(scope.row, scope.index)" @click.stop="handleSlotDelete(scope.row, scope.index)"
>删除 >删除
+1 -1
View File
@@ -51,7 +51,7 @@
>部署 >部署
</el-link> </el-link>
<el-link <el-link
type="primary" type="danger"
size="default" size="default"
v-if="permission.flow_model_delete" v-if="permission.flow_model_delete"
@click.stop="handleSlotDelete(scope.row, scope.index)" @click.stop="handleSlotDelete(scope.row, scope.index)"
+3 -3
View File
@@ -59,7 +59,7 @@
<el-form-item label="名称"> <el-form-item label="名称">
<el-input v-model="carrierQuery.fullName" placeholder="请输入承运商名称" clearable /> <el-input v-model="carrierQuery.fullName" placeholder="请输入承运商名称" clearable />
</el-form-item> </el-form-item>
<el-form-item label="准入标准"> <el-form-item label="准入类型">
<el-select v-model="carrierQuery.accessType" placeholder="全部" clearable> <el-select v-model="carrierQuery.accessType" placeholder="全部" clearable>
<el-option label="临时" value="temporary" /> <el-option label="临时" value="temporary" />
<el-option label="正式" value="formal" /> <el-option label="正式" value="formal" />
@@ -92,7 +92,7 @@
<el-table-column prop="customerNature" label="客户性质" min-width="120" /> <el-table-column prop="customerNature" label="客户性质" min-width="120" />
<el-table-column prop="unifiedCreditCode" label="统一信用代码" min-width="180" /> <el-table-column prop="unifiedCreditCode" label="统一信用代码" min-width="180" />
<el-table-column prop="deptName" label="所属组织" min-width="150" /> <el-table-column prop="deptName" label="所属组织" min-width="150" />
<el-table-column prop="accessType" label="准入标准" min-width="110"> <el-table-column prop="accessType" label="准入类型" min-width="110">
<template #default="{ row }">{{ formatAccessType(row.accessType) }}</template> <template #default="{ row }">{{ formatAccessType(row.accessType) }}</template>
</el-table-column> </el-table-column>
<el-table-column prop="approvalStatus" label="审批状态" min-width="120"> <el-table-column prop="approvalStatus" label="审批状态" min-width="120">
@@ -100,7 +100,7 @@
</el-table-column> </el-table-column>
<el-table-column prop="currentNode" label="当前节点" min-width="130" /> <el-table-column prop="currentNode" label="当前节点" min-width="130" />
<el-table-column prop="currentProcessor" label="当前处理人" min-width="130" /> <el-table-column prop="currentProcessor" label="当前处理人" min-width="130" />
<el-table-column prop="approvedTime" label="审核通过时间" min-width="170" sortable/> <el-table-column prop="approvedTime" label="审核通过时间" min-width="170" sortable />
<el-table-column prop="status" label="状态" width="90"> <el-table-column prop="status" label="状态" width="90">
<template #default="{ row }">{{ Number(row.status) === 1 ? '启用' : '停用' }}</template> <template #default="{ row }">{{ Number(row.status) === 1 ? '启用' : '停用' }}</template>
</el-table-column> </el-table-column>
+1 -1
View File
@@ -97,7 +97,7 @@
</el-link> </el-link>
<el-link <el-link
v-if="this.permissionList.delBtn" v-if="this.permissionList.delBtn"
type="primary" type="danger"
@click="rowDel(row)" @click="rowDel(row)"
>删除 >删除
</el-link> </el-link>
@@ -233,7 +233,7 @@
<span class="score-unit"></span> <span class="score-unit"></span>
</div> </div>
<el-link <el-link
type="primary" type="danger"
class="option-delete" class="option-delete"
v-if="!readonly && itemForm.options.length > 1" v-if="!readonly && itemForm.options.length > 1"
@click="removeOption(index)" @click="removeOption(index)"
+207 -59
View File
@@ -581,20 +581,11 @@
<template #extra> <template #extra>
<div v-if="!readonly" class="section-actions"> <div v-if="!readonly" class="section-actions">
<el-button icon="el-icon-download" @click="downloadAttachments">批量下载</el-button> <el-button icon="el-icon-download" @click="downloadAttachments">批量下载</el-button>
<el-button type="primary" icon="el-icon-plus" @click="addAttachment"
>普通上传</el-button
>
<el-button type="primary" icon="el-icon-upload" @click="addAttachment"> <el-button type="primary" icon="el-icon-upload" @click="addAttachment">
OCR上传识别 OCR上传识别
</el-button> </el-button>
</div> </div>
</template> </template>
<el-alert
type="info"
:closable="false"
title="支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip的文件格式,单个文件大小限制500M"
class="archive-rule-alert"
/>
<el-alert <el-alert
v-if="missingQualificationText" v-if="missingQualificationText"
type="error" type="error"
@@ -602,29 +593,28 @@
:title="missingQualificationText" :title="missingQualificationText"
class="archive-rule-alert" class="archive-rule-alert"
/> />
<el-table :data="qualificationFiles" border> <el-table
:data="qualificationFiles"
border
@selection-change="handleQualificationSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="序号" type="index" width="90" align="center" /> <el-table-column label="序号" type="index" width="90" align="center" />
<el-table-column label="附件类型" min-width="160"> <el-table-column label="附件类型" min-width="160">
<template #default="{ row }"> <template #default="{ row }">
<el-select v-model="row.type" :disabled="readonly" filterable> <el-select v-model="row.type" :disabled="readonly" filterable>
<el-option label="法人身份证" value="法人身份证" /> <el-option
<el-option label="道路运输许可证" value="道路运输许可证" /> v-for="item in qualificationTypeOptions"
<el-option label="其他附件" value="其他附件" /> :key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="文件名称" min-width="180"> <el-table-column label="文件名称" min-width="180">
<template #default="{ row }"> <template #default="{ row }">
<vehicle-attachment-upload <span>{{ row.originalName || row.name || '-' }}</span>
v-model="row.files"
:readonly="readonly"
:multiple="false"
accept=".pdf,.bmp,.jpeg,.png,.jpg,.doc,.docx,.ppt,.pptx,.xlsx,.xls,.eml,.msg,.zip"
:max-size="500"
button-text="上传文件"
:show-tip="false"
@success="file => handleQualificationUploadSuccess(file, row)"
/>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="附件描述" min-width="220"> <el-table-column label="附件描述" min-width="220">
@@ -655,15 +645,59 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div v-if="!readonly" class="qualification-upload-bar">
<vehicle-attachment-upload
v-model="qualificationUploadFiles"
:multiple="true"
:limit="20"
accept=".pdf,.bmp,.jpeg,.png,.jpg,.doc,.docx,.ppt,.pptx,.xlsx,.xls,.eml,.msg,.zip"
:max-size="500"
button-text="上传附件"
:show-tip="false"
:show-file-list="false"
:show-uploading="true"
@success="handleQualificationUploadSuccess"
/>
<span class="qualification-upload-bar__tip">
支持pdf、bmp、jpeg、png、jpg、doc、docx、ppt、pptx、xlsx、xls、eml、msg、zip,单个文件不超过500M
</span>
</div>
</section-card> </section-card>
<section-card title="变更记录"> <section-card title="变更记录">
<el-table :data="archiveForm.changeRecords" border> <el-table :data="changeRecordPage.records" border>
<el-table-column label="序号" type="index" width="90" align="center" /> <el-table-column
label="序号"
type="index"
width="90"
align="center"
:index="changeRecordIndex"
/>
<el-table-column label="变更日期" prop="changeTime" min-width="170" sortable /> <el-table-column label="变更日期" prop="changeTime" min-width="170" sortable />
<el-table-column label="变更内容" prop="changeContent" min-width="260" /> <el-table-column label="变更字段" prop="changedFields" min-width="180" />
<el-table-column
label="原数据"
prop="beforeData"
min-width="240"
show-overflow-tooltip
:formatter="formatChangeData"
/>
<el-table-column
label="修改后数据"
prop="afterData"
min-width="240"
show-overflow-tooltip
:formatter="formatChangeData"
/>
<el-table-column label="变更内容" prop="changeContent" min-width="180" />
<el-table-column label="变更账号" prop="changeUserName" min-width="160" /> <el-table-column label="变更账号" prop="changeUserName" min-width="160" />
</el-table> </el-table>
<empty-pagination
:page="changeRecordPage"
always-show
@size-change="handleChangeRecordSizeChange"
@current-change="handleChangeRecordCurrentChange"
/>
</section-card> </section-card>
<template #footer> <template #footer>
@@ -1067,7 +1101,7 @@
<el-table-column label="得分说明" prop="scoreDescription" min-width="160" /> <el-table-column label="得分说明" prop="scoreDescription" min-width="160" />
<el-table-column label="自评得分" width="130" align="center"> <el-table-column label="自评得分" width="130" align="center">
<template #default="{ row: detail }"> <template #default="{ row: detail }">
<span>{{ formatScoreValue(detail.selfScore) }}分</span> <span>{{ formatScoreValue(getSignedScore(detail, 'selfScore')) }}分</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="复评得分" width="150" align="center"> <el-table-column label="复评得分" width="150" align="center">
@@ -1075,9 +1109,13 @@
<el-input <el-input
v-model="detail.reviewScore" v-model="detail.reviewScore"
maxlength="10" maxlength="10"
inputmode="numeric"
:disabled="readonly || !hasPermission('customer_type_re_cert')" :disabled="readonly || !hasPermission('customer_type_re_cert')"
@input="value => handleScoreDetailScoreInput(detail, 'reviewScore', value)" @input="value => handleScoreDetailScoreInput(detail, 'reviewScore', value)"
> >
<template v-if="isMinusScoreDetail(detail) && Number(detail.reviewScore) > 0" #prefix>
-
</template>
<template #suffix>分</template> <template #suffix>分</template>
</el-input> </el-input>
</template> </template>
@@ -1089,8 +1127,8 @@
<el-table-column min-width="560"> <el-table-column min-width="560">
<template #default="{ row }"> <template #default="{ row }">
<span class="score-category-table__name">{{ row.categoryName }}</span> <span class="score-category-table__name">{{ row.categoryName }}</span>
<span>自评:{{ row.selfScore }}分</span> <span>自评:{{ getSignedScore(row, 'selfScore') }}分</span>
<span>复评:{{ row.reviewScore }}分</span> <span>复评:{{ getSignedScore(row, 'reviewScore') }}分</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column width="60" align="center"> <el-table-column width="60" align="center">
@@ -1113,12 +1151,17 @@
button-text="上传附件" button-text="上传附件"
button-icon="el-icon-upload" button-icon="el-icon-upload"
:show-tip="false" :show-tip="false"
:show-uploading="true"
@success="handleScoreAttachmentUploadSuccess" @success="handleScoreAttachmentUploadSuccess"
/> />
</template> </template>
<el-table :data="scoreAttachmentFiles" border class="score-material-table"> <el-table :data="scoreAttachmentFiles" border class="score-material-table">
<el-table-column label="序号" type="index" width="90" align="center" /> <el-table-column label="序号" type="index" width="90" align="center" />
<el-table-column label="文件名" prop="name" min-width="220" /> <el-table-column label="文件名" min-width="220">
<template #default="{ row }">
{{ row.originalName || row.name || '-' }}
</template>
</el-table-column>
<el-table-column label="附件描述" prop="description" min-width="220" /> <el-table-column label="附件描述" prop="description" min-width="220" />
<el-table-column label="文件大小" min-width="120" align="center"> <el-table-column label="文件大小" min-width="120" align="center">
<template #default="{ row }"> <template #default="{ row }">
@@ -1137,7 +1180,7 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" width="120" align="center" v-if="!readonly"> <el-table-column label="操作" width="120" align="center" v-if="!readonly">
<template #default="{ $index }"> <template #default="{ $index }">
<el-link type="primary" @click="deleteScoreAttachment($index)"> <el-link type="danger" @click="deleteScoreAttachment($index)">
删除 删除
</el-link> </el-link>
</template> </template>
@@ -1164,6 +1207,7 @@
import { import {
getList, getList,
getDetail, getDetail,
getChangeRecordList,
submit, submit,
submitApproval, submitApproval,
withdrawApproval, withdrawApproval,
@@ -1294,6 +1338,13 @@ export default {
pageSize: 10, pageSize: 10,
pageSizes: [10, 20, 50, 100], pageSizes: [10, 20, 50, 100],
}, },
changeRecordPage: {
currentPage: 1,
pageSize: 5,
pageSizes: [5],
total: 0,
records: [],
},
contactIndex: -1, contactIndex: -1,
contactForm: this.emptyContact(), contactForm: this.emptyContact(),
contactMapBox: false, contactMapBox: false,
@@ -1310,6 +1361,8 @@ export default {
invoiceIndex: -1, invoiceIndex: -1,
invoiceForm: this.emptyInvoice(), invoiceForm: this.emptyInvoice(),
qualificationFiles: [], qualificationFiles: [],
qualificationUploadFiles: [],
selectedQualificationFiles: [],
deptTree: [], deptTree: [],
deptOptions: [], deptOptions: [],
regionOptions: [], regionOptions: [],
@@ -1317,6 +1370,7 @@ export default {
customerTypeOptions: [], customerTypeOptions: [],
businessScopeOptions: [], businessScopeOptions: [],
bankListOptions: [], bankListOptions: [],
qualificationTypeOptions: [],
creditLevelOptions: ['A', 'B', 'C', 'D', 'E', 'F'].map(item => ({ creditLevelOptions: ['A', 'B', 'C', 'D', 'E', 'F'].map(item => ({
label: `${item}级`, label: `${item}级`,
value: `${item}级`, value: `${item}级`,
@@ -1643,14 +1697,14 @@ export default {
}, },
scoreTableData() { scoreTableData() {
const start = (this.scorePage.currentPage - 1) * this.scorePage.pageSize; const start = (this.scorePage.currentPage - 1) * this.scorePage.pageSize;
return this.scoreList return this.sortScoresByLatest(this.scoreList)
.slice(start, start + this.scorePage.pageSize) .slice(start, start + this.scorePage.pageSize)
.map((item, index) => ({ .map(({ score, index }, pageIndex) => ({
...item, ...score,
__raw: item, __raw: score,
__rawIndex: start + index, __rawIndex: index,
__index: start + index + 1, __index: start + pageIndex + 1,
maxCreditLimit: item.maxCreditLimit || '', maxCreditLimit: score.maxCreditLimit || '',
})); }));
}, },
contactPaginationPage() { contactPaginationPage() {
@@ -1770,6 +1824,43 @@ export default {
this.handleDetailCurrentChange('receipt', 1); this.handleDetailCurrentChange('receipt', 1);
this.handleDetailCurrentChange('invoice', 1); this.handleDetailCurrentChange('invoice', 1);
}, },
loadChangeRecords() {
if (!this.archiveForm.id) return;
const page = this.changeRecordPage;
getChangeRecordList(this.archiveForm.id, page.currentPage, page.pageSize).then(res => {
const data = res.data.data || {};
page.records = data.records || [];
page.total = Number(data.total || 0);
page.currentPage = Number(data.current || page.currentPage);
});
},
handleChangeRecordCurrentChange(currentPage) {
this.changeRecordPage.currentPage = Number(currentPage) || 1;
this.loadChangeRecords();
},
handleChangeRecordSizeChange(pageSize) {
this.changeRecordPage.pageSize = Number(pageSize) || 5;
this.changeRecordPage.currentPage = 1;
this.loadChangeRecords();
},
resetChangeRecordPage() {
this.changeRecordPage.currentPage = 1;
this.changeRecordPage.total = 0;
this.changeRecordPage.records = [];
},
changeRecordIndex(index) {
return (this.changeRecordPage.currentPage - 1) * this.changeRecordPage.pageSize + index + 1;
},
formatChangeData(row, column, value) {
if (!value) return '-';
try {
return Object.entries(JSON.parse(value))
.map(([field, fieldValue]) => `${field}${fieldValue ?? '-'}`)
.join('');
} catch (error) {
return value;
}
},
emptyContact() { emptyContact() {
return { return {
contactName: '', contactName: '',
@@ -1958,6 +2049,7 @@ export default {
}); });
this.loadDictOptions('scope_of_business', 'businessScopeOptions'); this.loadDictOptions('scope_of_business', 'businessScopeOptions');
this.loadDictOptions('bank_list', 'bankListOptions'); this.loadDictOptions('bank_list', 'bankListOptions');
this.loadDictOptions('customer_attachment_types', 'qualificationTypeOptions');
}, },
initScoreQuantificationOptions() { initScoreQuantificationOptions() {
this.scoreQuantificationLoading = true; this.scoreQuantificationLoading = true;
@@ -2611,7 +2703,8 @@ export default {
.filter(item => item.url) .filter(item => item.url)
.map(item => ({ .map(item => ({
type: String(item.type || '').trim(), type: String(item.type || '').trim(),
name: String(item.name || '').trim(), originalName: String(item.originalName || item.name || '').trim(),
name: String(item.originalName || item.name || '').trim(),
description: String(item.description || '').trim(), description: String(item.description || '').trim(),
size: String(item.size || '').trim(), size: String(item.size || '').trim(),
uploadUserName: String(item.uploadUserName || '').trim(), uploadUserName: String(item.uploadUserName || '').trim(),
@@ -2641,22 +2734,51 @@ export default {
if (mb >= 1) return `${mb.toFixed(2)} MB`; if (mb >= 1) return `${mb.toFixed(2)} MB`;
return `${(byteSize / 1024).toFixed(2)} KB`; return `${(byteSize / 1024).toFixed(2)} KB`;
}, },
handleQualificationUploadSuccess(file, row) { handleQualificationUploadSuccess(file) {
row.name = file.name || row.name || '客商材料'; const originalName = file.originalName || file.name || '客商材料';
row.size = this.formatAttachmentSize(file.size || row.size); this.qualificationFiles.push({
row.uploadUserName = this.userInfo.realName || this.userInfo.userName || ''; type: this.resolveQualificationType(originalName),
row.uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss'); originalName,
row.url = file.url || row.url || ''; name: originalName,
row.files = [file]; description: '',
size: this.formatAttachmentSize(file.size),
uploadUserName: this.userInfo.realName || this.userInfo.userName || '',
uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss'),
url: file.url || file.link || '',
files: [file],
});
},
resolveQualificationType(fileName) {
const name = String(fileName || '').toLocaleLowerCase();
return (
[...this.qualificationTypeOptions]
.filter(item => item?.label || item?.value)
.sort(
(a, b) =>
String(b.label || b.value || '').length - String(a.label || a.value || '').length
)
.find(item => {
const typeText = String(item.label || item.value || '').toLocaleLowerCase();
return typeText && name.includes(typeText);
})?.value || ''
);
}, },
downloadAttachments() { downloadAttachments() {
const files = this.qualificationFiles.filter(item => item.url); const source = this.selectedQualificationFiles.length
? this.selectedQualificationFiles
: this.qualificationFiles;
const files = source.filter(item => item.url);
if (!files.length) { if (!files.length) {
this.$message.warning('暂无可下载附件'); this.$message.warning(
this.selectedQualificationFiles.length ? '所选附件暂无可下载地址' : '暂无可下载附件'
);
return; return;
} }
files.forEach(item => window.open(item.url, '_blank')); files.forEach(item => window.open(item.url, '_blank'));
}, },
handleQualificationSelectionChange(rows) {
this.selectedQualificationFiles = rows || [];
},
normalizeDetail(detail) { normalizeDetail(detail) {
const businessScope = this.splitValue(detail.businessScope); const businessScope = this.splitValue(detail.businessScope);
const registeredDetailAddress = const registeredDetailAddress =
@@ -2723,10 +2845,9 @@ export default {
const time = this.$dayjs(value).valueOf(); const time = this.$dayjs(value).valueOf();
return Number.isFinite(time) ? time : 0; return Number.isFinite(time) ? time : 0;
}, },
getLatestCreditScore(scores = []) { sortScoresByLatest(scores = []) {
return (scores || []) return (scores || [])
.map((score, index) => ({ score, index })) .map((score, index) => ({ score, index }))
.filter(item => String(item.score.creditLevel || '').trim())
.sort((a, b) => { .sort((a, b) => {
const scoreDateDiff = const scoreDateDiff =
this.getScoreTimeValue(b.score.scoreDate) - this.getScoreTimeValue(a.score.scoreDate); this.getScoreTimeValue(b.score.scoreDate) - this.getScoreTimeValue(a.score.scoreDate);
@@ -2738,7 +2859,12 @@ export default {
this.getScoreTimeValue(b.score.createTime) - this.getScoreTimeValue(a.score.createTime); this.getScoreTimeValue(b.score.createTime) - this.getScoreTimeValue(a.score.createTime);
if (createTimeDiff) return createTimeDiff; if (createTimeDiff) return createTimeDiff;
return b.index - a.index; return b.index - a.index;
})[0]?.score; });
},
getLatestCreditScore(scores = []) {
return this.sortScoresByLatest(scores)
.filter(item => String(item.score.creditLevel || '').trim())
[0]?.score;
}, },
applyArchiveCreditFromScores(archive) { applyArchiveCreditFromScores(archive) {
const latestScore = this.getLatestCreditScore(archive.scores || []); const latestScore = this.getLatestCreditScore(archive.scores || []);
@@ -2754,27 +2880,35 @@ export default {
this.readonly = readonly; this.readonly = readonly;
this.activeTab = 'scores'; this.activeTab = 'scores';
this.resetDetailPagination(); this.resetDetailPagination();
this.resetChangeRecordPage();
if (row && row.id) { if (row && row.id) {
getDetail(row.id).then(res => { getDetail(row.id).then(res => {
this.archiveForm = this.normalizeDetail(res.data.data); this.archiveForm = this.normalizeDetail(res.data.data);
this.qualificationFiles = this.parseAttachments( this.qualificationFiles = this.parseAttachments(
this.archiveForm.qualificationAttachments this.archiveForm.qualificationAttachments
); );
this.qualificationUploadFiles = [];
this.archiveBox = true; this.archiveBox = true;
this.loadChangeRecords();
}); });
return; return;
} }
this.archiveForm = this.emptyArchive(); this.archiveForm = this.emptyArchive();
this.qualificationFiles = []; this.qualificationFiles = [];
this.qualificationUploadFiles = [];
this.selectedQualificationFiles = [];
this.archiveBox = true; this.archiveBox = true;
}, },
resetArchive() { resetArchive() {
this.readonly = false; this.readonly = false;
this.archiveForm = this.emptyArchive(); this.archiveForm = this.emptyArchive();
this.qualificationFiles = []; this.qualificationFiles = [];
this.qualificationUploadFiles = [];
this.selectedQualificationFiles = [];
this.scoreBox = false; this.scoreBox = false;
this.resetScoreDialog(); this.resetScoreDialog();
this.resetDetailPagination(); this.resetDetailPagination();
this.resetChangeRecordPage();
this.contactBox = false; this.contactBox = false;
this.contactIndex = -1; this.contactIndex = -1;
this.contactForm = this.emptyContact(); this.contactForm = this.emptyContact();
@@ -3056,13 +3190,9 @@ export default {
this.calculateScore(this.currentScore); this.calculateScore(this.currentScore);
}, },
handleScoreDetailScoreInput(detail, prop, value) { handleScoreDetailScoreInput(detail, prop, value) {
const normalized = String(value || '') const normalized = String(value || '').replace(/\D/g, '');
.replace(/[^\d.]/g, '')
.replace(/^\./, '')
.replace(/(\..*)\./g, '$1')
.replace(/^(\d+)(\.\d{0,2})?.*$/, '$1$2');
if (prop === 'reviewScore' && normalized !== '') { if (prop === 'reviewScore' && normalized !== '') {
const maxScore = this.getScoreItemFullScore(detail); const maxScore = Math.floor(this.getScoreItemFullScore(detail));
if (Number(normalized) > maxScore) { if (Number(normalized) > maxScore) {
detail[prop] = String(maxScore); detail[prop] = String(maxScore);
this.$message.warning( this.$message.warning(
@@ -3112,7 +3242,7 @@ export default {
}, },
getSignedScore(detail, prop) { getSignedScore(detail, prop) {
const score = Number(detail[prop] || 0); const score = Number(detail[prop] || 0);
return this.isMinusScoreDetail(detail) ? -score : score; return this.isMinusScoreDetail(detail) && score > 0 ? -score : score;
}, },
getScoreItemFullScore(detail = {}) { getScoreItemFullScore(detail = {}) {
const itemScore = Number(detail.score); const itemScore = Number(detail.score);
@@ -3220,7 +3350,7 @@ export default {
this.archiveForm.scores.splice(this.scoreRecordIndex, 1, score); this.archiveForm.scores.splice(this.scoreRecordIndex, 1, score);
} else { } else {
this.archiveForm.scores.push(score); this.archiveForm.scores.push(score);
this.handleScoreCurrentChange(this.scorePageCount); this.handleScoreCurrentChange(1);
} }
this.syncArchiveCreditFromScores(); this.syncArchiveCreditFromScores();
this.activeTab = 'scores'; this.activeTab = 'scores';
@@ -3567,6 +3697,24 @@ export default {
margin-bottom: 12px; margin-bottom: 12px;
} }
.qualification-upload-bar {
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
margin-top: 12px;
:deep(.vehicle-attachment-upload) {
width: auto;
}
&__tip {
grid-column: 2;
color: #909399;
font-size: 13px;
text-align: center;
}
}
.archive-tabs { .archive-tabs {
margin-top: 18px; margin-top: 18px;
} }