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