This commit is contained in:
2026-09-21 11:14:51 +08:00
parent 7078de6385
commit 57368f0179
15 changed files with 647 additions and 39 deletions
+23
View File
@@ -0,0 +1,23 @@
import request from '@/axios';
export const getMkPublicDetail = (bizType, id) => {
return request({
url: `/blade-transport/mk-process/public/${bizType}/detail`,
method: 'get',
meta: {
isToken: false,
},
params: { id },
});
};
export const postMkPublicProcessMessage = (bizType, data) => {
return request({
url: `/blade-transport/mk-process/public/${bizType}/process-message`,
method: 'post',
meta: {
isToken: false,
},
data,
});
};
+13
View File
@@ -16,3 +16,16 @@ export const processSubmit = data => {
data,
});
};
/**
* 调用 MK processDelete 删除审核流(驳回后重新提交前使用)
* @param {Object} data
* @param {string} data.formInstanceId 业务表单实例 id
*/
export const processDelete = data => {
return request({
url: '/blade-system/businessProcess/processDelete',
method: 'post',
data,
});
};
+66
View File
@@ -84,6 +84,72 @@ export default [
isAuth: false,
},
},
{
path: '/business/project-apply/public-view',
name: '查看项目信息',
component: () => import('@/views/mk/public-biz-view.vue'),
meta: {
keepAlive: false,
isTab: false,
isAuth: false,
bizType: 'project-apply',
},
},
{
path: '/business/contract-manage/public-view',
name: '查看合同信息',
component: () => import('@/views/mk/public-biz-view.vue'),
meta: {
keepAlive: false,
isTab: false,
isAuth: false,
bizType: 'contract-manage',
},
},
{
path: '/business/waybill-manage/public-view',
name: '查看运单信息',
component: () => import('@/views/mk/public-biz-view.vue'),
meta: {
keepAlive: false,
isTab: false,
isAuth: false,
bizType: 'waybill-manage',
},
},
{
path: '/settlement/pre-settlement/public-view',
name: '查看预结算信息',
component: () => import('@/views/mk/public-biz-view.vue'),
meta: {
keepAlive: false,
isTab: false,
isAuth: false,
bizType: 'pre-settlement',
},
},
{
path: '/settlement/formal-settlement/public-view',
name: '查看正式结算信息',
component: () => import('@/views/mk/public-biz-view.vue'),
meta: {
keepAlive: false,
isTab: false,
isAuth: false,
bizType: 'formal-settlement',
},
},
{
path: '/payment/payment-application/public-view',
name: '查看付款申请信息',
component: () => import('@/views/mk/public-biz-view.vue'),
meta: {
keepAlive: false,
isTab: false,
isAuth: false,
bizType: 'payment-application',
},
},
{
path: '/',
name: '主页',
+78
View File
@@ -0,0 +1,78 @@
import { getDictionary } from '@/api/system/dictbiz';
import { processDelete, processSubmit } from '@/api/system/business-process';
import { ElMessage } from 'element-plus';
export const MK_BIZ = {
'customer-archive': {
dictName: '提交客商审核流',
subjectPrefix: '客商准入审批',
rejected: ['rejected'],
},
'project-apply': {
dictName: '提交项目审核流',
subjectPrefix: '项目审批',
rejected: ['rejected', 'change_rejected', 'withdrawn'],
},
'contract-manage': {
dictName: '提交合同审核流',
subjectPrefix: '合同审批',
rejected: ['rejected', 'change_rejected', 'withdrawn'],
},
'waybill-manage': {
dictName: '提交运单审核流',
subjectPrefix: '运单审批',
rejected: ['rejected', 'returned'],
},
'pre-settlement': {
dictName: '提交预结算审核流',
subjectPrefix: '预结算审批',
rejected: ['returned'],
},
'formal-settlement': {
dictName: '提交正式结算审核流',
subjectPrefix: '正式结算审批',
rejected: ['returned'],
},
'payment-application': {
dictName: '提交付款审核流',
subjectPrefix: '付款审批',
rejected: ['returned'],
},
};
export async function resolveMkTemplateCode(dictName) {
const res = await getDictionary({ code: 'mk_template' });
const list = res?.data?.data || [];
const matched = list.find(item => String(item.dictValue || '').trim() === dictName);
const templateCode = matched?.dictKey;
if (!templateCode) {
ElMessage.warning(`未配置业务字典 mk_template「${dictName}」,无法提交审核流`);
return Promise.reject(new Error(`未配置业务字典 mk_template「${dictName}`));
}
return String(templateCode);
}
export async function submitMkApprovalFlow({
bizType,
formInstanceId,
subjectName = '',
approvalStatus = '',
}) {
const conf = MK_BIZ[bizType];
if (!conf) {
return Promise.reject(new Error(`不支持的MK业务类型:${bizType}`));
}
if ((conf.rejected || []).includes(approvalStatus)) {
await processDelete({ formInstanceId: String(formInstanceId) });
}
const templateCode = await resolveMkTemplateCode(conf.dictName);
const subject = subjectName
? `${conf.subjectPrefix}${subjectName}`
: `${conf.subjectPrefix}${formInstanceId}`;
return processSubmit({
templateCode,
formInstanceId: String(formInstanceId),
subject,
bizType,
});
}
@@ -3128,6 +3128,7 @@ import { getDictionary as getSystemDictionary } from '@/api/system/dict';
import { addressTypeOptions } from '@/option/base/common-address';
import { packageOptions } from '@/option/business/common';
import { formatUpdateUserName } from '@/utils/audit';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { getToken } from '@/utils/auth';
import { openImportDialog } from '@/utils/import-excel';
import { applyTableMenuWidth } from '@/utils/table-menu';
@@ -5521,11 +5522,23 @@ export default {
return;
}
this.getSaveRequest()(submitRow).then(
() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
if (this.isStandaloneWaybillPage) this.closeCrudDialog();
res => {
const data = res.data?.data || {};
const id = data.id || submitRow.id;
const after = id
? submitMkApprovalFlow({
bizType: 'waybill-manage',
formInstanceId: id,
subjectName: data.waybillNo || submitRow.waybillNo || '',
approvalStatus: data.approvalStatus || submitRow.approvalStatus || '',
})
: Promise.resolve();
return after.then(() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '提交成功!' });
done();
if (this.isStandaloneWaybillPage) this.closeCrudDialog();
});
},
error => {
window.console.log(error);
@@ -5544,12 +5557,26 @@ export default {
? this.api.updateAttachments
: this.getSaveRequest();
request(submitRow).then(
() => {
this.attachmentUploadMode = false;
this.onLoad(this.page);
this.$message({ type: 'success', message: '操作成功!' });
done();
if (this.isStandaloneWaybillPage) this.closeCrudDialog();
res => {
const skipMk = this.attachmentUploadMode;
const data = res.data?.data || {};
const id = data.id || submitRow.id;
const after =
skipMk || !id
? Promise.resolve()
: submitMkApprovalFlow({
bizType: 'waybill-manage',
formInstanceId: id,
subjectName: data.waybillNo || submitRow.waybillNo || '',
approvalStatus: data.approvalStatus || submitRow.approvalStatus || '',
});
return after.then(() => {
this.attachmentUploadMode = false;
this.onLoad(this.page);
this.$message({ type: 'success', message: skipMk ? '操作成功!' : '提交成功!' });
done();
if (this.isStandaloneWaybillPage) this.closeCrudDialog();
});
},
error => {
this.attachmentUploadMode = false;
@@ -302,6 +302,7 @@
<script>
import * as api from '@/api/business/contract-manage';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import BillingPlanEditor from './components/billing-plan-editor.vue';
import ContractAttachmentSection, {
normalizeContractFileRows,
@@ -629,7 +630,7 @@ export default {
removeCustomPeriodRow(index) { if (index <= 0) return; const periods = [...(this.settlementRule.customPeriods || [])]; periods.splice(index, 1); this.settlementRule.customPeriods = normalizeCustomPeriods(periods); },
validateCustomPeriods(periods = [], label) { const rows = normalizeCustomPeriods(periods); if (!rows.length) { this.$message.warning(`${label}:请至少配置一段自定义周期`); return false; } for (let index = 0; index < rows.length; index += 1) { const row = rows[index]; const startDay = Number(row.startDay); const endDay = Number(row.endDay); if (!Number.isFinite(startDay) || startDay < 1 || startDay > 31) { this.$message.warning(`${label}:请选择第${index + 1}行运单区间开始日`); return false; } if (!Number.isFinite(endDay) || endDay < 1 || endDay > 31) { this.$message.warning(`${label}:请选择第${index + 1}行运单区间结束日`); return false; } if (endDay < startDay) { this.$message.warning(`${label}:第${index + 1}行结束日不能早于开始日`); return false; } if (index > 0 && startDay !== Number(rows[index - 1].endDay) + 1) { this.$message.warning(`${label}:自定义多周期区间必须连续,不允许重叠或存在日期缺口`); return false; } } return true; },
validateSettlementRule(rule, label) { if (Number(rule.autoGenerate) !== 1) return true; if (!rule.billStartDate || !rule.settlementType) { this.$message.warning(`${label}:请完整填写账单起始日期和结算类型`); return false; } if (rule.settlementType === '月结' && !rule.billCycleType) { this.$message.warning(`${label}:请选择结算周期`); return false; } if (rule.settlementType === '月结' && rule.billCycleType === '固定截单日' && !rule.billCutoffDay) { this.$message.warning(`${label}:请选择账单截单日`); return false; } if (rule.settlementType === '月结' && rule.billCycleType === '自定义多周期') return this.validateCustomPeriods(rule.customPeriods, label); if (rule.settlementType === '固定天数周期结算' && !rule.cycleDays) { this.$message.warning(`${label}:请选择周期天数`); return false; } return true; },
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } if (this.settlementConfigTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; else this.formalSettlementConfig = { ...this.settlementRule }; if (!this.validateSettlementRule(this.preSettlementConfig, '预结算配置') || !this.validateSettlementRule(this.formalSettlementConfig, '正式结算配置')) return; const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, settlementCurrency: String(this.form.settlementCurrency || '').trim() || 'RMB', copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), invoiceCycle: normalizeOptionalPositiveInteger(this.form.invoiceCycle), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), contractAmount: normalizeOptionalAmount(this.form.contractAmount), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeContent, changeReason: this.form.changeReason, changeAttachmentsJson: JSON.stringify(this.changeMaterials) }); this.$message.success('变更已提交'); this.$router.back(); },
async submit() { await this.$refs.formRef.validate(); const total = this.paymentRatioRows.reduce((sum, row) => sum + Number(row.ratioLimit || 0), 0); if (this.paymentRatioRows.length && Math.abs(total - 100) > 0.0001) { this.$message.warning('付款比例上限合计必须等于100%'); return; } if (this.settlementConfigTab === 'pre') this.preSettlementConfig = { ...this.settlementRule }; else this.formalSettlementConfig = { ...this.settlementRule }; if (!this.validateSettlementRule(this.preSettlementConfig, '预结算配置') || !this.validateSettlementRule(this.formalSettlementConfig, '正式结算配置')) return; const settlementRule = { preSettlementConfig: this.preSettlementConfig, formalSettlementConfig: this.formalSettlementConfig }; await api.submitChange({ ...this.form, settlementCurrency: String(this.form.settlementCurrency || '').trim() || 'RMB', copyCount: normalizeOptionalPositiveInteger(this.form.copyCount), invoiceCycle: normalizeOptionalPositiveInteger(this.form.invoiceCycle), paymentDays: normalizeOptionalPositiveInteger(this.form.paymentDays), contractAmount: normalizeOptionalAmount(this.form.contractAmount), startDate: this.period[0], endDate: this.period[1], feeGenerationMode: this.feeGenerationMode, billingEnabled: this.feeGenerationMode === 'system' ? 1 : 0, billingPlanJson: JSON.stringify(this.plans), settlementRuleJson: JSON.stringify(settlementRule), preSettlementConfigJson: JSON.stringify(this.preSettlementConfig), formalSettlementConfigJson: JSON.stringify(this.formalSettlementConfig), paymentRatioJson: JSON.stringify(this.paymentRatioRows), contractFileJson: JSON.stringify(this.contractFileRows), attachmentsJson: JSON.stringify(this.attachments), changeContent: this.form.changeContent, changeReason: this.form.changeReason, changeAttachmentsJson: JSON.stringify(this.changeMaterials) }); await submitMkApprovalFlow({ bizType: 'contract-manage', formInstanceId: this.form.id, subjectName: this.form.contractName || '', approvalStatus: this.form.approvalStatus || 'change_rejected' }); this.$message.success('变更已提交'); this.$router.back(); },
},
};
</script>
+38 -5
View File
@@ -1035,6 +1035,7 @@ import { getDictionary as getBizDictionary } from '@/api/system/dictbiz';
import { config, option } from '@/option/business/contract-manage';
import { getToken } from '@/utils/auth';
import { downloadFileByUrl, downloadXls } from '@/utils/util';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import BillingPlanEditor from './components/billing-plan-editor.vue';
import ContractAttachmentSection, {
attachmentName as sharedAttachmentName,
@@ -1824,9 +1825,17 @@ export default {
const id = saved.id || this.form.id;
if (action === 'temporary' || action === 'formal') {
if (!id) throw new Error('合同保存成功但未返回主键,无法提交合同');
return action === 'temporary'
return (action === 'temporary'
? this.api.toTemporary(id)
: this.api.submitFormal(id);
: this.api.submitFormal(id)
).then(() =>
submitMkApprovalFlow({
bizType: 'contract-manage',
formInstanceId: id,
subjectName: saved.contractName || submit.contractName || '',
approvalStatus: saved.approvalStatus || submit.approvalStatus || '',
})
);
}
return null;
})
@@ -1853,8 +1862,20 @@ export default {
: this.api.submit(payload);
request
.then(() => {
this.$message.success(isChangeRejected ? '已重新提交变更审批' : '修改成功');
this.closeForm();
if (!isChangeRejected) {
this.$message.success('修改成功');
this.closeForm();
return;
}
return submitMkApprovalFlow({
bizType: 'contract-manage',
formInstanceId: payload.id || this.form.id,
subjectName: payload.contractName || this.form.contractName || '',
approvalStatus: this.form.approvalStatus || 'change_rejected',
}).then(() => {
this.$message.success('已重新提交变更审批');
this.closeForm();
});
})
.finally(() => {
this.submitAction = '';
@@ -2698,7 +2719,19 @@ export default {
}
const run = value => {
const args = operation.prompt ? [row.id, value] : [row.id];
this.api[operation.action](...args).then(() => {
const request = () => this.api[operation.action](...args);
const afterMk =
operation.action === 'submitFormal'
? request().then(() =>
submitMkApprovalFlow({
bizType: 'contract-manage',
formInstanceId: row.id,
subjectName: row.contractName || '',
approvalStatus: row.approvalStatus || '',
})
)
: request();
afterMk.then(() => {
this.$message.success(operation.successMessage || `${operation.label}成功`);
this.onLoad(this.page, this.query);
});
+49 -7
View File
@@ -925,6 +925,7 @@ import { getDictionary as getBizDictionary } from '@/api/system/dictbiz';
import { getList as getUserList } from '@/api/system/user';
import { getToken } from '@/utils/auth';
import { downloadFileByUrl, downloadXls } from '@/utils/util';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import { ElImageViewer } from 'element-plus';
import { OpenFileViewer } from '@open-file-viewer/vue';
import PdfPreview from '@/components/pdf-preview/main.vue';
@@ -1589,7 +1590,17 @@ export default {
}
const run = value => {
const args = operation.prompt ? [row.id, value] : [row.id];
this.api[operation.action](...args).then(res => {
const request = () => this.api[operation.action](...args);
const afterMk =
operation.action === 'submitApproval'
? submitMkApprovalFlow({
bizType: 'project-apply',
formInstanceId: row.id,
subjectName: row.projectName || '',
approvalStatus: row.approvalStatus || '',
}).then(() => request())
: request();
afterMk.then(res => {
if (res.data?.success === false || res.data?.data === false) {
this.$message.error(res.data?.msg || `${operation.label}失败,请联系管理员`);
return;
@@ -1757,9 +1768,26 @@ export default {
this.$message.error(res.data?.msg || '保存失败,请联系管理员');
return;
}
this.$message.success('操作成功!');
this.closeProjectForm();
this.onLoad(this.page, this.query);
const data = res.data?.data || {};
const id = data.id || this.form.id;
const name = data.projectName || this.form.projectName || '';
const status = data.approvalStatus || this.form.approvalStatus || '';
if (!id) {
this.$message.success('操作成功!');
this.closeProjectForm();
this.onLoad(this.page, this.query);
return;
}
return submitMkApprovalFlow({
bizType: 'project-apply',
formInstanceId: id,
subjectName: name,
approvalStatus: status,
}).then(() => {
this.$message.success('提交成功!');
this.closeProjectForm();
this.onLoad(this.page, this.query);
});
},
error => {
window.console.log(error);
@@ -1827,9 +1855,23 @@ export default {
);
return;
}
this.$message.success(`${needSubmit ? '提交' : '保存'}成功!`);
this.closeProjectForm();
this.onLoad(this.page, this.query);
if (!needSubmit) {
this.$message.success('保存成功!');
this.closeProjectForm();
this.onLoad(this.page, this.query);
return;
}
const id = this.form.id;
return submitMkApprovalFlow({
bizType: 'project-apply',
formInstanceId: id,
subjectName: this.form.projectName || '',
approvalStatus: this.form.approvalStatus || 'change_rejected',
}).then(() => {
this.$message.success('提交成功!');
this.closeProjectForm();
this.onLoad(this.page, this.query);
});
})
.finally(() => {
this.submitLoading = false;
+271
View File
@@ -0,0 +1,271 @@
<template>
<div ref="page" class="mk-public-biz-view">
<basic-container>
<div class="mk-public-biz-view__title">{{ pageTitle }}</div>
<el-descriptions v-if="detail" :column="2" border>
<el-descriptions-item
v-for="item in visibleFields"
:key="item.prop"
:label="item.label"
:span="item.span || 1"
>
{{ displayValue(detail[item.prop]) }}
</el-descriptions-item>
</el-descriptions>
<el-empty v-else description="暂无数据" />
</basic-container>
</div>
</template>
<script>
import { getMkPublicDetail, postMkPublicProcessMessage } from '@/api/mk-process';
const FIELD_MAP = {
'project-apply': [
{ label: '申请单号', prop: 'applyNo' },
{ label: '项目编号', prop: 'projectCode' },
{ label: '项目名称', prop: 'projectName', span: 2 },
{ label: '审核状态', prop: 'approvalStatusName' },
{ label: '当前节点', prop: 'currentNode' },
{ label: '当前处理人', prop: 'currentProcessor' },
{ label: '所属组织', prop: 'deptName' },
{ label: '备注', prop: 'remark', span: 2 },
],
'contract-manage': [
{ label: '合同编号', prop: 'contractNo' },
{ label: '合同名称', prop: 'contractName', span: 2 },
{ label: '合同类别', prop: 'contractCategory' },
{ label: '审核状态', prop: 'approvalStatusName' },
{ label: '当前节点', prop: 'currentNode' },
{ label: '当前处理人', prop: 'currentProcessor' },
{ label: '甲方', prop: 'partyA' },
{ label: '乙方', prop: 'partyB' },
{ label: '项目名称', prop: 'projectName', span: 2 },
],
'waybill-manage': [
{ label: '运单号', prop: 'waybillNo' },
{ label: '项目', prop: 'projectName' },
{ label: '客户合同', prop: 'contractName' },
{ label: '客户名称', prop: 'customerName' },
{ label: '货物名称', prop: 'cargoName' },
{ label: '承运商', prop: 'carrierName' },
{ label: '当前过程节点', prop: 'currentProcessNode' },
{ label: '发货地', prop: 'departureName' },
{ label: '收货地', prop: 'arrivalName' },
],
'pre-settlement': [
{ label: '预结算单号', prop: 'preSettlementNo' },
{ label: '合同名称', prop: 'contractName' },
{ label: '项目名称', prop: 'projectName' },
{ label: '结算金额', prop: 'settlementAmount' },
{ label: '审核状态', prop: 'approvalStatusName' },
{ label: '当前节点', prop: 'currentNode' },
{ label: '当前处理人', prop: 'currentProcessor' },
{ label: '备注', prop: 'remark', span: 2 },
],
'formal-settlement': [
{ label: '正式结算单号', prop: 'formalSettlementNo' },
{ label: '预结算单号', prop: 'preSettlementNos' },
{ label: '项目名称', prop: 'projectName' },
{ label: '合同名称', prop: 'contractName' },
{ label: '结算金额', prop: 'settlementAmount' },
{ label: '审核状态', prop: 'approvalStatusName' },
{ label: '当前节点', prop: 'currentNode' },
{ label: '当前处理人', prop: 'currentProcessor' },
],
'payment-application': [
{ label: '付款申请号', prop: 'paymentNo' },
{ label: '付款类型', prop: 'paymentTypeName' },
{ label: '收款方', prop: 'payeeName' },
{ label: '项目名称', prop: 'projectName' },
{ label: '申请金额', prop: 'applyAmount' },
{ label: '审核状态', prop: 'approvalStatusName' },
{ label: '当前节点', prop: 'currentNode' },
{ label: '当前处理人', prop: 'currentProcessor' },
],
};
const TITLE_MAP = {
'project-apply': '查看项目信息',
'contract-manage': '查看合同信息',
'waybill-manage': '查看运单信息',
'pre-settlement': '查看预结算信息',
'formal-settlement': '查看正式结算信息',
'payment-application': '查看付款申请信息',
};
export default {
name: 'MkPublicBizView',
data() {
return {
detail: null,
};
},
computed: {
bizType() {
return this.$route.meta.bizType || this.$route.query.bizType || '';
},
pageTitle() {
return TITLE_MAP[this.bizType] || '查看详情';
},
visibleFields() {
return FIELD_MAP[this.bizType] || [];
},
},
created() {
this.handleIframeHeight = () => this.sendIframeHeight();
this.handleProcessMessage = event => this.onProcessMessage(event);
document.addEventListener('DOMContentLoaded', this.handleIframeHeight, false);
window.addEventListener('message', this.handleProcessMessage);
},
mounted() {
document.documentElement.classList.add('mk-iframe-page');
document.body.classList.add('mk-iframe-page');
const app = document.getElementById('app');
if (app) app.classList.add('mk-iframe-page');
this.loadDetail();
this.handleIframeHeight();
window.addEventListener('load', this.handleIframeHeight);
this.mkHeightTimers = [300, 800, 1600].map(delay => setTimeout(this.handleIframeHeight, delay));
if (typeof ResizeObserver === 'undefined') return;
this.mkHeightObserver = new ResizeObserver(() => this.handleIframeHeight());
this.$nextTick(() => {
if (this.$refs.page) this.mkHeightObserver.observe(this.$refs.page);
this.mkHeightObserver.observe(document.body);
});
},
beforeUnmount() {
document.removeEventListener('DOMContentLoaded', this.handleIframeHeight, false);
window.removeEventListener('load', this.handleIframeHeight);
window.removeEventListener('message', this.handleProcessMessage);
(this.mkHeightTimers || []).forEach(timer => clearTimeout(timer));
if (this.mkHeightObserver) {
this.mkHeightObserver.disconnect();
this.mkHeightObserver = null;
}
document.documentElement.classList.remove('mk-iframe-page');
document.body.classList.remove('mk-iframe-page');
const app = document.getElementById('app');
if (app) app.classList.remove('mk-iframe-page');
},
methods: {
loadDetail() {
const id = this.getFormId();
if (!id || !this.bizType) return;
getMkPublicDetail(this.bizType, id).then(res => {
this.detail = res.data?.data || null;
this.handleIframeHeight();
});
},
sendIframeHeight() {
this.$nextTick(() => {
window.parent.postMessage({ height: document.body.clientHeight }, '*');
});
},
onProcessMessage(event) {
const data = event && event.data;
if (!data || typeof data !== 'object') return;
if (data.height && !data.status && !data.type) return;
if (data.type === 'formValues' || data.type === 'afterSubmit') return;
const formValues = data.formValues;
if (data.status === 'submit') {
this.submitData(formValues);
} else if (data.status === 'save') {
this.saveData(formValues);
}
if (data.type === 'getFormValues') {
window.parent.postMessage({ type: 'formValues', formData: this.buildFormData() }, '*');
}
},
submitData(lbpmFormValues) {
const formData = this.buildFormData();
this.postFormData('submit', lbpmFormValues, formData);
if (!lbpmFormValues) return;
const parameters = Object.assign({}, lbpmFormValues, {
loginName: this.getLoginName(lbpmFormValues),
formInstanceId: this.getFormId(),
subject: formData.subject,
});
window.parent.postMessage({ type: 'afterSubmit', success: true, parameters }, '*');
},
saveData(lbpmFormValues) {
this.postFormData('save', lbpmFormValues, this.buildFormData());
},
postFormData(status, formValues, formData) {
const payload = { status, formValues: formValues || {}, formData };
postMkPublicProcessMessage(this.bizType, payload).catch(error => {
console.error('公开页提交流程数据失败:', error);
});
},
buildFormData() {
const detail = this.detail || {};
return {
...detail,
id: this.getFormId() || detail.id,
subject: this.pageTitle,
formInstanceId: this.getFormId(),
};
},
getFormId() {
return this.$route.query.id || this.detail?.id || '';
},
getLoginName(formValues = {}) {
return (
formValues.loginName ||
this.$route.query.loginName ||
this.$route.query.submitIdentity ||
''
);
},
displayValue(value) {
if (value === null || value === undefined || value === '') return '-';
if (Array.isArray(value)) return value.join('、') || '-';
if (typeof value === 'object') return JSON.stringify(value);
return value;
},
},
};
</script>
<style lang="scss">
html.mk-iframe-page,
html.mk-iframe-page body,
html.mk-iframe-page #app,
html.mk-iframe-page #app.mk-iframe-page {
height: auto !important;
min-height: 100%;
overflow: visible;
}
</style>
<style lang="scss" scoped>
.mk-public-biz-view {
min-height: 100%;
padding: 12px 0 24px;
box-sizing: border-box;
background: #f0f2f5;
:deep(.basic-container) {
padding: 0 12px;
}
&__title {
position: relative;
padding-left: 12px;
margin: 8px 0 16px;
font-size: 16px;
font-weight: 600;
line-height: 22px;
&::before {
content: '';
position: absolute;
left: 0;
top: 2px;
width: 4px;
height: 18px;
background: #409eff;
}
}
}
</style>
@@ -608,6 +608,7 @@ import {
} from '@/api/vehicle/customer-archive';
import { readSettlementTransfer, removeSettlementTransfer } from '@/utils/settlement-transfer';
import { downloadFileByUrl } from '@/utils/util';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import PdfPreview from '@/components/pdf-preview/main.vue';
const attachmentViewerPlugins = [
@@ -2354,6 +2355,12 @@ export default {
const saved = await this.saveDraft(true);
if (!saved) return;
await api.submit({ id: this.form.id });
await submitMkApprovalFlow({
bizType: 'payment-application',
formInstanceId: this.form.id,
subjectName: this.form.paymentNo || '',
approvalStatus: this.form.approvalStatus || '',
});
this.$message.success('提交成功');
this.goBack();
},
@@ -233,6 +233,7 @@ import { mapGetters } from 'vuex';
import * as api from '@/api/payment/paymentApplication';
import { paymentApplicationTableColumns } from '@/option/payment/paymentApplication';
import organizationSearch from '@/mixins/organization-search';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
const emptyQuery = () => ({
paymentNo: '',
@@ -361,6 +362,12 @@ export default {
},
async handleSubmit(row) {
await api.submit({ id: row.id });
await submitMkApprovalFlow({
bizType: 'payment-application',
formInstanceId: row.id,
subjectName: row.paymentNo || '',
approvalStatus: row.approvalStatus || '',
});
this.$message.success('提交成功');
this.loadTable();
},
@@ -955,6 +955,7 @@ import {
settlementSummaryColumns,
} from '@/option/settlement/preSettlementTable';
import { downloadFileByUrl } from '@/utils/util';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
import * as XLSX from 'xlsx';
export default {
@@ -1553,6 +1554,12 @@ export default {
await this.persistPendingAdjustments();
if (shouldSubmit) {
await submit({ id: this.form.id });
await submitMkApprovalFlow({
bizType: 'pre-settlement',
formInstanceId: this.form.id,
subjectName: this.form.preSettlementNo || this.form.contractName || '',
approvalStatus: this.form.approvalStatus || '',
});
this.$message.success('审批流程已发起');
this.visible = false;
this.$emit('success', this.form.id);
@@ -182,6 +182,7 @@ import organizationSearch from '@/mixins/organization-search';
import { formalSettlementTableColumns } from '@/option/settlement/formalSettlementTable';
import FormalSettlementEditor from './components/formal-settlement-editor.vue';
import FormalSettlementTablePanel from './components/formal-settlement-table-panel.vue';
import { submitMkApprovalFlow } from '@/utils/mk-approval';
const emptyQuery = () => ({
formalSettlementNo: '',
@@ -337,6 +338,12 @@ export default {
async handleSubmit(row) {
await this.$confirm('提交后来源预结算将保持锁定,确认提交?', '提示', { type: 'warning' });
await api.submit({ id: row.id });
await submitMkApprovalFlow({
bizType: 'formal-settlement',
formInstanceId: row.id,
subjectName: row.formalSettlementNo || '',
approvalStatus: row.approvalStatus || '',
});
this.$message.success('提交成功');
this.loadTable();
},
+18 -6
View File
@@ -198,6 +198,17 @@
<el-form ref="userFormRef" :model="form" :rules="userRules" label-position="right" label-width="calc(6em + 24px)">
<el-row :gutter="18">
<el-col :span="6"><el-form-item label="账号名" prop="account"><el-input v-model="form.account" /></el-form-item></el-col>
<el-col v-if="userDialogMode === 'add'" :span="6">
<el-form-item label="登录密码" prop="password">
<el-input
v-model="form.password"
type="password"
show-password
autocomplete="new-password"
placeholder="请输入登录密码"
/>
</el-form-item>
</el-col>
<el-col :span="6"><el-form-item label="姓名" prop="realName"><el-input v-model="form.realName" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="手机号" prop="phone"><el-input v-model="form.phone" /></el-form-item></el-col>
<el-col :span="6"><el-form-item label="邮箱"><el-input v-model="form.email" /></el-form-item></el-col>
@@ -544,19 +555,16 @@ export default {
}
return undefined;
},
// 所属组织级联配置:checkStrictly 为 false 时只能选择最后一级(叶子节点)
// 所属组织级联配置:checkStrictly 为 true 时任意一级都可选择
deptCascaderProps() {
return {
label: 'title',
value: 'id',
children: 'children',
emitPath: false,
checkStrictly: false,
checkStrictly: true,
expandTrigger: 'click',
leaf: (data, node) => {
// 判断是否为叶子节点:没有 children 或 children 为空数组
return !data.children || data.children.length === 0;
},
leaf: data => !data.children || data.children.length === 0,
};
},
// 所属组织为单选级联:form.deptId 为数组(提交时 join),级联返回单个 id 值
@@ -835,6 +843,7 @@ export default {
if (mode === 'add') {
this.form = {
account: '',
password: '',
realName: '',
phone: '',
email: '',
@@ -890,6 +899,9 @@ export default {
roleId: func.join(this.form.roleId),
leaderId: func.join(this.form.leaderId),
};
if (this.userDialogMode !== 'add') {
delete row.password;
}
const request = this.userDialogMode === 'add' ? add(row) : update(this.sensitiveManager.getSubmitData(row));
request.then(() => {
this.userDialog = false;
+23 -9
View File
@@ -1500,7 +1500,7 @@ import {
getDetail as getCreditScoreQuantificationDetail,
} from '@/api/vehicle/credit-score-quantification';
import { getDictionary } from '@/api/system/dictbiz';
import { processSubmit } from '@/api/system/business-process';
import { processDelete, processSubmit } from '@/api/system/business-process';
import { getDeptTree } from '@/api/system/dept';
import { getLazyTree } from '@/api/base/region';
import { exportBlob } from '@/api/common';
@@ -4152,7 +4152,11 @@ export default {
archive.fullName ||
this.archiveForm.fullName ||
'';
this.submitCustomerApproval(id, fullName).then(() => {
this.submitCustomerApproval(
id,
fullName,
archive.approvalStatus || this.archiveForm.approvalStatus
).then(() => {
this.closeArchive();
this.onLoad(this.page);
this.$message({ type: 'success', message: '提交成功!' });
@@ -4163,15 +4167,19 @@ export default {
/**
* 列表 / 新增 / 编辑提交共用:提交 MK 审核流并更新客商审批状态
*/
submitCustomerApproval(id, fullName = '') {
return this.submitMkApprovalFlow(id, fullName).then(() => submitApproval(id));
submitCustomerApproval(id, fullName = '', approvalStatus = '') {
return this.submitMkApprovalFlow(id, fullName, approvalStatus).then(() => submitApproval(id));
},
/**
* 提交 MK 审核流:templateCode 取业务字典 mk_template 中「提交审核流」的键值
* 提交 MK 审核流:templateCode 取业务字典 mk_template 中「提交客商审核流」的键值
* 提交人手机号由后端从用户表读取真实值(前端接口会脱敏)
* MK 驳回后再提交时,先删除旧流程再创建新流程
*/
async submitMkApprovalFlow(formInstanceId, subjectName = '') {
const templateCode = await this.resolveMkTemplateCode('提交审核流');
async submitMkApprovalFlow(formInstanceId, subjectName = '', approvalStatus = '') {
if (approvalStatus === 'rejected') {
await processDelete({ formInstanceId: String(formInstanceId) });
}
const templateCode = await this.resolveMkTemplateCode('提交客商审核流');
const subject = subjectName
? `客商准入审批:${subjectName}`
: `客商准入审批:${formInstanceId}`;
@@ -4181,7 +4189,7 @@ export default {
subject,
});
},
async resolveMkTemplateCode(dictName = '提交审核流') {
async resolveMkTemplateCode(dictName = '提交客商审核流') {
const res = await getDictionary({ code: 'mk_template' });
const list = res?.data?.data || [];
const matched = list.find(item => String(item.dictValue || '').trim() === dictName);
@@ -4782,7 +4790,13 @@ export default {
cancelButtonText: '取消',
type: 'warning',
})
.then(() => this.submitCustomerApproval(row.id, archive.fullName || row.fullName))
.then(() =>
this.submitCustomerApproval(
row.id,
archive.fullName || row.fullName,
archive.approvalStatus || row.approvalStatus
)
)
.then(() => {
this.onLoad(this.page);
this.$message({ type: 'success', message: '提交成功!' });