This commit is contained in:
fuenmao
2026-08-26 19:21:35 +08:00
parent ec7e889edc
commit c091fc92b6
+39 -6
View File
@@ -628,11 +628,18 @@
v-if="canEdit" v-if="canEdit"
v-model="c.isAgreed" v-model="c.isAgreed"
class="agree-checkbox" class="agree-checkbox"
:disabled="!isContractPrepared(c.id)" :disabled="!isContractPrepared(c.id) || !c.hasViewed"
:label="`我已完整阅读并同意《${c.contractName}》全部条款`" :label="`我已完整阅读并同意《${c.contractName}》全部条款`"
/> />
<span v-else class="confirmed-text">✓ 候选人已确认同意</span> <span v-else class="confirmed-text">✓ 候选人已确认同意</span>
</div> </div>
<div
v-if="canEdit && isContractPrepared(c.id) && !c.hasViewed"
class="contract-view-hint"
>
请先点击“下载并查看合同”,查看后才能勾选确认。
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -897,6 +904,7 @@ async function load(silent = false) {
task.value = data.task; task.value = data.task;
contracts.value = (data.contracts || []).map((c: any) => ({ contracts.value = (data.contracts || []).map((c: any) => ({
...c, ...c,
hasViewed: Boolean(c.readAt),
isAgreed: c.contractStatus === "confirmed" isAgreed: c.contractStatus === "confirmed"
})); }));
contracts.value.forEach((contract: any) => { contracts.value.forEach((contract: any) => {
@@ -1103,6 +1111,7 @@ async function prepareContract(contract: any) {
contractPrepareErrors[key] = ""; contractPrepareErrors[key] = "";
try { try {
const previousFileId = contract.generatedDocxFileId;
const response = await onboardingPublicApi.prepareContract({ const response = await onboardingPublicApi.prepareContract({
token: token.value, token: token.value,
taskContractId: contract.id taskContractId: contract.id
@@ -1110,13 +1119,20 @@ async function prepareContract(contract: any) {
// 使用后端返回的新文件 Id 作为下载版本,避免手机浏览器复用旧合同缓存。 // 使用后端返回的新文件 Id 作为下载版本,避免手机浏览器复用旧合同缓存。
contract.generatedDocxFileId = response.data.fileId; contract.generatedDocxFileId = response.data.fileId;
contract.generatedAt = response.data.generatedAt; contract.generatedAt = response.data.generatedAt;
if (previousFileId && previousFileId !== response.data.fileId) {
contract.hasViewed = false;
contract.isAgreed = false;
}
contractPrepareStatus[key] = "ready"; contractPrepareStatus[key] = "ready";
return true; return true;
} catch (err: any) { } catch (err: any) {
const message = err?.message || "合同准备失败,请稍后重试"; const message = err?.msg || err?.message || "合同准备失败,请稍后重试";
contractPrepareStatus[key] = "error"; contractPrepareStatus[key] = "error";
contractPrepareErrors[key] = message; contractPrepareErrors[key] = message;
ElMessage.error(`${contract.contractName}:${message}`); // 业务异常已由统一请求拦截器提示;仅为网络等非标准异常补充提示,避免重复弹窗。
if (!err?.msg) {
ElMessage.error(`${contract.contractName}:${message}`);
}
return false; return false;
} }
} }
@@ -1132,7 +1148,10 @@ async function prepareContracts() {
async function handleContractAction(contract: any) { async function handleContractAction(contract: any) {
if (isContractPrepareFailed(contract.id)) { if (isContractPrepareFailed(contract.id)) {
await prepareContract(contract); const prepared = await prepareContract(contract);
if (prepared) {
ElMessage.success("合同已重新准备完成,请再次点击下载查看");
}
return; return;
} }
@@ -1148,7 +1167,9 @@ function previewAndDownloadContract(c: any) {
fileVersion: c.generatedDocxFileId fileVersion: c.generatedDocxFileId
}); });
// 下载必须直接发生在用户点击事件中,避免手机浏览器拦截异步打开或二次跳转。 c.hasViewed = true;
c.isAgreed = false;
// 下载地址必须在用户点击事件中直接打开,微信及部分手机浏览器会拦截异步跳转空白页。
const downloadWindow = window.open(url, "_blank"); const downloadWindow = window.open(url, "_blank");
if (!downloadWindow) { if (!downloadWindow) {
window.location.assign(url); window.location.assign(url);
@@ -1161,6 +1182,11 @@ async function submitAll() {
return ElMessage.warning(`请先等待合同准备完成:${unprepared.map(c => c.contractName).join("、")}`); return ElMessage.warning(`请先等待合同准备完成:${unprepared.map(c => c.contractName).join("、")}`);
} }
const unviewed = contracts.value.filter(c => !c.hasViewed);
if (unviewed.length) {
return ElMessage.warning(`请先下载并查看合同:${unviewed.map(c => c.contractName).join("、")}`);
}
const unconfirmed = contracts.value.filter(c => !c.isAgreed); const unconfirmed = contracts.value.filter(c => !c.isAgreed);
if (unconfirmed.length) { if (unconfirmed.length) {
return ElMessage.warning(`请先勾选同意全部合同(未勾选:${unconfirmed.map(c => c.contractName).join("、")})`); return ElMessage.warning(`请先勾选同意全部合同(未勾选:${unconfirmed.map(c => c.contractName).join("、")})`);
@@ -1179,7 +1205,7 @@ async function submitAll() {
submitting.value = true; submitting.value = true;
try { try {
await saveCurrentEmployeeInfo(); // 员工资料在进入材料步骤前已经保存;此处重复保存会使刚生成的合同失效。
for (const c of contracts.value) { for (const c of contracts.value) {
await onboardingPublicApi.confirmContract({ token: token.value, taskContractId: c.id }); await onboardingPublicApi.confirmContract({ token: token.value, taskContractId: c.id });
} }
@@ -1571,6 +1597,13 @@ onBeforeUnmount(() => {
font-weight: 600; font-weight: 600;
} }
.contract-view-hint {
margin-top: 10px;
color: #d97706;
font-size: 13px;
line-height: 1.5;
}
.confirmed-text { .confirmed-text {
color: #16a34a; color: #16a34a;
font-weight: 600; font-weight: 600;