|
|
@@ -10,12 +10,9 @@
|
|
|
<el-switch v-model="form.leaveNeedPunch" active-text="开启" inactive-text="关闭" :disabled="readonly" />
|
|
|
</el-form-item>
|
|
|
<el-form-item label="打卡时间">
|
|
|
+ <!-- value 是后端 leavePunch.punchTimeLimitType 枚举,别再写中文字符串 -->
|
|
|
<el-select v-model="form.leavePunchWindow" placeholder="选择打卡时间" style="width:240px" :disabled="readonly">
|
|
|
- <el-option label="不限制" value="不限制" />
|
|
|
- <el-option label="上下班前后 30 分钟" value="上下班前后 30 分钟" />
|
|
|
- <el-option label="上下班前后 1 小时" value="上下班前后 1 小时" />
|
|
|
- <el-option label="仅请假开始时间" value="仅请假开始时间" />
|
|
|
- <el-option label="仅请假结束时间" value="仅请假结束时间" />
|
|
|
+ <el-option v-for="item in leavePunchTimeOptions" :key="item.value" :label="item.label" :value="item.value" />
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
</section>
|
|
|
@@ -30,6 +27,13 @@
|
|
|
</div>
|
|
|
<el-table :data="form.leaveRules" class="leave-rule-table" size="small" border stripe>
|
|
|
<el-table-column type="index" label="序号" width="60" align="center" header-align="center" />
|
|
|
+ <!-- 关联:勾选后随规则一起提交(leavePolicyIds);同一规则内请假类型不能重复 -->
|
|
|
+ <el-table-column label="关联" width="60" align="center" header-align="center">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-checkbox :value="isLeavePolicyLinked(row)" :disabled="readonly"
|
|
|
+ @change="(checked) => toggleLeavePolicyLink(row, checked)" />
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
<el-table-column prop="category" label="假期分类" width="90" align="center" />
|
|
|
<el-table-column prop="name" label="假期名称" width="100" align="center" />
|
|
|
<el-table-column prop="type" label="假期类型" width="110" align="center" />
|
|
|
@@ -37,13 +41,6 @@
|
|
|
<el-table-column prop="condition" label="满足条件" width="140" />
|
|
|
<el-table-column prop="quota" label="年度额度" width="90" align="center" />
|
|
|
<el-table-column prop="salary" label="薪资规则" width="130" />
|
|
|
- <el-table-column prop="approval" label="审批流程" width="80" align="center">
|
|
|
- <template slot-scope="{ row }">
|
|
|
- <span class="status-pill" :class="row.approval === '已审核' ? 'success' : 'muted'">
|
|
|
- <i></i>{{ row.approval }}
|
|
|
- </span>
|
|
|
- </template>
|
|
|
- </el-table-column>
|
|
|
<el-table-column prop="status" label="状态" width="80" align="center">
|
|
|
<template slot-scope="{ row }">
|
|
|
<span class="status-pill" :class="row.status === '已生效' ? 'success' : (row.status === '已归档' ? 'muted' : 'pending')">
|
|
|
@@ -53,7 +50,8 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column v-if="!readonly" label="操作" width="90" align="left" fixed="right">
|
|
|
<template slot-scope="{ row, $index }">
|
|
|
- <el-button type="text" size="mini" :class="row.action === '已归档' ? 'is-archived' : ''" @click="onLeaveRuleAction(row, $index)">{{ row.action }}</el-button>
|
|
|
+ <el-button type="text" size="mini" :class="row.status === '已归档' ? 'is-archived' : ''"
|
|
|
+ :disabled="leaveSaving" @click="onLeaveRuleAction(row, $index)">{{ row.action }}</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
@@ -106,7 +104,7 @@
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import { saveLeavePolicy, serializeLeavePolicy, adaptLeavePolicy } from '@/api/hr/attendance';
|
|
|
+import { saveLeavePolicy, serializeLeavePolicy, adaptLeavePolicy, LEAVE_PUNCH_TIME_OPTIONS } from '@/api/hr/attendance';
|
|
|
|
|
|
const leaveTypeOptions = [
|
|
|
{ label: '年假', value: 'ANNUAL' },
|
|
|
@@ -146,6 +144,8 @@ export default {
|
|
|
data() {
|
|
|
return {
|
|
|
leaveTypeOptions,
|
|
|
+ /* 打卡时间下拉:value 即后端枚举(来自 api 层,别再本地写中文 value) */
|
|
|
+ leavePunchTimeOptions: LEAVE_PUNCH_TIME_OPTIONS,
|
|
|
leaveDialogVisible: false,
|
|
|
leaveDialogTitle: '新增假期制度',
|
|
|
leaveSaving: false,
|
|
|
@@ -174,6 +174,7 @@ export default {
|
|
|
this.$nextTick(() => this.$refs.leaveFormRef?.clearValidate?.());
|
|
|
},
|
|
|
async confirmLeaveDialog() {
|
|
|
+ if (this.leaveSaving) return;
|
|
|
const valid = await new Promise((resolve) => {
|
|
|
this.$refs.leaveFormRef?.validate((ok) => resolve(ok));
|
|
|
});
|
|
|
@@ -216,19 +217,74 @@ export default {
|
|
|
this.leaveSaving = false;
|
|
|
}
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 该行是否已被本规则关联(form.leavePolicyIds 里是否有它的主键)。
|
|
|
+ * 勾选结果随规则一起提交(POST/PUT rules 的 leavePolicyIds)。
|
|
|
+ */
|
|
|
+ isLeavePolicyLinked(row) {
|
|
|
+ return (this.form.leavePolicyIds || []).some((id) => String(id) === String(row.id));
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 勾选/取消关联。后端约定:同一规则内请假类型不能重复 → 勾选时前端先拦一次。
|
|
|
+ */
|
|
|
+ toggleLeavePolicyLink(row, checked) {
|
|
|
+ const ids = (this.form.leavePolicyIds || []).map(String);
|
|
|
+ if (!checked) {
|
|
|
+ this.$set(this.form, 'leavePolicyIds', ids.filter((id) => id !== String(row.id)));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const duplicated = (this.form.leaveRules || []).find(
|
|
|
+ (item) => String(item.id) !== String(row.id)
|
|
|
+ && String(item.leaveType) === String(row.leaveType)
|
|
|
+ && ids.includes(String(item.id)),
|
|
|
+ );
|
|
|
+ if (duplicated) {
|
|
|
+ this.$message.warning(`同一规则内请假类型不能重复:「${row.type || row.leaveType}」已关联「${duplicated.name}」`);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!ids.includes(String(row.id))) ids.push(String(row.id));
|
|
|
+ this.$set(this.form, 'leavePolicyIds', ids);
|
|
|
+ },
|
|
|
onLeaveRuleAction(row, index) {
|
|
|
- if (row.action === '已归档') {
|
|
|
- this.$confirm('确定恢复该假期制度为可编辑?', '提示', { type: 'warning' })
|
|
|
- .then(() => {
|
|
|
- this.$set(this.form.leaveRules[index], 'action', '修改');
|
|
|
- this.$set(this.form.leaveRules[index], 'approval', '待审核');
|
|
|
- this.$set(this.form.leaveRules[index], 'status', '未生效');
|
|
|
- this.$message.success('已恢复为可编辑');
|
|
|
- })
|
|
|
- .catch(() => {});
|
|
|
+ // 未生效 → 打开编辑弹窗;已生效 → 停用;已归档 → 恢复(后两者都要落库,见下)
|
|
|
+ if (row.action === '修改') {
|
|
|
+ this.openLeaveDialog(row);
|
|
|
return;
|
|
|
}
|
|
|
- this.openLeaveDialog(row);
|
|
|
+ this.changeLeavePolicyStatus(row, index, row.action === '停用' ? '已归档' : '未生效');
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 停用 / 恢复假期制度。
|
|
|
+ * ★ 原来只改本地内存(不发请求),刷新即还原 —— 现在走真实 upsert:
|
|
|
+ * 停用 → saveLeavePolicy(status=DISABLED);恢复 → saveLeavePolicy(status=DRAFT 即「未生效、可编辑」)。
|
|
|
+ * 确认框放在锁内(leaveSaving 先行置位),避免连点弹出两个确认框。
|
|
|
+ */
|
|
|
+ async changeLeavePolicyStatus(row, index, nextStatusText) {
|
|
|
+ if (this.leaveSaving) return;
|
|
|
+ const toDisabled = nextStatusText === '已归档';
|
|
|
+ this.leaveSaving = true;
|
|
|
+ let cancelled = false;
|
|
|
+ try {
|
|
|
+ await this.$confirm(
|
|
|
+ toDisabled ? '停用后该假期制度不能再被考勤规则关联,确定停用?' : '确定恢复该假期制度为可编辑(未生效)?',
|
|
|
+ '提示',
|
|
|
+ { type: 'warning' },
|
|
|
+ ).catch(() => {
|
|
|
+ cancelled = true;
|
|
|
+ });
|
|
|
+ if (cancelled) return;
|
|
|
+ const payload = serializeLeavePolicy({ ...row, status: nextStatusText });
|
|
|
+ await saveLeavePolicy(payload);
|
|
|
+ const next = toDisabled
|
|
|
+ ? { status: '已归档', action: '恢复' }
|
|
|
+ : { status: '未生效', action: '修改', approval: '待审核' };
|
|
|
+ Object.keys(next).forEach((key) => this.$set(this.form.leaveRules[index], key, next[key]));
|
|
|
+ this.$message.success(toDisabled ? '已停用' : '已恢复为可编辑');
|
|
|
+ } catch (error) {
|
|
|
+ this.$message.error(error.message || '操作失败');
|
|
|
+ } finally {
|
|
|
+ this.leaveSaving = false;
|
|
|
+ }
|
|
|
},
|
|
|
},
|
|
|
};
|