|
@@ -117,7 +117,7 @@
|
|
|
提交变更
|
|
提交变更
|
|
|
</el-link>
|
|
</el-link>
|
|
|
<el-link type="primary" :underline="false" icon="el-icon-close" @click="openVoidDraft(row, 'CHANGE')">
|
|
<el-link type="primary" :underline="false" icon="el-icon-close" @click="openVoidDraft(row, 'CHANGE')">
|
|
|
- 作废
|
|
|
|
|
|
|
+ 作废变更
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-if="isRenewDraftStatus(row)">
|
|
<template v-if="isRenewDraftStatus(row)">
|
|
@@ -128,7 +128,7 @@
|
|
|
提交
|
|
提交
|
|
|
</el-link>
|
|
</el-link>
|
|
|
<el-link type="primary" :underline="false" icon="el-icon-close" @click="openVoidDraft(row, 'RENEW')">
|
|
<el-link type="primary" :underline="false" icon="el-icon-close" @click="openVoidDraft(row, 'RENEW')">
|
|
|
- 作废
|
|
|
|
|
|
|
+ 作废续签
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-if="isTerminateDraftStatus(row)">
|
|
<template v-if="isTerminateDraftStatus(row)">
|
|
@@ -140,26 +140,26 @@
|
|
|
</el-link>
|
|
</el-link>
|
|
|
<el-link type="primary" :underline="false" icon="el-icon-close"
|
|
<el-link type="primary" :underline="false" icon="el-icon-close"
|
|
|
@click="openVoidDraft(row, 'TERMINATION')">
|
|
@click="openVoidDraft(row, 'TERMINATION')">
|
|
|
- 作废
|
|
|
|
|
|
|
+ 作废解除
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
</template>
|
|
</template>
|
|
|
<!-- 变更审批中:详情统一从「合同编号 / 员工姓名」点开,这里只留变更审批记录 -->
|
|
<!-- 变更审批中:详情统一从「合同编号 / 员工姓名」点开,这里只留变更审批记录 -->
|
|
|
<template v-else-if="isChangeApprovingStatus(row)">
|
|
<template v-else-if="isChangeApprovingStatus(row)">
|
|
|
<el-link type="warning" :underline="false" icon="el-icon-tickets" @click="openChangeApprovalRecord(row)">
|
|
<el-link type="warning" :underline="false" icon="el-icon-tickets" @click="openChangeApprovalRecord(row)">
|
|
|
- 审批记录
|
|
|
|
|
|
|
+ 变更审批
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<!-- 续签审批中 / 签署中:同上,只留续签审批记录 -->
|
|
<!-- 续签审批中 / 签署中:同上,只留续签审批记录 -->
|
|
|
<template v-else-if="isRenewApprovingStatus(row)">
|
|
<template v-else-if="isRenewApprovingStatus(row)">
|
|
|
<el-link type="warning" :underline="false" icon="el-icon-tickets" @click="openRenewApprovalRecord(row)">
|
|
<el-link type="warning" :underline="false" icon="el-icon-tickets" @click="openRenewApprovalRecord(row)">
|
|
|
- 审批记录
|
|
|
|
|
|
|
+ 续签审批
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<!-- 解除审批中:任何变更 / 续签 / 解除操作都不允许,只留解除审批记录 -->
|
|
<!-- 解除审批中:任何变更 / 续签 / 解除操作都不允许,只留解除审批记录 -->
|
|
|
<template v-else-if="isTerminateApprovingStatus(row)">
|
|
<template v-else-if="isTerminateApprovingStatus(row)">
|
|
|
<el-link type="warning" :underline="false" icon="el-icon-tickets" @click="openTerminateApprovalRecord(row)">
|
|
<el-link type="warning" :underline="false" icon="el-icon-tickets" @click="openTerminateApprovalRecord(row)">
|
|
|
- 审批记录
|
|
|
|
|
|
|
+ 解除审批
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-else>
|
|
<template v-else>
|
|
@@ -168,7 +168,7 @@
|
|
|
编辑
|
|
编辑
|
|
|
</el-link>
|
|
</el-link>
|
|
|
<el-link type="primary" :underline="false" icon="el-icon-close" @click="openVoid(row)">
|
|
<el-link type="primary" :underline="false" icon="el-icon-close" @click="openVoid(row)">
|
|
|
- 作废
|
|
|
|
|
|
|
+ 作废合同
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<template v-if="isEffective(row)">
|
|
<template v-if="isEffective(row)">
|
|
@@ -194,12 +194,34 @@
|
|
|
<!-- 续签已签署待生效:审批已走完,操作不锁死,保留刚走完的续签审批记录入口 -->
|
|
<!-- 续签已签署待生效:审批已走完,操作不锁死,保留刚走完的续签审批记录入口 -->
|
|
|
<el-link v-if="isRenewSignedWaitEffective(row)" type="warning" :underline="false"
|
|
<el-link v-if="isRenewSignedWaitEffective(row)" type="warning" :underline="false"
|
|
|
icon="el-icon-tickets" @click="openRenewApprovalRecord(row)">
|
|
icon="el-icon-tickets" @click="openRenewApprovalRecord(row)">
|
|
|
- 审批记录
|
|
|
|
|
|
|
+ 续签审批
|
|
|
|
|
+ </el-link>
|
|
|
|
|
+ <!-- 驳回态:流程已结束,操作不锁死,但要能查看驳回原因(合同自身 / 续签 / 解除) -->
|
|
|
|
|
+ <!-- 合同审批被驳回:可编辑后再次提交审批(与签订/续签同一个 hr_contract_approval,businessId = 合同主键) -->
|
|
|
|
|
+ <el-link v-if="isContractRejected(row)" type="primary" :underline="false" icon="el-icon-edit"
|
|
|
|
|
+ @click="openEdit(row)">
|
|
|
|
|
+ 编辑
|
|
|
|
|
+ </el-link>
|
|
|
|
|
+ <el-link v-if="isContractRejected(row)" type="primary" :underline="false"
|
|
|
|
|
+ icon="el-icon-s-promotion" @click="launchApproval(row)">
|
|
|
|
|
+ 提交
|
|
|
|
|
+ </el-link>
|
|
|
|
|
+ <el-link v-if="isContractRejected(row)" type="warning" :underline="false"
|
|
|
|
|
+ icon="el-icon-tickets" @click="openApprovalRecord(row)">
|
|
|
|
|
+ 合同审批
|
|
|
|
|
+ </el-link>
|
|
|
|
|
+ <el-link v-if="isRenewRejected(row)" type="warning" :underline="false"
|
|
|
|
|
+ icon="el-icon-tickets" @click="openRenewApprovalRecord(row)">
|
|
|
|
|
+ 续签审批
|
|
|
|
|
+ </el-link>
|
|
|
|
|
+ <el-link v-if="isTerminateRejected(row)" type="warning" :underline="false"
|
|
|
|
|
+ icon="el-icon-tickets" @click="openTerminateApprovalRecord(row)">
|
|
|
|
|
+ 解除审批
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<el-link v-if="isApproving(row)" type="warning" :underline="false" icon="el-icon-tickets"
|
|
<el-link v-if="isApproving(row)" type="warning" :underline="false" icon="el-icon-tickets"
|
|
|
@click="openApprovalRecord(row)">
|
|
@click="openApprovalRecord(row)">
|
|
|
- 审批记录
|
|
|
|
|
|
|
+ 合同审批
|
|
|
</el-link>
|
|
</el-link>
|
|
|
</template>
|
|
</template>
|
|
|
<template slot="empty">
|
|
<template slot="empty">
|
|
@@ -793,10 +815,12 @@
|
|
|
<!-- 作废劳动合同 / 草稿弹窗 -->
|
|
<!-- 作废劳动合同 / 草稿弹窗 -->
|
|
|
<ele-modal :visible.sync="voidVisible" width="480px" :title="voidDialogTitle" append-to-body>
|
|
<ele-modal :visible.sync="voidVisible" width="480px" :title="voidDialogTitle" append-to-body>
|
|
|
<el-form ref="voidFormRef" :model="voidForm" :rules="voidRules" label-position="top">
|
|
<el-form ref="voidFormRef" :model="voidForm" :rules="voidRules" label-position="top">
|
|
|
- <el-form-item label="作废原因" prop="reason">
|
|
|
|
|
|
|
+ <!-- 作废原因:仅「合同草稿 / 续签草稿」接口收 reason;变更、解除作废接口无请求体 -->
|
|
|
|
|
+ <el-form-item v-if="voidNeedsReason" label="作废原因" prop="reason" :required="voidNeedsReason">
|
|
|
<el-input v-model="voidForm.reason" type="textarea" :rows="4" maxlength="200" show-word-limit
|
|
<el-input v-model="voidForm.reason" type="textarea" :rows="4" maxlength="200" show-word-limit
|
|
|
:placeholder="voidForm.targetType === 'CONTRACT' ? '已签署且生效的合同不能作废' : '请填写作废原因'" />
|
|
:placeholder="voidForm.targetType === 'CONTRACT' ? '已签署且生效的合同不能作废' : '请填写作废原因'" />
|
|
|
</el-form-item>
|
|
</el-form-item>
|
|
|
|
|
+ <p v-else class="cm-void-tip">作废后该合同可重新发起变更、续签或解除终止,变更历史仍保留该记录。</p>
|
|
|
</el-form>
|
|
</el-form>
|
|
|
<span slot="footer">
|
|
<span slot="footer">
|
|
|
<el-button @click="voidVisible = false">取消</el-button>
|
|
<el-button @click="voidVisible = false">取消</el-button>
|
|
@@ -845,6 +869,9 @@ import {
|
|
|
terminateContract,
|
|
terminateContract,
|
|
|
archiveContractOffline,
|
|
archiveContractOffline,
|
|
|
voidContract,
|
|
voidContract,
|
|
|
|
|
+ voidContractChange,
|
|
|
|
|
+ voidContractRenewal,
|
|
|
|
|
+ voidContractTermination,
|
|
|
getContractTemplatePage,
|
|
getContractTemplatePage,
|
|
|
getContractTemplateVersions,
|
|
getContractTemplateVersions,
|
|
|
exportContractLedger,
|
|
exportContractLedger,
|
|
@@ -1144,8 +1171,9 @@ function blankTerminateForm() {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function blankVoidForm() {
|
|
function blankVoidForm() {
|
|
|
- /* targetType:CONTRACT=作废合同草稿 / CHANGE=作废变更草稿 / RENEW=作废续签草稿 / TERMINATION=作废解除草稿 */
|
|
|
|
|
- return { id: null, reason: '', targetType: 'CONTRACT' };
|
|
|
|
|
|
|
+ /* targetType:CONTRACT=作废合同草稿 / CHANGE=作废变更草稿 / RENEW=作废续签草稿 / TERMINATION=作废解除草稿
|
|
|
|
|
+ contractId = 原合同主键(接口路径的 {id});draftId = 对应草稿单据主键(变更/续签/解除的第二个路径参数) */
|
|
|
|
|
+ return { contractId: null, draftId: null, reason: '', targetType: 'CONTRACT' };
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function blankArchiveForm() {
|
|
function blankArchiveForm() {
|
|
@@ -1259,9 +1287,9 @@ export default {
|
|
|
createVisible: false,
|
|
createVisible: false,
|
|
|
createMode: 'create',
|
|
createMode: 'create',
|
|
|
changeSnapshot: blankChangeSnapshot(),
|
|
changeSnapshot: blankChangeSnapshot(),
|
|
|
- /* 编辑中的变更草稿主键:保存时带上 = 原地修改(2026-10-19 后端支持);空 = 新建 */
|
|
|
|
|
|
|
+ /* 编辑中的变更草稿主键:保存时穿透 changeId = 原地修改(不传 = 新建) */
|
|
|
editingChangeId: '',
|
|
editingChangeId: '',
|
|
|
- /* 编辑中的续签草稿主键(= 续签生成的新合同主键):保存时带上 = 原地修改;空 = 新建 */
|
|
|
|
|
|
|
+ /* 编辑中的续签草稿主键(= 续签生成的新合同主键):保存时穿透 renewalContractId = 原地修改 */
|
|
|
editingRenewContractId: '',
|
|
editingRenewContractId: '',
|
|
|
createForm: blankCreateForm(),
|
|
createForm: blankCreateForm(),
|
|
|
createRules: {
|
|
createRules: {
|
|
@@ -1364,7 +1392,17 @@ export default {
|
|
|
voidSubmitting: false,
|
|
voidSubmitting: false,
|
|
|
voidForm: blankVoidForm(),
|
|
voidForm: blankVoidForm(),
|
|
|
voidRules: {
|
|
voidRules: {
|
|
|
- reason: [{ required: true, message: '请填写作废原因', trigger: 'blur' }],
|
|
|
|
|
|
|
+ reason: [
|
|
|
|
|
+ {
|
|
|
|
|
+ /* 只有收 reason 的接口(合同作废 / 续签草稿作废)才必填 */
|
|
|
|
|
+ validator: (_rule, value, callback) => {
|
|
|
|
|
+ if (!this.voidNeedsReason) return callback();
|
|
|
|
|
+ if (String(value || '').trim()) return callback();
|
|
|
|
|
+ callback(new Error('请填写作废原因'));
|
|
|
|
|
+ },
|
|
|
|
|
+ trigger: 'blur',
|
|
|
|
|
+ },
|
|
|
|
|
+ ],
|
|
|
},
|
|
},
|
|
|
archiveVisible: false,
|
|
archiveVisible: false,
|
|
|
archiveSubmitting: false,
|
|
archiveSubmitting: false,
|
|
@@ -1471,6 +1509,10 @@ export default {
|
|
|
};
|
|
};
|
|
|
return map[this.voidForm.targetType] || '作废劳动合同';
|
|
return map[this.voidForm.targetType] || '作废劳动合同';
|
|
|
},
|
|
},
|
|
|
|
|
+ /** 作废原因只对「合同作废 / 续签草稿作废」可见必填:变更、解除作废接口没有请求体 */
|
|
|
|
|
+ voidNeedsReason() {
|
|
|
|
|
+ return ['CONTRACT', 'RENEW'].includes(this.voidForm.targetType);
|
|
|
|
|
+ },
|
|
|
isCompareMode() {
|
|
isCompareMode() {
|
|
|
return this.isChangeMode || this.isRenewMode;
|
|
return this.isChangeMode || this.isRenewMode;
|
|
|
},
|
|
},
|
|
@@ -1651,6 +1693,8 @@ export default {
|
|
|
EXPIRING: 'expiring',
|
|
EXPIRING: 'expiring',
|
|
|
CHANGED: 'changed',
|
|
CHANGED: 'changed',
|
|
|
RENEWED: 'active',
|
|
RENEWED: 'active',
|
|
|
|
|
+ /* 驳回 = 红色(danger),与列表续签/解除状态的驳回配色一致(2026-10-20 用户要求) */
|
|
|
|
|
+ REJECTED: 'terminated',
|
|
|
TERMINATED: 'terminated',
|
|
TERMINATED: 'terminated',
|
|
|
ENDED: 'terminated',
|
|
ENDED: 'terminated',
|
|
|
CANCELLED: 'expired',
|
|
CANCELLED: 'expired',
|
|
@@ -2983,9 +3027,9 @@ export default {
|
|
|
随后用该主键 + hr_contract_change_approval 发起审批,终态通过后才把字段应用到合同上。
|
|
随后用该主键 + hr_contract_change_approval 发起审批,终态通过后才把字段应用到合同上。
|
|
|
所以这里必须把返回的变更单主键带出去,不能用合同 id 顶替。 */
|
|
所以这里必须把返回的变更单主键带出去,不能用合同 id 顶替。 */
|
|
|
const changeId = await changeContract(form.id, compact({
|
|
const changeId = await changeContract(form.id, compact({
|
|
|
- /* ★ 2026-10-19 后端支持:携带变更草稿主键 = 原地修改该草稿(不传 = 新建);
|
|
|
|
|
|
|
+ /* ★ 2026-10-20 用户确认:原地修改变更草稿的入参字段名是 changeId(不是 id);
|
|
|
编辑已有草稿时必须带上,否则会撞「已有草稿」校验 */
|
|
编辑已有草稿时必须带上,否则会撞「已有草稿」校验 */
|
|
|
- id: this.editingChangeId || undefined,
|
|
|
|
|
|
|
+ changeId: this.editingChangeId || undefined,
|
|
|
/* ★ 变更类型仍是接口枚举必填项,前端目前只有「其他」一种业务口径,固定 OTHER;
|
|
/* ★ 变更类型仍是接口枚举必填项,前端目前只有「其他」一种业务口径,固定 OTHER;
|
|
|
变更原因改为用户在表单里填写(changeReason),不再写死「合同变更」 */
|
|
变更原因改为用户在表单里填写(changeReason),不再写死「合同变更」 */
|
|
|
changeType: 'OTHER',
|
|
changeType: 'OTHER',
|
|
@@ -3030,9 +3074,10 @@ export default {
|
|
|
...payload,
|
|
...payload,
|
|
|
renewal: true,
|
|
renewal: true,
|
|
|
probationMonths: 0,
|
|
probationMonths: 0,
|
|
|
- /* ★ 2026-10-19 后端支持:携带续签草稿(新合同)主键 = 原地修改该草稿 */
|
|
|
|
|
- id: this.editingRenewContractId || undefined,
|
|
|
|
|
}),
|
|
}),
|
|
|
|
|
+ /* ★ 2026-10-20 契约确认:续签草稿主键在 body 顶层(不是 contract 里),字段名 renewalContractId;
|
|
|
|
|
+ 传入同一原合同下尚未发起审批的续签合同主键时原地更新,不传则新建 */
|
|
|
|
|
+ renewalContractId: this.editingRenewContractId || undefined,
|
|
|
});
|
|
});
|
|
|
/* 拿不到新合同主键时**不能**退回原合同 id —— 那会把审批发到旧合同上 */
|
|
/* 拿不到新合同主键时**不能**退回原合同 id —— 那会把审批发到旧合同上 */
|
|
|
return { id: this.pickCreatedId(created), payload };
|
|
return { id: this.pickCreatedId(created), payload };
|
|
@@ -3060,7 +3105,7 @@ export default {
|
|
|
: this.isChangeMode
|
|
: this.isChangeMode
|
|
|
? '合同变更已保存'
|
|
? '合同变更已保存'
|
|
|
: this.isEditMode
|
|
: this.isEditMode
|
|
|
- ? '合同草稿已修改'
|
|
|
|
|
|
|
+ ? '合同已修改'
|
|
|
: '合同已保存',
|
|
: '合同已保存',
|
|
|
);
|
|
);
|
|
|
this.closeCreate();
|
|
this.closeCreate();
|
|
@@ -3267,13 +3312,15 @@ export default {
|
|
|
this.isTerminateDraftStatus(row)
|
|
this.isTerminateDraftStatus(row)
|
|
|
);
|
|
);
|
|
|
},
|
|
},
|
|
|
- /** 变更审批中:变更单已提交、流程未到终态(DRAFT/REJECTED/CANCELLED 之外,且带流程特征) */
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 变更审批中:有变更状态编码、且不是草稿/终态(REJECTED/CANCELLED/EFFECTIVE)即视为审批中。
|
|
|
|
|
+ * ★ 2026-10-20 截图实测:后端会下发枚举注释之外的「审批中」编码(tag 文案「变更审批中」),
|
|
|
|
|
+ * 用 /PENDING|APPROV|SIGN/ 白名单猜会漏 → 改成排除法,未知编码按审批中处理。
|
|
|
|
|
+ */
|
|
|
isChangeApprovingStatus(row = {}) {
|
|
isChangeApprovingStatus(row = {}) {
|
|
|
const code = String(row.changeStatusCode || '').toUpperCase();
|
|
const code = String(row.changeStatusCode || '').toUpperCase();
|
|
|
- if (!code || code === 'DRAFT' || code === 'REJECTED' || code === 'CANCELLED') {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- return /PENDING|APPROV|SIGN/.test(code);
|
|
|
|
|
|
|
+ if (!code) return false;
|
|
|
|
|
+ return !['DRAFT', 'REJECTED', 'CANCELLED', 'EFFECTIVE'].includes(code);
|
|
|
},
|
|
},
|
|
|
/**
|
|
/**
|
|
|
* 续签审批中 / 签署中:PENDING_APPROVAL、PENDING_SIGN、SIGNING。
|
|
* 续签审批中 / 签署中:PENDING_APPROVAL、PENDING_SIGN、SIGNING。
|
|
@@ -3304,13 +3351,23 @@ export default {
|
|
|
isRenewSignedWaitEffective(row = {}) {
|
|
isRenewSignedWaitEffective(row = {}) {
|
|
|
return String(row.renewalStatusCode || '').toUpperCase() === 'SIGNED_WAIT_EFFECTIVE';
|
|
return String(row.renewalStatusCode || '').toUpperCase() === 'SIGNED_WAIT_EFFECTIVE';
|
|
|
},
|
|
},
|
|
|
- /** 解除审批中:解除单已提交、流程未到终态(口径与变更一致) */
|
|
|
|
|
|
|
+ /** 解除审批中:口径与变更一致 —— 排除法,非草稿/终态即审批中 */
|
|
|
isTerminateApprovingStatus(row = {}) {
|
|
isTerminateApprovingStatus(row = {}) {
|
|
|
const code = String(row.terminationStatusCode || '').toUpperCase();
|
|
const code = String(row.terminationStatusCode || '').toUpperCase();
|
|
|
- if (!code || code === 'DRAFT' || code === 'REJECTED' || code === 'CANCELLED') {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- return /PENDING|APPROV|SIGN/.test(code);
|
|
|
|
|
|
|
+ if (!code) return false;
|
|
|
|
|
+ return !['DRAFT', 'REJECTED', 'CANCELLED', 'EFFECTIVE'].includes(code);
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 合同自身审批被驳回(签订 / 续签审批未过):流程已结束,但要能看驳回原因 */
|
|
|
|
|
+ isContractRejected(row = {}) {
|
|
|
|
|
+ return String(row.statusCode || '').toUpperCase() === 'REJECTED';
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 最近一次续签审批被驳回 */
|
|
|
|
|
+ isRenewRejected(row = {}) {
|
|
|
|
|
+ return String(row.renewalStatusCode || '').toUpperCase() === 'REJECTED';
|
|
|
|
|
+ },
|
|
|
|
|
+ /** 最近一次解除审批被驳回 */
|
|
|
|
|
+ isTerminateRejected(row = {}) {
|
|
|
|
|
+ return String(row.terminationStatusCode || '').toUpperCase() === 'REJECTED';
|
|
|
},
|
|
},
|
|
|
/**
|
|
/**
|
|
|
* 解除审批记录:流程实例挂在解除单上(「劳动合同解除终止信息」的 processInstanceId)。
|
|
* 解除审批记录:流程实例挂在解除单上(「劳动合同解除终止信息」的 processInstanceId)。
|
|
@@ -3358,13 +3415,19 @@ export default {
|
|
|
/** 变更审批记录:用变更审批的流程实例(changeProcessInstanceId),不是合同自身的审批 */
|
|
/** 变更审批记录:用变更审批的流程实例(changeProcessInstanceId),不是合同自身的审批 */
|
|
|
async openChangeApprovalRecord(row = {}) {
|
|
async openChangeApprovalRecord(row = {}) {
|
|
|
let pid = row.changeProcessInstanceId;
|
|
let pid = row.changeProcessInstanceId;
|
|
|
- if (!pid && row.changeId && row.id) {
|
|
|
|
|
|
|
+ if (!pid && row.id) {
|
|
|
try {
|
|
try {
|
|
|
- const list = await getContractChanges(row.id);
|
|
|
|
|
- const hit = (Array.isArray(list) ? list : []).find(
|
|
|
|
|
- (item) => String(item.id) === String(row.changeId),
|
|
|
|
|
- );
|
|
|
|
|
- pid = hit?.processInstanceId || hit?.changeProcessInstanceId || '';
|
|
|
|
|
|
|
+ /* 列表行没带 changeProcessInstanceId 时查变更台账:
|
|
|
|
|
+ 优先按 changeId 精确取,行没带 changeId 时按变更状态编码匹配同一状态的那份 */
|
|
|
|
|
+ const list = this.toCascadeList(await getContractChanges(row.id));
|
|
|
|
|
+ const code = String(row.changeStatusCode || '').toUpperCase();
|
|
|
|
|
+ const hit =
|
|
|
|
|
+ (row.changeId
|
|
|
|
|
+ ? list.find((item) => String(item.id) === String(row.changeId))
|
|
|
|
|
+ : null) ||
|
|
|
|
|
+ list.find((item) => String(item.changeStatus || '').toUpperCase() === code) ||
|
|
|
|
|
+ null;
|
|
|
|
|
+ pid = hit?.processInstanceId || '';
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
|
/* 走下方统一提示 */
|
|
/* 走下方统一提示 */
|
|
|
}
|
|
}
|
|
@@ -3614,8 +3677,8 @@ export default {
|
|
|
this.$message.warning('缺少合同主键,无法编辑');
|
|
this.$message.warning('缺少合同主键,无法编辑');
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (!isDraft(row)) {
|
|
|
|
|
- this.$message.warning('仅未提交审批的合同草稿可以修改');
|
|
|
|
|
|
|
+ if (!isDraft(row) && !this.isContractRejected(row)) {
|
|
|
|
|
+ this.$message.warning('仅草稿或被驳回的合同可以修改');
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
this.createMode = 'edit';
|
|
this.createMode = 'edit';
|
|
@@ -3675,7 +3738,7 @@ export default {
|
|
|
this.createMode = 'renew';
|
|
this.createMode = 'renew';
|
|
|
this.createForm = blankCreateForm();
|
|
this.createForm = blankCreateForm();
|
|
|
this.changeSnapshot = blankChangeSnapshot();
|
|
this.changeSnapshot = blankChangeSnapshot();
|
|
|
- /* 续签草稿主键(= 续签生成的新合同主键):保存时带上 = 原地修改该草稿 */
|
|
|
|
|
|
|
+ /* 续签草稿主键(= 续签生成的新合同主键):保存时穿透 renewalContractId 原地修改该草稿 */
|
|
|
this.editingRenewContractId = draftContractId || '';
|
|
this.editingRenewContractId = draftContractId || '';
|
|
|
this.createVisible = true;
|
|
this.createVisible = true;
|
|
|
this.loading = true;
|
|
this.loading = true;
|
|
@@ -3795,8 +3858,9 @@ export default {
|
|
|
this.terminateSubmitting = true;
|
|
this.terminateSubmitting = true;
|
|
|
try {
|
|
try {
|
|
|
const result = await terminateContract(form.id, compact({
|
|
const result = await terminateContract(form.id, compact({
|
|
|
- /* ★ 2026-10-19 后端支持:携带解除草稿主键 = 原地修改该草稿(不传 = 新建) */
|
|
|
|
|
- id: this.terminateDraftId || undefined,
|
|
|
|
|
|
|
+ /* ★ 2026-10-20 契约确认:原地修改解除草稿的入参字段名是 terminationId(不是 id);
|
|
|
|
|
+ 传入同一原合同下未发起审批的草稿主键时原地更新,不传则新建草稿 */
|
|
|
|
|
+ terminationId: this.terminateDraftId || undefined,
|
|
|
terminationType: form.terminationType,
|
|
terminationType: form.terminationType,
|
|
|
reason: form.reason,
|
|
reason: form.reason,
|
|
|
reasonCode: form.reasonCode,
|
|
reasonCode: form.reasonCode,
|
|
@@ -3842,7 +3906,7 @@ export default {
|
|
|
this.$message.warning('仅未提交审批的合同草稿可以作废');
|
|
this.$message.warning('仅未提交审批的合同草稿可以作废');
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- this.voidForm = { id: row.id, reason: '', targetType: 'CONTRACT' };
|
|
|
|
|
|
|
+ this.voidForm = { contractId: row.id, draftId: row.id, reason: '', targetType: 'CONTRACT' };
|
|
|
this.voidVisible = true;
|
|
this.voidVisible = true;
|
|
|
this.$nextTick(() => this.$refs.voidFormRef?.clearValidate());
|
|
this.$nextTick(() => this.$refs.voidFormRef?.clearValidate());
|
|
|
},
|
|
},
|
|
@@ -3871,7 +3935,7 @@ export default {
|
|
|
);
|
|
);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- this.voidForm = { id, reason: '', targetType: flow };
|
|
|
|
|
|
|
+ this.voidForm = { contractId: row.id, draftId: id, reason: '', targetType: flow };
|
|
|
this.voidVisible = true;
|
|
this.voidVisible = true;
|
|
|
this.$nextTick(() => this.$refs.voidFormRef?.clearValidate());
|
|
this.$nextTick(() => this.$refs.voidFormRef?.clearValidate());
|
|
|
},
|
|
},
|
|
@@ -3885,7 +3949,7 @@ export default {
|
|
|
);
|
|
);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- this.voidForm = { id: draft.id, reason: '', targetType: 'TERMINATION' };
|
|
|
|
|
|
|
+ this.voidForm = { contractId: row.id, draftId: draft.id, reason: '', targetType: 'TERMINATION' };
|
|
|
this.voidVisible = true;
|
|
this.voidVisible = true;
|
|
|
this.$nextTick(() => this.$refs.voidFormRef?.clearValidate());
|
|
this.$nextTick(() => this.$refs.voidFormRef?.clearValidate());
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
@@ -3905,8 +3969,37 @@ export default {
|
|
|
RENEW: '续签草稿已作废',
|
|
RENEW: '续签草稿已作废',
|
|
|
TERMINATION: '解除草稿已作废',
|
|
TERMINATION: '解除草稿已作废',
|
|
|
};
|
|
};
|
|
|
- await voidContract(this.voidForm.id, { reason: this.voidForm.reason });
|
|
|
|
|
- this.$message.success(msgMap[this.voidForm.targetType] || '作废成功');
|
|
|
|
|
|
|
+ const { contractId, draftId, targetType } = this.voidForm;
|
|
|
|
|
+ const body = { reason: this.voidForm.reason };
|
|
|
|
|
+ if (!contractId) {
|
|
|
|
|
+ this.$message.warning('缺少原合同主键,无法作废');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (targetType === 'CONTRACT') {
|
|
|
|
|
+ await voidContract(contractId, body);
|
|
|
|
|
+ } else if (targetType === 'RENEW') {
|
|
|
|
|
+ /* 续签草稿作废:唯一收「作废参数」的草稿接口 */
|
|
|
|
|
+ if (!draftId) {
|
|
|
|
|
+ this.$message.warning('缺少续签草稿主键,无法作废');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ await voidContractRenewal(contractId, draftId, body);
|
|
|
|
|
+ } else if (targetType === 'CHANGE' || targetType === 'TERMINATION') {
|
|
|
|
|
+ /* 变更 / 解除作废接口只有路径参数,无请求体 */
|
|
|
|
|
+ if (!draftId) {
|
|
|
|
|
+ this.$message.warning('缺少草稿主键,无法作废');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (targetType === 'CHANGE') {
|
|
|
|
|
+ await voidContractChange(contractId, draftId);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ await voidContractTermination(contractId, draftId);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$message.warning('未知的作废对象类型,无法作废');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ this.$message.success(msgMap[targetType] || '作废成功');
|
|
|
this.voidVisible = false;
|
|
this.voidVisible = false;
|
|
|
this.applyFilters();
|
|
this.applyFilters();
|
|
|
} catch (e) {
|
|
} catch (e) {
|
|
@@ -3968,4 +4061,12 @@ export default {
|
|
|
.cm-change-none {
|
|
.cm-change-none {
|
|
|
color: #c0c4cc;
|
|
color: #c0c4cc;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+/* 作废弹框:变更/解除草稿作废无需填原因时的说明文案 */
|
|
|
|
|
+.cm-void-tip {
|
|
|
|
|
+ margin: 0;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ line-height: 1.7;
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+}
|
|
|
</style>
|
|
</style>
|