<template>
|
<div class="app-container">
|
<el-tabs v-model="activeTab"
|
type="border-card">
|
<!-- 假期设置 -->
|
<el-tab-pane label="假期设置"
|
name="holiday">
|
<div class="tab-content">
|
<el-button type="primary"
|
@click="openDialog('holiday', 'add')">新增假期</el-button>
|
<el-table :data="holidayData"
|
border
|
style="width: 100%; margin-top: 20px;">
|
<el-table-column prop="name"
|
label="假期名称" />
|
<el-table-column prop="type"
|
label="假期类型">
|
<template #default="scope">
|
<el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="startDate"
|
label="开始日期" />
|
<el-table-column prop="endDate"
|
label="结束日期" />
|
<el-table-column prop="days"
|
label="天数"
|
align="center" />
|
<el-table-column prop="status"
|
label="状态">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
{{ scope.row.status === 'active' ? '启用' : '停用' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作"
|
fixed="right">
|
<template #default="scope">
|
<el-button type="primary"
|
size="small"
|
@click="openDialog('holiday', 'edit', scope.row)">编辑</el-button>
|
<el-button type="danger"
|
size="small"
|
@click="deleteItem('holiday', scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-tab-pane>
|
<!-- 年假设置 -->
|
<el-tab-pane label="年假设置"
|
name="annual">
|
<div class="tab-content">
|
<el-button type="primary"
|
@click="openDialog('annual', 'add')">新增年假规则</el-button>
|
<el-table :data="annualData"
|
border
|
style="width: 100%; margin-top: 20px;">
|
<el-table-column prop="employeeType"
|
label="员工类型">
|
<template #default="scope">
|
<el-tag :type="getTagType(scope.row.employeeType)">{{ getTypeLabel(scope.row.employeeType) }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="workYears"
|
label="工作年限" />
|
<el-table-column prop="annualDays"
|
label="年假天数"
|
align="center" />
|
<el-table-column prop="maxCarryOver"
|
label="最大结转天数"
|
align="center" />
|
<el-table-column prop="status"
|
label="状态">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
{{ scope.row.status === 'active' ? '启用' : '停用' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作"
|
fixed="right">
|
<template #default="scope">
|
<el-button type="primary"
|
size="small"
|
@click="openDialog('annual', 'edit', scope.row)">编辑</el-button>
|
<el-button type="danger"
|
size="small"
|
@click="deleteItem('annual', scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-tab-pane>
|
<!-- 加班设置 -->
|
<el-tab-pane label="加班设置"
|
name="overtime">
|
<div class="tab-content">
|
<el-button type="primary"
|
@click="openDialog('overtime', 'add')">新增加班规则</el-button>
|
<el-table :data="overtimeData"
|
border
|
style="width: 100%; margin-top: 20px;">
|
<el-table-column prop="name"
|
label="规则名称" />
|
<el-table-column prop="type"
|
label="加班类型">
|
<template #default="scope">
|
<el-tag :type="getTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="startTime"
|
label="开始时间" />
|
<el-table-column prop="endTime"
|
label="结束时间" />
|
<el-table-column prop="rate"
|
label="倍率"
|
align="center" />
|
<el-table-column prop="status"
|
label="状态">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
{{ scope.row.status === 'active' ? '启用' : '停用' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作"
|
fixed="right">
|
<template #default="scope">
|
<el-button type="primary"
|
size="small"
|
@click="openDialog('overtime', 'edit', scope.row)">编辑</el-button>
|
<el-button type="danger"
|
size="small"
|
@click="deleteItem('overtime', scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-tab-pane>
|
<!-- 上班时间设置 -->
|
<el-tab-pane label="上班时间设置"
|
name="worktime">
|
<div class="tab-content">
|
<el-button type="primary"
|
@click="openDialog('worktime', 'add')">新增时间段</el-button>
|
<el-table :data="worktimeData"
|
border
|
style="width: 100%; margin-top: 20px;">
|
<el-table-column prop="name"
|
label="时间段名称" />
|
<el-table-column prop="startTime"
|
label="上班时间" />
|
<el-table-column prop="endTime"
|
label="下班时间" />
|
<el-table-column prop="flexibleStart"
|
label="弹性上班">
|
<template #default="scope">
|
<el-tag :type="scope.row.flexibleStart === 'true' ? 'success' : 'info'">
|
{{ scope.row.flexibleStart === 'true' ? '是' : '否' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="flexibleMinutes"
|
label="弹性时间(分钟)"
|
width="120"
|
align="center" />
|
<el-table-column prop="status"
|
label="状态">
|
<template #default="scope">
|
<el-tag :type="scope.row.status === 'active' ? 'success' : 'info'">
|
{{ scope.row.status === 'active' ? '启用' : '停用' }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column label="操作"
|
fixed="right">
|
<template #default="scope">
|
<el-button type="primary"
|
size="small"
|
@click="openDialog('worktime', 'edit', scope.row)">编辑</el-button>
|
<el-button type="danger"
|
size="small"
|
@click="deleteItem('worktime', scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
</div>
|
</el-tab-pane>
|
<!-- 打卡记录 -->
|
<el-tab-pane label="打卡记录"
|
name="attendance">
|
<div class="tab-content">
|
<div style="margin-bottom: 20px;">
|
<el-date-picker v-model="attendanceDate"
|
type="date"
|
placeholder="选择日期"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD"
|
style="margin-right: 10px;"
|
@change="filterAttendanceData" />
|
<el-select v-model="attendanceStatus"
|
placeholder="选择状态"
|
style="width: 120px; margin-right: 10px;"
|
@change="filterAttendanceData">
|
<el-option label="全部"
|
value="" />
|
<el-option label="正常"
|
value="normal" />
|
<el-option label="迟到"
|
value="late" />
|
<el-option label="早退"
|
value="early" />
|
<el-option label="缺勤"
|
value="absent" />
|
</el-select>
|
<el-button type="primary"
|
@click="exportAttendance">导出记录</el-button>
|
</div>
|
<el-table :data="filteredAttendanceData"
|
border
|
style="width: 100%;">
|
<el-table-column prop="employeeName"
|
label="员工姓名"
|
width="120" />
|
<el-table-column prop="department"
|
label="部门"
|
width="120" />
|
<el-table-column prop="date"
|
label="日期"
|
width="120" />
|
<el-table-column prop="clockInTime"
|
label="上班打卡"
|
width="120" />
|
<el-table-column prop="clockOutTime"
|
label="下班打卡"
|
width="120" />
|
<el-table-column prop="workHours"
|
label="工作时长"
|
width="100"
|
align="center" />
|
<el-table-column prop="status"
|
label="状态"
|
width="100"
|
align="center">
|
<template #default="scope">
|
<el-tag :type="getAttendanceTagType(scope.row.status)">{{ getAttendanceStatusLabel(scope.row.status) }}</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column prop="location"
|
label="打卡地点"
|
width="150" />
|
<el-table-column prop="remark"
|
label="备注"
|
min-width="150" />
|
</el-table>
|
</div>
|
</el-tab-pane>
|
</el-tabs>
|
<!-- 通用弹窗 -->
|
<el-dialog v-model="dialogVisible"
|
:title="dialogTitle"
|
width="600px">
|
<el-form ref="formRef"
|
:model="form"
|
:rules="rules"
|
label-width="100px">
|
<el-form-item label="名称"
|
prop="name"
|
v-if="currentType !== 'annual'">
|
<el-input v-model="form.name"
|
placeholder="请输入名称" />
|
</el-form-item>
|
<el-form-item label="类型"
|
prop="type"
|
v-if="currentType === 'holiday' || currentType === 'overtime'">
|
<el-select v-model="form.type"
|
placeholder="请选择类型"
|
style="width: 100%">
|
<el-option v-for="option in getTypeOptions()"
|
:key="option.value"
|
:label="option.label"
|
:value="option.value" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="员工类型"
|
prop="employeeType"
|
v-if="currentType === 'annual'">
|
<el-select v-model="form.employeeType"
|
placeholder="请选择员工类型"
|
style="width: 100%">
|
<!-- <el-option label="正式员工" value="regular" />
|
<el-option label="试用期员工" value="probation" />
|
<el-option label="实习生" value="intern" /> -->
|
<el-option v-for="option in getTypeOptions()"
|
:key="option.value"
|
:label="option.label"
|
:value="option.value" />
|
</el-select>
|
</el-form-item>
|
<el-form-item label="工作年限"
|
prop="workYears"
|
v-if="currentType === 'annual'">
|
<el-input v-model="form.workYears"
|
placeholder="如:1-3年、3-5年等" />
|
</el-form-item>
|
<el-form-item label="年假天数"
|
prop="annualDays"
|
v-if="currentType === 'annual'">
|
<el-input-number v-model="form.annualDays"
|
:min="0"
|
:max="365"
|
style="width: 100%" />
|
</el-form-item>
|
<el-form-item label="最大结转天数"
|
prop="maxCarryOver"
|
v-if="currentType === 'annual'">
|
<el-input-number v-model="form.maxCarryOver"
|
:min="0"
|
:max="30"
|
style="width: 100%" />
|
</el-form-item>
|
<el-form-item label="日期范围"
|
prop="dateRange"
|
v-if="currentType === 'holiday'">
|
<el-date-picker v-model="form.dateRange"
|
type="daterange"
|
range-separator="至"
|
start-placeholder="开始日期"
|
end-placeholder="结束日期"
|
style="width: 100%"
|
@change="calculateDays" />
|
</el-form-item>
|
<el-form-item label="天数"
|
prop="days"
|
v-if="currentType === 'holiday'">
|
<el-input-number v-model="form.days"
|
:min="0"
|
style="width: 100%" />
|
</el-form-item>
|
<el-form-item label="开始时间"
|
prop="startTime"
|
v-if="currentType === 'overtime'">
|
<el-time-picker v-model="form.startTime"
|
placeholder="开始时间"
|
format="HH:mm"
|
value-format="HH:mm"
|
style="width: 100%"
|
@change="validateTimeField('startTime')" />
|
</el-form-item>
|
<el-form-item label="结束时间"
|
prop="endTime"
|
v-if="currentType === 'overtime'">
|
<el-time-picker v-model="form.endTime"
|
placeholder="结束时间"
|
format="HH:mm"
|
value-format="HH:mm"
|
style="width: 100%"
|
@change="validateTimeField('endTime')" />
|
</el-form-item>
|
<el-form-item label="倍率"
|
prop="rate"
|
v-if="currentType === 'overtime'">
|
<el-input-number v-model="form.rate"
|
:min="1"
|
:max="3"
|
:step="0.5"
|
style="width: 100%" />
|
</el-form-item>
|
<el-form-item label="上班时间"
|
prop="workStartTime"
|
v-if="currentType === 'worktime'">
|
<el-time-picker v-model="form.workStartTime"
|
placeholder="上班时间"
|
format="HH:mm"
|
value-format="HH:mm"
|
style="width: 100%"
|
@change="validateTimeField('workStartTime')" />
|
</el-form-item>
|
<el-form-item label="下班时间"
|
prop="workEndTime"
|
v-if="currentType === 'worktime'">
|
<el-time-picker v-model="form.workEndTime"
|
placeholder="下班时间"
|
format="HH:mm"
|
value-format="HH:mm"
|
style="width: 100%"
|
@change="validateTimeField('workEndTime')" />
|
</el-form-item>
|
<el-form-item label="弹性上班"
|
prop="flexibleStart"
|
v-if="currentType === 'worktime'">
|
<el-switch v-model="form.flexibleStart" />
|
</el-form-item>
|
<el-form-item label="弹性时间(分钟)"
|
prop="flexibleMinutes"
|
v-if="currentType === 'worktime' && form.flexibleStart">
|
<el-input-number v-model="form.flexibleMinutes"
|
:min="0"
|
:max="120"
|
style="width: 100%" />
|
</el-form-item>
|
<el-form-item label="状态"
|
prop="status">
|
<el-radio-group v-model="form.status">
|
<el-radio value="active">启用</el-radio>
|
<el-radio value="inactive">停用</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button type="primary"
|
@click="submitForm">确定</el-button>
|
<el-button @click="dialogVisible = false">取消</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import { ref, reactive, onMounted, onUnmounted } from "vue";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
import {
|
listHolidaySettings,
|
addHolidaySettings,
|
updateHolidaySettings,
|
delHolidaySettings,
|
listAnnualLeaveSettingList,
|
addAnnualLeaveSetting,
|
updateAnnualLeaveSetting,
|
delAnnualLeaveSetting,
|
listOvertimeSettingList,
|
addOvertimeSetting,
|
updateOvertimeSetting,
|
delOvertimeSetting,
|
listWorkingHoursSettingList,
|
addWorkingHoursSetting,
|
updateWorkingHoursSetting,
|
delWorkingHoursSetting,
|
} from "@/api/collaborativeApproval/attendanceManagement.js";
|
|
// 当前激活的标签页
|
const activeTab = ref("holiday");
|
|
// 弹窗相关
|
const dialogVisible = ref(false);
|
const dialogTitle = ref("");
|
const currentType = ref("");
|
const currentAction = ref("");
|
const currentEditId = ref("");
|
const formRef = ref();
|
const page = {
|
current: 1,
|
size: 20,
|
total: 0,
|
};
|
const holidayData = ref([]);
|
const annualData = ref([]);
|
const overtimeData = ref([]);
|
const worktimeData = ref([]);
|
|
// 打卡记录相关数据
|
const attendanceData = ref([]);
|
const filteredAttendanceData = ref([]);
|
const attendanceDate = ref("");
|
const attendanceStatus = ref("");
|
|
// 表单数据
|
const form = reactive({
|
name: "",
|
type: "",
|
dateRange: [],
|
startDate: "",
|
endDate: "",
|
days: 0,
|
employeeType: "",
|
workYears: "",
|
annualDays: 0,
|
maxCarryOver: 0,
|
startTime: "", // 加班开始时间
|
endTime: "", // 加班结束时间
|
workStartTime: "", // 上班时间
|
workEndTime: "", // 下班时间
|
rate: 1.5,
|
flexibleStart: false,
|
flexibleMinutes: 30,
|
status: "active",
|
});
|
|
// 表单验证规则
|
const rules = {
|
name: [{ required: true, message: "请输入名称", trigger: "blur" }],
|
type: [{ required: true, message: "请选择类型", trigger: "change" }],
|
dateRange: [{ required: true, message: "请选择日期范围", trigger: "change" }],
|
days: [{ required: true, message: "请输入天数", trigger: "blur" }],
|
employeeType: [
|
{ required: true, message: "请选择员工类型", trigger: "change" },
|
],
|
workYears: [{ required: true, message: "请输入工作年限", trigger: "blur" }],
|
annualDays: [{ required: true, message: "请输入年假天数", trigger: "blur" }],
|
maxCarryOver: [
|
{ required: true, message: "请输入最大结转天数", trigger: "blur" },
|
],
|
startTime: [
|
{
|
required: true,
|
message: "请选择开始时间",
|
trigger: "change",
|
validator: (rule, value, callback) => {
|
if (!value) {
|
callback(new Error("请选择开始时间"));
|
} else {
|
callback();
|
}
|
},
|
},
|
],
|
endTime: [
|
{
|
required: true,
|
message: "请选择结束时间",
|
trigger: "change",
|
validator: (rule, value, callback) => {
|
if (!value) {
|
callback(new Error("请选择结束时间"));
|
} else {
|
callback();
|
}
|
},
|
},
|
],
|
workStartTime: [
|
{
|
required: true,
|
message: "请选择上班时间",
|
trigger: "change",
|
validator: (rule, value, callback) => {
|
if (!value) {
|
callback(new Error("请选择上班时间"));
|
} else {
|
callback();
|
}
|
},
|
},
|
],
|
workEndTime: [
|
{
|
required: true,
|
message: "请选择下班时间",
|
trigger: "change",
|
validator: (rule, value, callback) => {
|
if (!value) {
|
callback(new Error("请选择下班时间"));
|
} else {
|
callback();
|
}
|
},
|
},
|
],
|
rate: [{ required: true, message: "请输入倍率", trigger: "blur" }],
|
};
|
// 工具函数
|
const getTagType = type => {
|
const tagMap = {
|
legal: "success",
|
adjustment: "warning",
|
special: "info",
|
company: "primary",
|
weekday: "primary",
|
weekend: "warning",
|
holiday: "danger",
|
night: "info",
|
regular: "success",
|
probation: "info",
|
intern: "danger",
|
};
|
return tagMap[type] || "info";
|
};
|
|
const getTypeLabel = type => {
|
const labelMap = {
|
legal: "法定节假日",
|
adjustment: "调休日",
|
special: "特殊假期",
|
company: "公司假期",
|
weekday: "工作日加班",
|
weekend: "周末加班",
|
holiday: "节假日加班",
|
night: "深夜加班",
|
regular: "正式员工",
|
probation: "试用期员工",
|
intern: "实习生",
|
};
|
return labelMap[type] || type;
|
};
|
|
// 打卡记录相关工具函数
|
const getAttendanceTagType = status => {
|
const tagMap = {
|
normal: "success",
|
late: "warning",
|
early: "warning",
|
absent: "danger",
|
};
|
return tagMap[status] || "info";
|
};
|
|
const getAttendanceStatusLabel = status => {
|
const labelMap = {
|
normal: "正常",
|
late: "迟到",
|
early: "早退",
|
absent: "缺勤",
|
};
|
return labelMap[status] || status;
|
};
|
|
const getTypeOptions = () => {
|
if (currentType.value === "holiday") {
|
return [
|
{ label: "法定节假日", value: "legal" },
|
{ label: "调休日", value: "adjustment" },
|
{ label: "特殊假期", value: "special" },
|
{ label: "公司假期", value: "company" },
|
];
|
} else if (currentType.value === "overtime") {
|
return [
|
{ label: "工作日加班", value: "weekday" },
|
{ label: "周末加班", value: "weekend" },
|
{ label: "节假日加班", value: "holiday" },
|
{ label: "深夜加班", value: "night" },
|
];
|
} else if (currentType.value === "annual") {
|
return [
|
{ label: "正式员工", value: "regular" },
|
{ label: "试用期员工", value: "probation" },
|
{ label: "实习生", value: "intern" },
|
];
|
}
|
return [];
|
};
|
|
// 计算假期天数
|
const calculateDays = () => {
|
try {
|
if (
|
form.dateRange &&
|
form.dateRange.length === 2 &&
|
form.dateRange[0] &&
|
form.dateRange[1]
|
) {
|
const start = new Date(form.dateRange[0]);
|
const end = new Date(form.dateRange[1]);
|
form.startDate = start.toISOString().split("T")[0];
|
form.endDate = end.toISOString().split("T")[0];
|
|
if (isNaN(start.getTime()) || isNaN(end.getTime())) {
|
console.warn("无效的日期格式");
|
return;
|
}
|
|
const diffTime = Math.abs(end - start);
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)) + 1;
|
form.days = diffDays;
|
}
|
} catch (error) {
|
console.error("计算天数失败:", error);
|
}
|
};
|
|
// 验证时间格式
|
// const validateTime = (time) => {
|
// if (!time) return ''
|
// if (typeof time === 'string') return time
|
// if (time instanceof Date) {
|
// return time.toTimeString().slice(0, 5)
|
// }
|
// return ''
|
// }
|
|
// 验证时间字段
|
const validateTimeField = fieldName => {
|
try {
|
const value = form[fieldName];
|
if (value && typeof value === "object" && value.hour !== undefined) {
|
// 如果是时间对象,转换为字符串格式
|
const hours = value.hour.toString().padStart(2, "0");
|
const minutes = value.minute.toString().padStart(2, "0");
|
form[fieldName] = `${hours}:${minutes}`;
|
}
|
} catch (error) {
|
console.error(`验证时间字段 ${fieldName} 失败:`, error);
|
form[fieldName] = "";
|
}
|
};
|
|
// 打开弹窗
|
const openDialog = (type, action, row = null) => {
|
try {
|
currentType.value = type;
|
currentAction.value = action;
|
|
if (action === "add") {
|
dialogTitle.value = `新增${getTypeName(type)}`;
|
currentEditId.value = "";
|
resetForm();
|
} else if (action === "edit" && row) {
|
dialogTitle.value = `编辑${getTypeName(type)}`;
|
currentEditId.value = row.id;
|
fillForm(row);
|
}
|
|
dialogVisible.value = true;
|
} catch (error) {
|
console.error("打开弹窗失败:", error);
|
ElMessage.error("打开弹窗失败,请重试");
|
}
|
};
|
|
const getTypeName = type => {
|
const nameMap = {
|
holiday: "假期",
|
annual: "年假规则",
|
overtime: "加班规则",
|
worktime: "时间段",
|
};
|
return nameMap[type] || "";
|
};
|
|
const resetForm = () => {
|
Object.assign(form, {
|
name: "",
|
type: "",
|
dateRange: [],
|
startDate: "",
|
endDate: "",
|
days: 0,
|
employeeType: "",
|
workYears: "",
|
annualDays: 0,
|
maxCarryOver: 0,
|
startTime: "",
|
endTime: "",
|
workStartTime: "",
|
workEndTime: "",
|
rate: 1.5,
|
flexibleStart: false,
|
flexibleMinutes: 30,
|
status: "active",
|
});
|
};
|
|
const fillForm = row => {
|
if (currentType.value === "holiday") {
|
Object.assign(form, {
|
name: row.name,
|
type: row.type,
|
dateRange: [new Date(row.startDate), new Date(row.endDate)],
|
startDate: row.startDate,
|
endDate: row.endDate,
|
days: row.days,
|
status: row.status,
|
});
|
} else if (currentType.value === "annual") {
|
Object.assign(form, {
|
employeeType: row.employeeType,
|
workYears: row.workYears,
|
annualDays: row.annualDays,
|
maxCarryOver: row.maxCarryOver,
|
status: row.status,
|
});
|
} else if (currentType.value === "overtime") {
|
Object.assign(form, {
|
name: row.name,
|
type: row.type,
|
startTime: row.startTime || "",
|
endTime: row.endTime || "",
|
rate: row.rate,
|
status: row.status,
|
});
|
} else if (currentType.value === "worktime") {
|
Object.assign(form, {
|
name: row.name,
|
workStartTime: row.startTime || "",
|
workEndTime: row.endTime || "",
|
flexibleStart: row.flexibleStart,
|
flexibleMinutes: row.flexibleMinutes,
|
status: row.status,
|
});
|
}
|
};
|
|
// 提交表单
|
const submitForm = async () => {
|
try {
|
if (!formRef.value) {
|
ElMessage.error("表单引用不存在");
|
return;
|
}
|
|
await formRef.value.validate();
|
|
if (currentAction.value === "add") {
|
addItem();
|
} else if (currentAction.value === "edit") {
|
editItem();
|
}
|
|
dialogVisible.value = false;
|
ElMessage.success("操作成功");
|
} catch (error) {
|
console.error("表单验证失败:", error);
|
ElMessage.error("表单验证失败,请检查输入");
|
}
|
};
|
|
const addItem = () => {
|
if (currentType.value === "holiday") {
|
const params = {
|
name: form.name,
|
type: form.type,
|
startDate: form.startDate,
|
endDate: form.endDate,
|
days: form.days,
|
status: form.status,
|
};
|
addHolidaySettings(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("添加成功");
|
// dialogVisible.value = false;
|
getHolidaySettingsList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (currentType.value === "annual") {
|
// annualData.value.push(newItem)
|
const params = {
|
employeeType: form.employeeType,
|
workYears: form.workYears,
|
annualDays: form.annualDays,
|
maxCarryOver: form.maxCarryOver,
|
status: form.status,
|
};
|
addAnnualLeaveSetting(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("添加成功");
|
// dialogVisible.value = false;
|
getAnnualLeaveSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (currentType.value === "overtime") {
|
const params = {
|
name: form.name,
|
type: form.type,
|
startTime: form.startTime || "",
|
endTime: form.endTime || "",
|
rate: form.rate,
|
status: form.status,
|
};
|
addOvertimeSetting(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("添加成功");
|
// dialogVisible.value = false;
|
getOvertimeSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
// newItem.startTime = form.startTime || ''
|
// newItem.endTime = form.endTime || ''
|
// overtimeData.value.push(newItem)
|
} else if (currentType.value === "worktime") {
|
const params = {
|
name: form.name,
|
startTime: form.workStartTime || "",
|
endTime: form.workEndTime || "",
|
flexibleStart: form.flexibleStart,
|
flexibleMinutes: form.flexibleMinutes,
|
status: form.status,
|
};
|
addWorkingHoursSetting(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("添加成功");
|
getWorkingHoursSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
// newItem.startTime = form.workStartTime || ''
|
// newItem.endTime = form.workEndTime || ''
|
// worktimeData.value.push(newItem)
|
}
|
};
|
|
const editItem = () => {
|
let dataArray;
|
let index;
|
|
if (currentType.value === "holiday") {
|
const params = {
|
id: currentEditId.value,
|
name: form.name,
|
type: form.type,
|
startDate: form.dateRange[0].toISOString().split("T")[0],
|
endDate: form.dateRange[1].toISOString().split("T")[0],
|
days: form.days,
|
status: form.status,
|
};
|
updateHolidaySettings(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("更新成功");
|
// dialogVisible.value = false;
|
getHolidaySettingsList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (currentType.value === "annual") {
|
const params = {
|
id: currentEditId.value,
|
employeeType: form.employeeType,
|
workYears: form.workYears,
|
annualDays: form.annualDays,
|
maxCarryOver: form.maxCarryOver,
|
status: form.status,
|
};
|
updateAnnualLeaveSetting(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("更新成功");
|
getAnnualLeaveSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (currentType.value === "overtime") {
|
const params = {
|
id: currentEditId.value,
|
name: form.name,
|
type: form.type,
|
startTime: form.startTime || "",
|
endTime: form.endTime || "",
|
rate: form.rate,
|
status: form.status,
|
};
|
updateOvertimeSetting(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("更新成功");
|
getOvertimeSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
|
// dataArray = overtimeData.value
|
// index = dataArray.findIndex(item => item.id === currentEditId.value)
|
// if (index > -1) {
|
// dataArray[index] = {
|
// ...dataArray[index],
|
// name: form.name,
|
// type: form.type,
|
// startTime: form.startTime || '',
|
// endTime: form.endTime || '',
|
// rate: form.rate,
|
// status: form.status
|
// }
|
// }
|
} else if (currentType.value === "worktime") {
|
const params = {
|
id: currentEditId.value,
|
name: form.name,
|
startTime: form.workStartTime || "",
|
endTime: form.workEndTime || "",
|
flexibleStart: form.flexibleStart,
|
flexibleMinutes: form.flexibleMinutes,
|
status: form.status,
|
};
|
updateWorkingHoursSetting(params)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("更新成功");
|
getWorkingHoursSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
// dataArray = worktimeData.value
|
// index = dataArray.findIndex(item => item.id === currentEditId.value)
|
// if (index > -1) {
|
// dataArray[index] = {
|
// ...dataArray[index],
|
// name: form.name,
|
// startTime: form.workStartTime || '',
|
// endTime: form.workEndTime || '',
|
// flexibleStart: form.flexibleStart,
|
// flexibleMinutes: form.flexibleMinutes,
|
// status: form.status
|
// }
|
// }
|
}
|
};
|
|
// 打卡记录过滤功能
|
const filterAttendanceData = () => {
|
let filtered = attendanceData.value;
|
|
// 按日期过滤
|
if (attendanceDate.value) {
|
filtered = filtered.filter(item => item.date === attendanceDate.value);
|
}
|
|
// 按状态过滤
|
if (attendanceStatus.value) {
|
filtered = filtered.filter(item => item.status === attendanceStatus.value);
|
}
|
|
filteredAttendanceData.value = filtered;
|
};
|
|
// 导出打卡记录
|
const exportAttendance = () => {
|
ElMessage.success("导出功能开发中...");
|
};
|
|
// 初始化打卡记录假数据
|
const initAttendanceData = () => {
|
const mockData = [
|
{
|
id: 1,
|
employeeName: "陈志强",
|
department: "技术部",
|
date: "2025-08-15",
|
clockInTime: "09:00:00",
|
clockOutTime: "18:00:00",
|
workHours: "8.0h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 2,
|
employeeName: "李雪梅",
|
department: "市场部",
|
date: "2025-08-16",
|
clockInTime: "08:58:00",
|
clockOutTime: "18:05:00",
|
workHours: "8.12h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 3,
|
employeeName: "王建华",
|
department: "人事部",
|
date: "2025-08-16",
|
clockInTime: "09:02:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.97h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 4,
|
employeeName: "赵晓丽",
|
department: "财务部",
|
date: "2025-09-02",
|
clockInTime: "08:55:00",
|
clockOutTime: "18:10:00",
|
workHours: "8.25h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 5,
|
employeeName: "张国庆",
|
department: "技术部",
|
date: "2025-09-02",
|
clockInTime: "09:00:00",
|
clockOutTime: "18:30:00",
|
workHours: "8.5h",
|
status: "normal",
|
location: "公司总部",
|
remark: "加班",
|
},
|
{
|
id: 6,
|
employeeName: "刘明辉",
|
department: "运营部",
|
date: "2025-09-03",
|
clockInTime: "09:05:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.92h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 7,
|
employeeName: "孙丽华",
|
department: "设计部",
|
date: "2025-09-03",
|
clockInTime: "08:59:00",
|
clockOutTime: "18:02:00",
|
workHours: "8.05h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 8,
|
employeeName: "周建军",
|
department: "销售部",
|
date: "2025-09-04",
|
clockInTime: "09:15:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.75h",
|
status: "late",
|
location: "公司总部",
|
remark: "交通堵塞",
|
},
|
{
|
id: 9,
|
employeeName: "吴小芳",
|
department: "客服部",
|
date: "2025-09-04",
|
clockInTime: "09:01:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.98h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 10,
|
employeeName: "马文杰",
|
department: "技术部",
|
date: "2025-09-05",
|
clockInTime: "08:57:00",
|
clockOutTime: "17:30:00",
|
workHours: "7.55h",
|
status: "early",
|
location: "公司总部",
|
remark: "有急事提前离开",
|
},
|
{
|
id: 11,
|
employeeName: "林晓东",
|
department: "行政部",
|
date: "2025-09-05",
|
clockInTime: "09:03:00",
|
clockOutTime: "18:08:00",
|
workHours: "8.08h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 12,
|
employeeName: "黄美玲",
|
department: "财务部",
|
date: "2025-09-06",
|
clockInTime: "",
|
clockOutTime: "",
|
workHours: "0h",
|
status: "absent",
|
location: "",
|
remark: "请病假",
|
},
|
{
|
id: 13,
|
employeeName: "郑海涛",
|
department: "市场部",
|
date: "2025-08-14",
|
clockInTime: "09:00:00",
|
clockOutTime: "18:00:00",
|
workHours: "8.0h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 14,
|
employeeName: "谢丽娟",
|
department: "人事部",
|
date: "2025-08-20",
|
clockInTime: "08:58:00",
|
clockOutTime: "18:03:00",
|
workHours: "8.08h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 15,
|
employeeName: "何志伟",
|
department: "技术部",
|
date: "2025-08-21",
|
clockInTime: "09:10:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.83h",
|
status: "late",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 16,
|
employeeName: "许雅芳",
|
department: "设计部",
|
date: "2025-08-22",
|
clockInTime: "09:01:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.98h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 17,
|
employeeName: "邓建平",
|
department: "运营部",
|
date: "2025-09-10",
|
clockInTime: "08:59:00",
|
clockOutTime: "18:05:00",
|
workHours: "8.1h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
{
|
id: 18,
|
employeeName: "曾小红",
|
department: "客服部",
|
date: "2025-09-11",
|
clockInTime: "09:02:00",
|
clockOutTime: "18:00:00",
|
workHours: "7.97h",
|
status: "normal",
|
location: "公司总部",
|
remark: "",
|
},
|
];
|
|
attendanceData.value = mockData;
|
filteredAttendanceData.value = mockData;
|
};
|
|
// 删除项目
|
const deleteItem = (type, row) => {
|
ElMessageBox.confirm("确定要删除这个项目吗?", "提示", {
|
confirmButtonText: "确定",
|
cancelButtonText: "取消",
|
type: "warning",
|
}).then(() => {
|
let ids = [];
|
let dataArray;
|
if (type === "holiday") {
|
ids.push(row.id);
|
delHolidaySettings(ids)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("删除成功");
|
ids = [];
|
getHolidaySettingsList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (type === "annual") {
|
ids.push(row.id);
|
delAnnualLeaveSetting(ids)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("删除成功");
|
ids = [];
|
getAnnualLeaveSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (type === "overtime") {
|
ids.push(row.id);
|
delOvertimeSetting(ids)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("删除成功");
|
ids = [];
|
getOvertimeSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
} else if (type === "worktime") {
|
ids.push(row.id);
|
delWorkingHoursSetting(ids)
|
.then(res => {
|
if (res.code == 200) {
|
ElMessage.success("删除成功");
|
ids = [];
|
getWorkingHoursSettingList();
|
}
|
})
|
.catch(err => {
|
ElMessage.error(err.msg);
|
});
|
}
|
|
// const index = dataArray.findIndex(item => item.id === row.id)
|
// if (index > -1) {
|
// dataArray.splice(index, 1)
|
// ElMessage.success('删除成功')
|
// }
|
});
|
};
|
// 获取假期设置列表
|
const getHolidaySettingsList = () => {
|
// tableLoading.value = true;
|
listHolidaySettings({ ...page.value })
|
.then(res => {
|
// tableLoading.value = false;
|
holidayData.value = res.data.records;
|
page.total = res.data.total;
|
})
|
.catch(err => {
|
// tableLoading.value = false;
|
});
|
};
|
// 获取年假规则列表
|
const getAnnualLeaveSettingList = () => {
|
listAnnualLeaveSettingList({ ...page.value })
|
.then(res => {
|
// console.log(res.data)
|
annualData.value = res.data.records;
|
page.total = res.data.total;
|
})
|
.catch(err => {});
|
};
|
// 获取加班规则列表
|
const getOvertimeSettingList = () => {
|
listOvertimeSettingList({ ...page.value })
|
.then(res => {
|
// console.log(res.data)
|
overtimeData.value = res.data.records;
|
page.total = res.data.total;
|
})
|
.catch(err => {});
|
};
|
// 获取工作时间规则列表
|
const getWorkingHoursSettingList = () => {
|
listWorkingHoursSettingList({ ...page.value })
|
.then(res => {
|
// console.log(res.data)
|
worktimeData.value = res.data.records;
|
page.total = res.data.total;
|
})
|
.catch(err => {});
|
};
|
onMounted(() => {
|
getHolidaySettingsList();
|
getAnnualLeaveSettingList();
|
getOvertimeSettingList();
|
getWorkingHoursSettingList();
|
initAttendanceData();
|
console.log("考勤管理页面加载完成");
|
});
|
|
onUnmounted(() => {
|
// 清理工作
|
dialogVisible.value = false;
|
currentType.value = "";
|
currentAction.value = "";
|
currentEditId.value = "";
|
});
|
</script>
|
|
<style scoped>
|
.app-container {
|
padding: 20px;
|
}
|
|
.tab-content {
|
padding: 20px 0;
|
}
|
|
.dialog-footer {
|
text-align: right;
|
}
|
|
:deep(.el-tabs__content) {
|
padding: 20px;
|
}
|
|
:deep(.el-form-item) {
|
margin-bottom: 20px;
|
}
|
</style>
|