获取相对方
This commit is contained in:
@@ -129,6 +129,21 @@ export function saveContractCollectInfo(id, data) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getCounterpartyConfirm(id) {
|
||||||
|
return request({
|
||||||
|
url: `/contract/launch/${id}/counterparty-confirm`,
|
||||||
|
method: "get",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function confirmCounterparty(id, data) {
|
||||||
|
return request({
|
||||||
|
url: `/contract/launch/${id}/counterparty-confirm`,
|
||||||
|
method: "post",
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function archiveLaunch(id, data = {}) {
|
export function archiveLaunch(id, data = {}) {
|
||||||
return request({
|
return request({
|
||||||
url: `/contract/launch/${id}/archive`,
|
url: `/contract/launch/${id}/archive`,
|
||||||
|
|||||||
@@ -532,6 +532,37 @@
|
|||||||
</div>
|
</div>
|
||||||
</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
|
<div
|
||||||
class="btn btn-success"
|
class="btn btn-success"
|
||||||
:class="{
|
:class="{
|
||||||
@@ -647,6 +678,7 @@ import {
|
|||||||
toRef,
|
toRef,
|
||||||
reactive,
|
reactive,
|
||||||
computed,
|
computed,
|
||||||
|
h,
|
||||||
nextTick,
|
nextTick,
|
||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
@@ -679,6 +711,8 @@ import {
|
|||||||
finishLaunchSeal,
|
finishLaunchSeal,
|
||||||
downloadLaunchFile,
|
downloadLaunchFile,
|
||||||
saveLaunchSealInfo,
|
saveLaunchSealInfo,
|
||||||
|
getCounterpartyConfirm,
|
||||||
|
confirmCounterparty,
|
||||||
} from "@/api/launch.js";
|
} from "@/api/launch.js";
|
||||||
|
|
||||||
const SUCCESS_CODE = "0000";
|
const SUCCESS_CODE = "0000";
|
||||||
@@ -1056,6 +1090,7 @@ async function showModal(contractIdParam, businessRecordParam) {
|
|||||||
await loadContract(contractIdToLoad);
|
await loadContract(contractIdToLoad);
|
||||||
await nextTick();
|
await nextTick();
|
||||||
calcDisplaySize();
|
calcDisplaySize();
|
||||||
|
await loadCounterpartyConfirm();
|
||||||
modalLoading.value = false;
|
modalLoading.value = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1077,6 +1112,7 @@ async function showModal(contractIdParam, businessRecordParam) {
|
|||||||
}
|
}
|
||||||
} catch {}
|
} catch {}
|
||||||
}
|
}
|
||||||
|
await loadCounterpartyConfirm();
|
||||||
modalLoading.value = false;
|
modalLoading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1138,6 +1174,8 @@ const pdfImages = ref([]);
|
|||||||
const imageWidth = ref(793);
|
const imageWidth = ref(793);
|
||||||
const imageHeight = ref(1122);
|
const imageHeight = ref(1122);
|
||||||
const completing = ref(false);
|
const completing = ref(false);
|
||||||
|
const counterpartyConfirmMap = ref({});
|
||||||
|
const counterpartyConfirmLoading = ref(false);
|
||||||
|
|
||||||
async function loadContract(cid) {
|
async function loadContract(cid) {
|
||||||
try {
|
try {
|
||||||
@@ -1264,6 +1302,44 @@ const fetchingSeals = ref(false);
|
|||||||
const sealList = ref([]);
|
const sealList = ref([]);
|
||||||
const sealDefaultScale = ref(1.0);
|
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 = '周小锋';
|
queryName.value = '周小锋';
|
||||||
queryIdOrMobile.value = '17681520782';
|
queryIdOrMobile.value = '17681520782';
|
||||||
@@ -1754,33 +1830,52 @@ async function handleCompleteContract() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Modal.confirm({
|
// 检查相对方签署确认情况
|
||||||
title: "确认结束",
|
await loadCounterpartyConfirm();
|
||||||
content: "确认结束合约?结束后将无法再继续添加签章。",
|
const notConfirmed = unconfirmedPartyNames.value;
|
||||||
okType: "danger",
|
if (notConfirmed.length) {
|
||||||
onOk: async () => {
|
Modal.confirm({
|
||||||
completing.value = true;
|
title: '以下相对方尚未确认签署完成',
|
||||||
try {
|
content: h('div', [
|
||||||
const res = await completeContract(contractId.value);
|
h('p', { style: { color: '#e6a23c', marginBottom: '12px' } }, `共 ${notConfirmed.length} 个相对方未确认:`),
|
||||||
if (!isSuccessResponse(res)) {
|
...notConfirmed.map(n =>
|
||||||
message.error(getResponseMessage(res, "结束合约失败"));
|
h('p', { style: { margin: '4px 0', color: '#f56c6c' } }, '⚠ ' + n)
|
||||||
return;
|
),
|
||||||
}
|
h('p', { style: { color: '#999', fontSize: '12px', marginTop: '12px' } }, '仍可强制结束合约,建议各方确认后再结束。'),
|
||||||
|
]),
|
||||||
|
okText: '强制结束',
|
||||||
|
okType: 'danger',
|
||||||
|
cancelText: '暂不结束',
|
||||||
|
onOk: () => doEndContract(),
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
contractStatus.value = 2000;
|
// 全部已确认,正常结束
|
||||||
updateBusinessStatusByContractStatus(2000);
|
doEndContract();
|
||||||
if (businessRecord.value?.id) {
|
}
|
||||||
await writeBackLaunchSealFinished(2000);
|
|
||||||
}
|
async function doEndContract() {
|
||||||
clearContractState();
|
completing.value = true;
|
||||||
message.success("合约已完成");
|
try {
|
||||||
} catch {
|
const res = await completeContract(contractId.value);
|
||||||
message.error("结束合约失败");
|
if (!isSuccessResponse(res)) {
|
||||||
} finally {
|
message.error(getResponseMessage(res, "结束合约失败"));
|
||||||
completing.value = false;
|
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() {
|
async function handleDownloadContract() {
|
||||||
@@ -2718,4 +2813,57 @@ watch(visible, (value) => {
|
|||||||
width: 320px;
|
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>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user