获取相对方

This commit is contained in:
2026-06-30 16:36:26 +08:00
parent fe019228b7
commit 83f5b5fcce
2 changed files with 189 additions and 26 deletions
@@ -532,6 +532,37 @@
</div>
</div>
<div v-if="counterpartyPartyNames.length" class="counterparty-confirm-section">
<div class="counterparty-confirm-title">相对方签署确认</div>
<div
v-for="name in counterpartyPartyNames"
:key="name"
class="counterparty-confirm-row"
>
<span
v-if="counterpartyConfirmMap[name]?.confirmed"
class="confirm-status status-done"
></span>
<span v-else class="confirm-status status-pending"></span>
<span class="confirm-name">{{ name }}</span>
<span
v-if="counterpartyConfirmMap[name]?.confirmed"
class="confirm-method"
>{{ counterpartyConfirmMap[name]?.method === 'manual' ? '(代确认)' : '(已确认)' }}</span>
<a-button
v-else
size="small"
type="primary"
ghost
:loading="counterpartyConfirmLoading"
@click="handleConfirmCounterparty(name)"
>我已签署完成</a-button>
</div>
<div v-if="unconfirmedPartyNames.length" class="counterparty-confirm-note">
所有相对方确认后方可正常结束未确认仍可强制结束
</div>
</div>
<div
class="btn btn-success"
:class="{
@@ -647,6 +678,7 @@ import {
toRef,
reactive,
computed,
h,
nextTick,
onMounted,
onUnmounted,
@@ -679,6 +711,8 @@ import {
finishLaunchSeal,
downloadLaunchFile,
saveLaunchSealInfo,
getCounterpartyConfirm,
confirmCounterparty,
} from "@/api/launch.js";
const SUCCESS_CODE = "0000";
@@ -1056,6 +1090,7 @@ async function showModal(contractIdParam, businessRecordParam) {
await loadContract(contractIdToLoad);
await nextTick();
calcDisplaySize();
await loadCounterpartyConfirm();
modalLoading.value = false;
return;
}
@@ -1077,6 +1112,7 @@ async function showModal(contractIdParam, businessRecordParam) {
}
} catch {}
}
await loadCounterpartyConfirm();
modalLoading.value = false;
}
@@ -1138,6 +1174,8 @@ const pdfImages = ref([]);
const imageWidth = ref(793);
const imageHeight = ref(1122);
const completing = ref(false);
const counterpartyConfirmMap = ref({});
const counterpartyConfirmLoading = ref(false);
async function loadContract(cid) {
try {
@@ -1264,6 +1302,44 @@ const fetchingSeals = ref(false);
const sealList = ref([]);
const sealDefaultScale = ref(1.0);
/** 解析相对方名单(分号分隔) */
const counterpartyPartyNames = computed(() => {
const text = businessRecord.value?.counterpartySummary || '';
return text.split(/[;]/).map(s => s.trim()).filter(Boolean);
});
/** 未确认的相对方名单 */
const unconfirmedPartyNames = computed(() => {
return counterpartyPartyNames.value.filter(name => !counterpartyConfirmMap.value[name]?.confirmed);
});
async function loadCounterpartyConfirm() {
if (!businessRecord.value?.id) return;
counterpartyConfirmLoading.value = true;
try {
const res = await getCounterpartyConfirm(businessRecord.value.id);
if (isSuccessResponse(res) && res.result) {
counterpartyConfirmMap.value = res.result || {};
}
} catch { /* ignore */ }
counterpartyConfirmLoading.value = false;
}
async function handleConfirmCounterparty(companyName) {
if (!businessRecord.value?.id) return;
try {
const res = await confirmCounterparty(businessRecord.value.id, { companyName });
if (isSuccessResponse(res) && res.result) {
counterpartyConfirmMap.value = res.result || {};
message.success(`已确认:${companyName}`);
} else {
message.error(getResponseMessage(res, '确认失败'));
}
} catch {
message.error('确认失败');
}
}
queryName.value = '周小锋';
queryIdOrMobile.value = '17681520782';
@@ -1754,33 +1830,52 @@ async function handleCompleteContract() {
return;
}
Modal.confirm({
title: "确认结束",
content: "确认结束合约?结束后将无法再继续添加签章。",
okType: "danger",
onOk: async () => {
completing.value = true;
try {
const res = await completeContract(contractId.value);
if (!isSuccessResponse(res)) {
message.error(getResponseMessage(res, "结束合约失败"));
return;
}
// 检查相对方签署确认情况
await loadCounterpartyConfirm();
const notConfirmed = unconfirmedPartyNames.value;
if (notConfirmed.length) {
Modal.confirm({
title: '以下相对方尚未确认签署完成',
content: h('div', [
h('p', { style: { color: '#e6a23c', marginBottom: '12px' } }, `${notConfirmed.length} 个相对方未确认:`),
...notConfirmed.map(n =>
h('p', { style: { margin: '4px 0', color: '#f56c6c' } }, '⚠ ' + n)
),
h('p', { style: { color: '#999', fontSize: '12px', marginTop: '12px' } }, '仍可强制结束合约,建议各方确认后再结束。'),
]),
okText: '强制结束',
okType: 'danger',
cancelText: '暂不结束',
onOk: () => doEndContract(),
});
return;
}
contractStatus.value = 2000;
updateBusinessStatusByContractStatus(2000);
if (businessRecord.value?.id) {
await writeBackLaunchSealFinished(2000);
}
clearContractState();
message.success("合约已完成");
} catch {
message.error("结束合约失败");
} finally {
completing.value = false;
}
},
});
// 全部已确认,正常结束
doEndContract();
}
async function doEndContract() {
completing.value = true;
try {
const res = await completeContract(contractId.value);
if (!isSuccessResponse(res)) {
message.error(getResponseMessage(res, "结束合约失败"));
return;
}
contractStatus.value = 2000;
updateBusinessStatusByContractStatus(2000);
if (businessRecord.value?.id) {
await writeBackLaunchSealFinished(2000);
}
clearContractState();
message.success("合约已完成");
} catch {
message.error("结束合约失败");
} finally {
completing.value = false;
}
}
async function handleDownloadContract() {
@@ -2718,4 +2813,57 @@ watch(visible, (value) => {
width: 320px;
}
}
/* 相对方签署确认 */
.counterparty-confirm-section {
margin: 14px 0;
padding: 10px 12px;
background: #f8fafc;
border-radius: 10px;
border: 1px solid #eef2f6;
}
.counterparty-confirm-title {
font-size: 13px;
font-weight: 600;
color: #2c3e50;
margin-bottom: 8px;
}
.counterparty-confirm-row {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 0;
font-size: 12px;
border-bottom: 1px dashed #eef2f6;
}
.counterparty-confirm-row:last-child {
border-bottom: none;
}
.confirm-status {
font-size: 14px;
flex-shrink: 0;
}
.confirm-status.status-done {
color: #67c23a;
}
.confirm-status.status-pending {
color: #c0c4cc;
}
.confirm-name {
flex: 1;
color: #2c3e50;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.confirm-method {
font-size: 11px;
color: #909399;
flex-shrink: 0;
}
.counterparty-confirm-note {
margin-top: 6px;
font-size: 11px;
color: #909399;
}
</style>