Merge pull request '项目+合同对接合同系统' (#8) from feature/hcs-api-p0-web into master

Reviewed-on: #8
This commit was merged in pull request #8.
This commit is contained in:
2026-10-27 14:47:14 +08:00
26 changed files with 1304 additions and 55 deletions
+23 -8
View File
@@ -270,6 +270,7 @@ export default {
rows: [],
selection: [],
loading: false,
approveLoading: false,
batchSyncing: false,
page: { current: 1, size: 10, total: 0 },
mkEnabled: false,
@@ -408,15 +409,29 @@ export default {
});
},
async handleApprove(row) {
await this.$confirm('确认审批通过该开票申请?', '提示', { type: 'warning' });
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
if (res.data.data === false) {
this.$message.warning(res.data.msg);
} else {
this.$message.success(res.data.msg || '审批通过');
// 防止重复点击:请求进行中忽略后续点击,避免重复审批和重复提示
if (this.approveLoading) return;
this.approveLoading = true;
let loading = null;
try {
await this.$confirm('确认审批通过该开票申请?', '提示', { type: 'warning' });
loading = this.$loading({
lock: true,
text: '审批处理中,请稍候…',
background: 'rgba(255, 255, 255, 0.6)',
});
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
if (res.data.data === false) {
this.$message.warning(res.data.msg);
} else {
this.$message.success(res.data.msg || '审批通过');
}
this.loadTable();
} finally {
loading?.close();
this.approveLoading = false;
}
this.loadTable();
},
async handleReturn(row) {
const { value } = await this.$prompt('请输入驳回原因', '审批驳回');
+23 -8
View File
@@ -255,6 +255,7 @@ export default {
rows: [],
selection: [],
loading: false,
approveLoading: false,
pushLoading: false,
page: { current: 1, size: 10, total: 0 },
mkEnabled: false,
@@ -365,15 +366,29 @@ export default {
});
},
async handleApprove(row) {
await this.$confirm('确认审批通过该收票登记?', '提示', { type: 'warning' });
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
if (res.data.data === false) {
this.$message.warning(res.data.msg);
} else {
this.$message.success(res.data.msg || '审批通过');
// 防止重复点击:请求进行中忽略后续点击,避免重复审批和重复提示
if (this.approveLoading) return;
this.approveLoading = true;
let loading = null;
try {
await this.$confirm('确认审批通过该收票登记?', '提示', { type: 'warning' });
loading = this.$loading({
lock: true,
text: '审批处理中,请稍候…',
background: 'rgba(255, 255, 255, 0.6)',
});
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
if (res.data.data === false) {
this.$message.warning(res.data.msg);
} else {
this.$message.success(res.data.msg || '审批通过');
}
this.loadTable();
} finally {
loading?.close();
this.approveLoading = false;
}
this.loadTable();
},
async handleReturn(row) {
const { value } = await this.$prompt('请输入驳回原因', '审批驳回');
@@ -219,6 +219,11 @@
show-word-limit /></el-form-item
></el-col>
</el-row>
<!-- 风险客商提示(基本信息备注后,同合同新增页):收款方外部客商高风险/黑名单时展示,文案由后端 riskTip 拼装 -->
<div v-if="payeeRiskText" class="payment-form-page__risk-tip">
<div class="payment-form-page__risk-tip-title">风险客商提示:</div>
<div class="payment-form-page__risk-tip-content">{{ payeeRiskText }}</div>
</div>
</section-card>
<section-card v-if="isSettlementRelatedType" title="结算信息">
<el-table :data="settlementRows" border
@@ -719,6 +724,7 @@ import * as billLedgerApi from '@/api/payment/billLedger';
import { getDictionary } from '@/api/system/dictbiz';
import { getList as getProjectList } from '@/api/business/project-apply';
import { getDetail as getContractDetail } from '@/api/business/contract-manage';
import { getRisk as getCustomerRisk } from '@/api/business/hcs';
import * as formalApi from '@/api/settlement/formalSettlement';
import * as preApi from '@/api/settlement/preSettlement';
import {
@@ -874,6 +880,11 @@ export default {
/** 合同付款比例设置(按第1笔、第2笔…顺序) */
contractPaymentRatioRows: [],
payeeCustomerLevel: '',
// 收款方 C101-1 风险查询留档:risky=高风险/黑名单,tip=后端拼装提示文案
payeeRisky: false,
payeeRiskTip: '',
payeeRiskLevel: '',
payeeBlackStatus: '',
attachmentRuleLoading: false,
// 最近一次从结算单同步过来的附件 URL,切换结算单时用于整批替换
linkedSettlementAttachmentUrls: [],
@@ -1047,11 +1058,22 @@ export default {
});
},
highRiskPayee() {
// 收款方 C101-1 高风险/黑名单,或客商等级 D/E/F(本地评级口径),命中须上传特批附件
if (this.payeeRisky) return true;
const level = String(this.payeeCustomerLevel || '')
.trim()
.toUpperCase();
return ['D', 'D级', 'E', 'E级', 'F', 'F级'].includes(level) || level.includes('高风险');
},
// 高风险/黑名单收款方提示(C101-1,同合同新增页风险客商提示口径;强制拦截在后端提交校验与金蝶推送门禁)
payeeRiskText() {
if (!this.payeeRisky) return '';
const levelMap = { 0: '低风险', 1: '中风险', 2: '高风险' };
const level = levelMap[this.payeeRiskLevel] || '未知';
const blacklist = String(this.payeeBlackStatus || '').trim().toLowerCase() === 'yes' ? '是' : '否';
const tip = this.payeeRiskTip || `收款方[${this.form.payeeName || ''}]为高风险/黑名单客商`;
return `风险等级:${level}|黑名单:${blacklist}。${tip},按集团规定不可直接付款,提交前须上传「特批附件」类型附件,审批通过后将自动发起付款特批`;
},
requiredAttachmentMaterials() {
if (this.form.paymentType === 'project_advance') {
return [ATTACHMENT_MATERIALS.contract];
@@ -2317,6 +2339,10 @@ export default {
const preserveCurrentValue = autoSelectDefault === false;
this.receiptAccountOptions = [];
this.payeeCustomerLevel = '';
this.payeeRisky = false;
this.payeeRiskTip = '';
this.payeeRiskLevel = '';
this.payeeBlackStatus = '';
if (!partyBName) {
if (!preserveCurrentValue) this.clearReceiptAccount();
return;
@@ -2348,6 +2374,19 @@ export default {
}
const detail = this.unwrapData(await getCustomerArchiveDetail(customer.id));
this.payeeCustomerLevel = detail.customerLevel || '';
// 收款方实时查 C101-1 客商风险(后端对内部组织客商默认返回无风险):高风险/黑名单在
// 基本信息"风险客商提示"条常驻展示并要求特批附件;查询失败不阻断填写,提交时后端强校验兜底
if (detail.customerCode) {
try {
const risk = this.unwrapData(await getCustomerRisk(detail.customerCode)) || {};
this.payeeRisky = Boolean(risk.risky);
this.payeeRiskTip = risk.riskTip || '';
this.payeeRiskLevel = risk.fdRiskLevel || '';
this.payeeBlackStatus = risk.fdBlackStatus || '';
} catch (error) {
// 忽略风险查询异常,提交时后端 C101-1 强校验兜底
}
}
this.receiptAccountOptions = (detail.receiptAccounts || [])
.filter(item => item.accountName || item.accountHolderName || item.bankAccount)
.map(item => ({
@@ -3312,6 +3351,15 @@ export default {
this.clearMessages();
const saved = await this.saveDraft({ showSuccess: false, closePage: false });
if (!saved) return;
// 高风险/黑名单收款方必须上传特批附件(与后端提交强校验同口径)
if (
this.missingAttachmentMaterials.some(
item => item.key === ATTACHMENT_MATERIALS.specialApproval.key
)
) {
this.$message.warning('收款方为高风险/黑名单客商,必须上传「特批附件」类型附件后再提交审批');
return;
}
const previousApprovalStatus = this.form.approvalStatus || '';
await api.submit({ id: this.form.id });
await submitMkApprovalFlow({
@@ -3344,6 +3392,26 @@ export default {
.payment-form-page__form {
padding-bottom: 72px;
}
// 风险客商提示条(基本信息备注后,同合同新增页):橙黄背景 + 红色文字
.payment-form-page__risk-tip {
margin: 0 0 18px;
padding: 10px 16px;
background: #faecd8;
border-radius: 4px;
.payment-form-page__risk-tip-title {
color: #f56c6c;
font-weight: 600;
line-height: 22px;
}
.payment-form-page__risk-tip-content {
color: #f56c6c;
line-height: 22px;
}
}
.payment-form-page__settlement-nos {
display: flex;
align-items: center;
@@ -331,6 +331,11 @@ export default {
// 防止重复点击:请求进行中忽略后续点击
if (this.approveLoading) return;
this.approveLoading = true;
const loading = this.$loading({
lock: true,
text: '审批处理中,请稍候…',
background: 'rgba(255, 255, 255, 0.6)',
});
try {
const res = await api.approve({ id: row.id });
// data=false 表示审批已通过但自动同步金蝶失败,msg 带具体原因
@@ -341,6 +346,7 @@ export default {
}
this.refreshChange();
} finally {
loading.close();
this.approveLoading = false;
}
},