✨ 完善客商MK审核提交、地区校验与流程实例校验

提交增加 loading,拆分所在地区/详细地址校验,支持 MK 审核跳转,并在已有流程实例时跳过重复提交。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-25 17:45:21 +08:00
parent aa26beda28
commit ee7160e393
3 changed files with 124 additions and 43 deletions
+27
View File
@@ -29,3 +29,30 @@ export const processDelete = data => {
data,
});
};
/**
* 查询 MK 流程实例是否仍存在(有数据则无需删除/重新提交)
* @param {Object} params
* @param {string} params.bizId 业务 id(formInstanceId)
*/
export const hasMkProcessInstance = params => {
return request({
url: '/blade-system/businessProcess/hasMkProcessInstance',
method: 'get',
params,
});
};
/**
* 获取 MK 审批页跳转链接(后端按 thirdParty.mk 配置拼接,含 SSO)
* @param {Object} params
* @param {string} [params.bizId] 业务 id(如客商 id)
* @param {string} [params.processInstanceId] 流程实例 id
*/
export const getMKApprovalUrl = params => {
return request({
url: '/blade-system/businessProcess/getMKApprovalUrl',
method: 'get',
params,
});
};
+12 -1
View File
@@ -1,5 +1,5 @@
import { getDictionary } from '@/api/system/dictbiz';
import { processDelete, processSubmit } from '@/api/system/business-process';
import { hasMkProcessInstance, processDelete, processSubmit } from '@/api/system/business-process';
import { ElMessage } from 'element-plus';
export const MK_BIZ = {
@@ -53,6 +53,12 @@ export function isMkEnabled(list = []) {
return String(matched?.dictKey ?? '').trim() === '1';
}
/** 加载业务字典并判断是否开启 MK */
export async function loadMkEnabled() {
const list = await loadMkTemplateList();
return isMkEnabled(list);
}
export async function resolveMkTemplateCode(dictName, list) {
const dictList = list || (await loadMkTemplateList());
const matched = dictList.find(item => String(item.dictValue || '').trim() === dictName);
@@ -78,6 +84,11 @@ export async function submitMkApprovalFlow({
if (!isMkEnabled(list)) {
return;
}
// 先查 MK 流程实例:已有数据则不删除、不重新提交
const existsRes = await hasMkProcessInstance({ bizId: String(formInstanceId) });
if (existsRes?.data?.data) {
return;
}
if ((conf.rejected || []).includes(approvalStatus)) {
await processDelete({ formInstanceId: String(formInstanceId) });
}
+85 -42
View File
@@ -155,9 +155,21 @@
>
复评
</el-link>
<el-link
type="primary"
v-if="
mkEnabled &&
hasPermission('customer_archive_approve') &&
row.approvalStatus === 'reviewing'
"
@click="handleMkAudit(row)"
>
审核
</el-link>
<el-link
type="success"
v-if="
!mkEnabled &&
hasPermission('customer_archive_approve') &&
row.approvalStatus === 'reviewing' &&
row.reviewStatus === '已完成'
@@ -168,7 +180,11 @@
</el-link>
<el-link
type="warning"
v-if="hasPermission('customer_archive_reject') && row.approvalStatus === 'reviewing'"
v-if="
!mkEnabled &&
hasPermission('customer_archive_reject') &&
row.approvalStatus === 'reviewing'
"
@click="handleReject(row)"
>
审核不通过
@@ -374,7 +390,7 @@
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="所在地区" prop="registeredDetailAddress" required>
<el-form-item label="所在地区" prop="registeredRegionName" required>
<div class="archive-form__address">
<el-cascader
ref="registeredRegionCascader"
@@ -1511,7 +1527,8 @@ import {
getDetail as getCreditScoreQuantificationDetail,
} from '@/api/vehicle/credit-score-quantification';
import { getDictionary } from '@/api/system/dictbiz';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { getMKApprovalUrl } from '@/api/system/business-process';
import { loadMkEnabled, submitMkApprovalFlow } from '@/utils/mk-approval';
import { getDeptTree } from '@/api/system/dept';
import { getLazyTree } from '@/api/base/region';
import { exportBlob } from '@/api/common';
@@ -1608,19 +1625,6 @@ export default {
}
callback();
};
const validateRegisteredAddress = (rule, value, callback) => {
const regionName = (this.archiveForm.registeredRegionName || '').trim();
const detailAddress = String(value || '').trim();
if (!regionName) {
callback(new Error('请选择省市区'));
} else if (!detailAddress) {
callback(new Error('请输入详细地址'));
} else if (detailAddress.length > 255) {
callback(new Error('详细地址最多255个字符'));
} else {
callback();
}
};
return {
form: {},
query: {},
@@ -1749,6 +1753,8 @@ export default {
approved: { label: '审核通过', type: 'success' },
rejected: { label: '审核不通过', type: 'danger' },
},
/** 业务字典 mk_template「开启MK」=1 */
mkEnabled: false,
formRules: {
customerCode: [{ max: 20, message: '客商编号最多20个字符', trigger: 'blur' }],
fullName: [{ required: true, message: '请输入客商名称', trigger: 'blur' }],
@@ -1771,8 +1777,10 @@ export default {
registeredCapital: [{ validator: validateNonNegative, trigger: 'blur' }],
maxCreditLimit: [{ validator: validateNonNegative, trigger: 'blur' }],
applyCreditLimit: [{ validator: validateNonNegative, trigger: 'blur' }],
registeredRegionName: [{ required: true, message: '请选择省市区', trigger: 'change' }],
registeredDetailAddress: [
{ validator: validateRegisteredAddress, trigger: ['change', 'blur'] },
{ required: true, message: '请输入详细地址', trigger: 'blur' },
{ max: 255, message: '详细地址最多255个字符', trigger: 'blur' },
],
businessScope: [
{
@@ -2028,6 +2036,7 @@ export default {
this.initDeptTree();
this.initRegionOptions();
this.initBusinessDictionaries();
this.initMkEnabled();
this.initScoreQuantificationOptions();
if (this.isArchivePage) {
this.reviewMode = this.$route.query.review === '1';
@@ -2863,12 +2872,12 @@ export default {
handleRegisteredRegionChange(value) {
if (!value || !value.length) {
this.archiveForm.registeredRegionName = '';
this.$refs.archiveForm?.validateField('registeredDetailAddress');
this.$refs.archiveForm?.validateField('registeredRegionName');
return;
}
this.$nextTick(() => {
this.archiveForm.registeredRegionName = this.getRegisteredRegionLabels(value).join('');
this.$refs.archiveForm?.validateField('registeredDetailAddress');
this.$refs.archiveForm?.validateField('registeredRegionName');
});
},
handleInvoiceRegisteredRegionChange(value) {
@@ -2899,6 +2908,15 @@ export default {
this.sortQualificationFiles();
});
},
initMkEnabled() {
loadMkEnabled()
.then(enabled => {
this.mkEnabled = !!enabled;
})
.catch(() => {
this.mkEnabled = false;
});
},
initScoreQuantificationOptions() {
this.scoreQuantificationLoading = true;
return getCreditScoreQuantificationList(1, 9999, { status: 1 })
@@ -4206,30 +4224,37 @@ export default {
// 仅提交时落变更记录;保存不记录
archive.recordChange = true;
if (!this.validateScoreForApproval(archive)) return;
submit(archive).then(res => {
const data = res.data.data;
const id = (data && typeof data === 'object' ? data.id : data) || this.archiveForm.id;
if (!id) {
this.closeArchive();
this.onLoad(this.page);
this.$message({ type: 'success', message: '保存成功,请在列表提交审批' });
return;
}
const fullName =
(data && typeof data === 'object' ? data.fullName : '') ||
archive.fullName ||
this.archiveForm.fullName ||
'';
this.submitCustomerApproval(
id,
fullName,
archive.approvalStatus || this.archiveForm.approvalStatus
).then(() => {
this.closeArchive();
this.onLoad(this.page);
this.$message({ type: 'success', message: '提交成功!' });
});
const loading = ElLoading.service({
lock: true,
text: '提交中',
background: 'rgba(255, 255, 255, 0.7)',
});
submit(archive)
.then(res => {
const data = res.data.data;
const id = (data && typeof data === 'object' ? data.id : data) || this.archiveForm.id;
if (!id) {
this.closeArchive();
this.onLoad(this.page);
this.$message({ type: 'success', message: '保存成功,请在列表提交审批' });
return;
}
const fullName =
(data && typeof data === 'object' ? data.fullName : '') ||
archive.fullName ||
this.archiveForm.fullName ||
'';
return this.submitCustomerApproval(
id,
fullName,
archive.approvalStatus || this.archiveForm.approvalStatus
).then(() => {
this.closeArchive();
this.onLoad(this.page);
this.$message({ type: 'success', message: '提交成功!' });
});
})
.finally(() => loading.close());
});
},
/**
@@ -4928,6 +4953,24 @@ export default {
this.$message({ type: 'success', message: '已撤回至草稿状态!' });
});
},
handleMkAudit(row) {
if (!row?.id) {
this.$message.warning('客商ID为空,无法打开审核页');
return;
}
getMKApprovalUrl({ bizId: String(row.id) })
.then(res => {
const url = res?.data?.data;
if (!url) {
this.$message.error('获取审核跳转地址失败');
return;
}
window.open(url, '_blank');
})
.catch(() => {
this.$message.error('获取审核跳转地址失败');
});
},
handleApprove(row) {
this.$confirm('是否确认审核通过?', '提示', {
confirmButtonText: '确定',