| | |
| | | <el-form :inline="true" :model="filterForm" class="filter-form"> |
| | | <el-form-item label="员工姓名:"> |
| | | <el-input |
| | | v-model="filterForm.employeeName" |
| | | placeholder="请输入员工姓名" |
| | | clearable |
| | | style="width: 150px" |
| | | v-model="filterForm.staffName" |
| | | placeholder="请输入员工姓名" |
| | | clearable |
| | | style="width: 150px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="班次类型:"> |
| | | <el-select v-model="filterForm.shiftType" placeholder="请选择班次" clearable style="width: 120px"> |
| | | <el-option label="早班" value="早班" /> |
| | | <el-option label="中班" value="中班" /> |
| | | <el-option label="晚班" value="晚班" /> |
| | | <el-option label="夜班" value="夜班" /> |
| | | <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="日期范围:"> |
| | | <el-date-picker |
| | | v-model="filterForm.dateRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 250px" |
| | | v-model="filterForm.dateRange" |
| | | type="daterange" |
| | | range-separator="至" |
| | | start-placeholder="开始日期" |
| | | end-placeholder="结束日期" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 250px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleFilter"> |
| | | <el-icon><Search /></el-icon> |
| | | <el-icon><Search/></el-icon> |
| | | 筛选 |
| | | </el-button> |
| | | <el-button @click="resetFilter"> |
| | | <el-icon><Refresh /></el-icon> |
| | | <el-icon><Refresh/></el-icon> |
| | | 重置 |
| | | </el-button> |
| | | <el-button type="primary" @click="openScheduleDialog('add')"> |
| | | <el-icon><Plus /></el-icon> |
| | | <el-icon><Plus/></el-icon> |
| | | 新增排班 |
| | | </el-button> |
| | | </el-form-item> |
| | |
| | | <!-- 排班表格 --> |
| | | <div class="table-section"> |
| | | <el-table |
| | | :data="filteredScheduleList" |
| | | border |
| | | stripe |
| | | style="width: 100%" |
| | | height="calc(100vh - 18.5em)" |
| | | @selection-change="handleSelectionChange" |
| | | :data="scheduleList" |
| | | border |
| | | :loading="tableLoading" |
| | | stripe |
| | | style="width: 100%" |
| | | height="calc(100vh - 18.5em)" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column type="selection" width="55" /> |
| | | <el-table-column prop="employeeName" label="员工姓名" width="120" /> |
| | | <el-table-column prop="employeeId" label="员工工号" width="100" /> |
| | | <el-table-column prop="department" label="部门" width="120" /> |
| | | <el-table-column type="selection" width="55"/> |
| | | <el-table-column prop="staffName" label="员工姓名" width="120"/> |
| | | <el-table-column prop="staffNo" label="员工工号" width="100"/> |
| | | <el-table-column prop="department" label="部门" width="120"> |
| | | <template #default="scope"> |
| | | {{ (department_type.find(i => i.value === String(scope.row.department)) || {}).label }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="shiftType" label="班次类型" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getShiftTagType(scope.row.shiftType)"> |
| | | {{ scope.row.shiftType }} |
| | | {{ (shift_type.find(i => i.value === String(scope.row.shiftType)) || {}).label }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="workDate" label="工作日期" width="120" /> |
| | | <el-table-column prop="startTime" label="开始时间" width="100" /> |
| | | <el-table-column prop="endTime" label="结束时间" width="100" /> |
| | | <el-table-column prop="workDate" label="工作日期" width="120"/> |
| | | <el-table-column prop="startTime" label="开始时间" width="100"/> |
| | | <el-table-column prop="endTime" label="结束时间" width="100"/> |
| | | <el-table-column prop="workHours" label="工作时长" width="100"> |
| | | <template #default="scope"> |
| | | {{ scope.row.workHours }}小时 |
| | |
| | | <el-table-column prop="status" label="状态" width="100"> |
| | | <template #default="scope"> |
| | | <el-tag :type="getStatusTagType(scope.row.status)"> |
| | | {{ scope.row.status }} |
| | | {{ (schedule_status.find(i => i.value === String(scope.row.status)) || {}).label }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="remark" label="备注" min-width="150" /> |
| | | <el-table-column prop="remark" label="备注" min-width="150"/> |
| | | <el-table-column label="操作" width="200" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="openScheduleDialog('edit', scope.row)" |
| | | type="primary" |
| | | size="small" |
| | | @click="openScheduleDialog('edit', scope.row)" |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | size="small" |
| | | @click="handleDelete(scope.row)" |
| | | type="danger" |
| | | size="small" |
| | | @click="handleDelete(scope.row)" |
| | | > |
| | | 删除 |
| | | </el-button> |
| | |
| | | <!-- 批量操作 --> |
| | | <div class="batch-actions" v-if="selectedRows.length > 0"> |
| | | <el-button |
| | | type="danger" |
| | | @click="handleBatchDelete" |
| | | :disabled="selectedRows.length === 0" |
| | | type="danger" |
| | | @click="handleBatchDelete" |
| | | :disabled="selectedRows.length === 0" |
| | | > |
| | | 批量删除 ({{ selectedRows.length }}) |
| | | </el-button> |
| | |
| | | |
| | | <!-- 排班新增/编辑对话框 --> |
| | | <el-dialog |
| | | v-model="scheduleDialog" |
| | | :title="dialogType === 'add' ? '新增排班' : '编辑排班'" |
| | | width="700px" |
| | | @close="closeScheduleDialog" |
| | | v-model="scheduleDialog" |
| | | :title="dialogType === 'add' ? '新增排班' : '编辑排班'" |
| | | width="700px" |
| | | @close="closeScheduleDialog" |
| | | > |
| | | <el-form |
| | | :model="scheduleForm" |
| | | :rules="scheduleRules" |
| | | ref="scheduleFormRef" |
| | | label-width="120px" |
| | | :model="scheduleForm" |
| | | :rules="scheduleRules" |
| | | ref="scheduleFormRef" |
| | | label-width="120px" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="员工姓名:" prop="employeeName"> |
| | | <el-input v-model="scheduleForm.employeeName" placeholder="请输入员工姓名" /> |
| | | <el-form-item label="员工姓名:" prop="staffId"> |
| | | <el-select v-model="scheduleForm.staffId" placeholder="请输入员工姓名" style="width: 100%" |
| | | @change="handleSelectStaff"> |
| | | <el-option v-for="item in personList" :label="item.staffName" :value="item.id" :key="item.id"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="员工工号:" prop="employeeId"> |
| | | <el-input v-model="scheduleForm.employeeId" placeholder="请输入员工工号" /> |
| | | <el-form-item label="员工工号:" prop="staffNo"> |
| | | <el-input :disabled="true" v-model="scheduleForm.staffNo" placeholder=""/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="部门:" prop="department"> |
| | | <el-select v-model="scheduleForm.department" placeholder="请选择部门" style="width: 100%"> |
| | | <el-option label="技术部" value="技术部" /> |
| | | <el-option label="销售部" value="销售部" /> |
| | | <el-option label="人事部" value="人事部" /> |
| | | <el-option label="财务部" value="财务部" /> |
| | | <el-option label="生产部" value="生产部" /> |
| | | <el-option v-for="item in department_type" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="班次类型:" prop="shiftType"> |
| | | <el-select v-model="scheduleForm.shiftType" placeholder="请选择班次" style="width: 100%"> |
| | | <el-option label="早班" value="早班" /> |
| | | <el-option label="中班" value="中班" /> |
| | | <el-option label="晚班" value="晚班" /> |
| | | <el-option label="夜班" value="夜班" /> |
| | | <el-option v-for="item in shift_type" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="工作日期:" prop="workDate"> |
| | | <el-date-picker |
| | | v-model="scheduleForm.workDate" |
| | | type="date" |
| | | placeholder="选择工作日期" |
| | | style="width: 100%" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | v-model="scheduleForm.workDate" |
| | | type="date" |
| | | placeholder="选择工作日期" |
| | | style="width: 100%" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="状态:" prop="status"> |
| | | <el-select v-model="scheduleForm.status" placeholder="请选择状态" style="width: 100%"> |
| | | <el-option label="已安排" value="已安排" /> |
| | | <el-option label="已确认" value="已确认" /> |
| | | <el-option label="已完成" value="已完成" /> |
| | | <el-option label="已取消" value="已取消" /> |
| | | <el-option v-for="item in schedule_status" :label="item.label" :value="item.value" :key="item.value"/> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="开始时间:" prop="startTime"> |
| | | <el-time-picker |
| | | v-model="scheduleForm.startTime" |
| | | placeholder="选择开始时间" |
| | | style="width: 100%" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | v-model="scheduleForm.startTime" |
| | | placeholder="选择开始时间" |
| | | style="width: 100%" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="结束时间:" prop="endTime"> |
| | | <el-time-picker |
| | | v-model="scheduleForm.endTime" |
| | | placeholder="选择结束时间" |
| | | style="width: 100%" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | v-model="scheduleForm.endTime" |
| | | placeholder="选择结束时间" |
| | | style="width: 100%" |
| | | format="HH:mm" |
| | | value-format="HH:mm" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="备注:" prop="remark"> |
| | | <el-input |
| | | v-model="scheduleForm.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入备注信息" |
| | | v-model="scheduleForm.remark" |
| | | type="textarea" |
| | | :rows="3" |
| | | placeholder="请输入备注信息" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | |
| | | |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitScheduleForm">确认</el-button> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, computed, onMounted } from 'vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import { Plus, Download, Search, Refresh } from '@element-plus/icons-vue' |
| | | import {ref, reactive, computed, onMounted} from 'vue' |
| | | import {ElMessage, ElMessageBox} from 'element-plus' |
| | | import {useDict} from "@/utils/dict.js" |
| | | import {Plus, Download, Search, Refresh} from '@element-plus/icons-vue' |
| | | import {save, del, delByIds, listPage} from "@/api/personnelManagement/scheduling.js" |
| | | import {getStaffOnJob} from "@/api/personnelManagement/onboarding.js"; |
| | | import dayjs from "dayjs"; |
| | | |
| | | // 响应式数据 |
| | | const scheduleDialog = ref(false) |
| | |
| | | |
| | | // 筛选表单 |
| | | const filterForm = reactive({ |
| | | employeeName: '', |
| | | staffName: '', |
| | | shiftType: '', |
| | | dateRange: [] |
| | | }) |
| | |
| | | // 排班表单 |
| | | const scheduleForm = reactive({ |
| | | id: '', |
| | | employeeName: '', |
| | | employeeId: '', |
| | | staffId: '', |
| | | staffNo: '', |
| | | department: '', |
| | | shiftType: '', |
| | | workDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | workStartTime: '', |
| | | workEndTime: '', |
| | | workHours: 0, |
| | | status: '已安排', |
| | | status: '', |
| | | remark: '' |
| | | }) |
| | | |
| | | // 表单验证规则 |
| | | const scheduleRules = reactive({ |
| | | employeeName: [{ required: true, message: '请输入员工姓名', trigger: 'blur' }], |
| | | employeeId: [{ required: true, message: '请输入员工工号', trigger: 'blur' }], |
| | | department: [{ required: true, message: '请选择部门', trigger: 'change' }], |
| | | shiftType: [{ required: true, message: '请选择班次类型', trigger: 'change' }], |
| | | workDate: [{ required: true, message: '请选择工作日期', trigger: 'change' }], |
| | | startTime: [{ required: true, message: '请选择开始时间', trigger: 'change' }], |
| | | endTime: [{ required: true, message: '请选择结束时间', trigger: 'change' }], |
| | | status: [{ required: true, message: '请选择状态', trigger: 'change' }] |
| | | staffId: [{required: true, message: '请选择员工', trigger: 'change'}], |
| | | department: [{required: true, message: '请选择部门', trigger: 'change'}], |
| | | shiftType: [{required: true, message: '请选择班次类型', trigger: 'change'}], |
| | | workDate: [{required: true, message: '请选择工作日期', trigger: 'change'}], |
| | | startTime: [{required: true, message: '请选择开始时间', trigger: 'change'}], |
| | | endTime: [{required: true, message: '请选择结束时间', trigger: 'change'}], |
| | | status: [{required: true, message: '请选择状态', trigger: 'change'}] |
| | | }) |
| | | const tableLoading = ref(false) |
| | | |
| | | //字典 |
| | | const {department_type, schedule_status, shift_type} = useDict("department_type", "schedule_status", "shift_type") |
| | | // 人员列表 |
| | | const personList = ref([]); |
| | | |
| | | // 模拟排班数据 |
| | | const scheduleList = ref([ |
| | | { |
| | | id: 1, |
| | | employeeName: '张海洋', |
| | | employeeId: 'EMP001', |
| | | department: '技术部', |
| | | shiftType: '早班', |
| | | workDate: '2024-01-15', |
| | | startTime: '08:00', |
| | | endTime: '17:00', |
| | | workHours: 9, |
| | | status: '已安排', |
| | | remark: '正常排班' |
| | | }, |
| | | { |
| | | id: 2, |
| | | employeeName: '李超', |
| | | employeeId: 'EMP002', |
| | | department: '销售部', |
| | | shiftType: '中班', |
| | | workDate: '2024-01-15', |
| | | startTime: '14:00', |
| | | endTime: '22:00', |
| | | workHours: 8, |
| | | status: '已确认', |
| | | remark: '客户会议' |
| | | }, |
| | | { |
| | | id: 3, |
| | | employeeName: '王杰', |
| | | employeeId: 'EMP003', |
| | | department: '生产部', |
| | | shiftType: '晚班', |
| | | workDate: '2024-01-15', |
| | | startTime: '22:00', |
| | | endTime: '06:00', |
| | | workHours: 8, |
| | | status: '已安排', |
| | | remark: '夜班生产' |
| | | } |
| | | ]) |
| | | const scheduleList = ref([]) |
| | | |
| | | // 计算属性:筛选后的排班列表 |
| | | const filteredScheduleList = computed(() => { |
| | | let result = scheduleList.value |
| | | |
| | | if (filterForm.employeeName) { |
| | | result = result.filter(item => |
| | | item.employeeName.includes(filterForm.employeeName) |
| | | ) |
| | | } |
| | | /** |
| | | * 获取当前在职人员列表 |
| | | */ |
| | | const getPersonList = () => { |
| | | getStaffOnJob().then(res => { |
| | | personList.value = res.data |
| | | }) |
| | | }; |
| | | |
| | | if (filterForm.shiftType) { |
| | | result = result.filter(item => item.shiftType === filterForm.shiftType) |
| | | } |
| | | |
| | | if (filterForm.dateRange && filterForm.dateRange.length === 2) { |
| | | result = result.filter(item => { |
| | | const workDate = new Date(item.workDate) |
| | | const startDate = new Date(filterForm.dateRange[0]) |
| | | const endDate = new Date(filterForm.dateRange[1]) |
| | | return workDate >= startDate && workDate <= endDate |
| | | }) |
| | | } |
| | | const handleSelectStaff = (val) => { |
| | | let obj = personList.value.find(item => item.id === val) |
| | | scheduleForm.staffNo = obj.staffNo |
| | | |
| | | return result |
| | | }) |
| | | } |
| | | |
| | | // 获取班次标签类型 |
| | | const getShiftTagType = (shiftType) => { |
| | | const typeMap = { |
| | | '早班': 'success', |
| | | '中班': 'warning', |
| | | '晚班': 'info', |
| | | '夜班': 'danger' |
| | | } |
| | | const typeMap = Object.fromEntries(shift_type.value.map(i => [i.value, i.elTagType])) |
| | | return typeMap[shiftType] || 'info' |
| | | } |
| | | |
| | | // 获取状态标签类型 |
| | | const getStatusTagType = (status) => { |
| | | const typeMap = { |
| | | '已安排': 'info', |
| | | '已确认': 'warning', |
| | | '已完成': 'success', |
| | | '已取消': 'danger' |
| | | } |
| | | const typeMap = Object.fromEntries(schedule_status.value.map(i => [i.value, i.elTagType])) |
| | | return typeMap[status] || 'info' |
| | | } |
| | | |
| | | // 筛选 |
| | | const handleFilter = () => { |
| | | // 筛选逻辑已在计算属性中实现 |
| | | const handleFilter = async () => { |
| | | tableLoading.value = true |
| | | let searchForm = { |
| | | staffName: filterForm.staffName, |
| | | shiftType: filterForm.shiftType, |
| | | ...(filterForm.dateRange.length > 0 && { |
| | | startDate: filterForm.dateRange[0], |
| | | endDate: filterForm.dateRange[1], |
| | | }) |
| | | } |
| | | let resp = await listPage(searchForm) |
| | | scheduleList.value = resp.data.records.map(it => { |
| | | return { |
| | | ...it, |
| | | 'startTime': dayjs(it.workStartTime).format('HH:mm'), |
| | | 'endTime': dayjs(it.workEndTime).format('HH:mm'), |
| | | } |
| | | }) |
| | | tableLoading.value = false |
| | | |
| | | } |
| | | |
| | | // 重置筛选 |
| | | const resetFilter = () => { |
| | | filterForm.employeeName = '' |
| | | filterForm.staffName = '' |
| | | filterForm.shiftType = '' |
| | | filterForm.dateRange = [] |
| | | } |
| | |
| | | const openScheduleDialog = (type, data) => { |
| | | dialogType.value = type |
| | | scheduleDialog.value = true |
| | | |
| | | getPersonList() |
| | | if (type === 'edit' && data) { |
| | | // 编辑模式,复制数据 |
| | | Object.assign(scheduleForm, { ...data }) |
| | | Object.assign(scheduleForm, {...data}) |
| | | } else { |
| | | // 新增模式,重置表单 |
| | | Object.keys(scheduleForm).forEach(key => { |
| | | scheduleForm[key] = '' |
| | | }) |
| | | scheduleForm.status = '已安排' |
| | | // scheduleForm.status = '已安排' |
| | | scheduleForm.workDate = new Date().toISOString().split('T')[0] |
| | | } |
| | | } |
| | |
| | | |
| | | // 计算工作时长 |
| | | const calculateWorkHours = () => { |
| | | if (scheduleForm.startTime && scheduleForm.endTime) { |
| | | const start = new Date(`2000-01-01 ${scheduleForm.startTime}`) |
| | | const end = new Date(`2000-01-01 ${scheduleForm.endTime}`) |
| | | |
| | | if (end < start) { |
| | | // 跨天的情况 |
| | | end.setDate(end.getDate() + 1) |
| | | if (scheduleForm.workDate && scheduleForm.startTime && scheduleForm.endTime) { |
| | | // 使用 workDate 与 startTime 和 endTime 组合 |
| | | const startDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.startTime}`) |
| | | const endDateTime = new Date(`${scheduleForm.workDate} ${scheduleForm.endTime}`) |
| | | |
| | | // 处理跨天情况(结束时间早于开始时间) |
| | | if (endDateTime < startDateTime) { |
| | | // 跨天,将结束日期加一天 |
| | | endDateTime.setDate(endDateTime.getDate() + 1) |
| | | } |
| | | |
| | | const diffMs = end - start |
| | | // 计算工作时长(小时) |
| | | const diffMs = endDateTime - startDateTime |
| | | const diffHours = diffMs / (1000 * 60 * 60) |
| | | scheduleForm.workHours = Math.round(diffHours * 100) / 100 |
| | | scheduleForm.workStartTime = dayjs(startDateTime).format("YYYY-MM-DD HH:mm:ss") |
| | | scheduleForm.workEndTime = dayjs(endDateTime).format("YYYY-MM-DD HH:mm:ss") |
| | | |
| | | } |
| | | } |
| | | |
| | | // 提交排班表单 |
| | | const submitScheduleForm = () => { |
| | | scheduleFormRef.value.validate((valid) => { |
| | | if (valid) { |
| | | // 计算工作时长 |
| | | calculateWorkHours() |
| | | |
| | | if (dialogType.value === 'add') { |
| | | // 新增 |
| | | const newSchedule = { |
| | | ...scheduleForm, |
| | | id: Date.now() // 使用时间戳作为临时ID |
| | | } |
| | | scheduleList.value.push(newSchedule) |
| | | ElMessage.success('新增排班成功') |
| | | } else { |
| | | // 编辑 |
| | | const index = scheduleList.value.findIndex(item => item.id === scheduleForm.id) |
| | | if (index !== -1) { |
| | | scheduleList.value[index] = { ...scheduleForm } |
| | | ElMessage.success('编辑排班成功') |
| | | } |
| | | } |
| | | |
| | | closeScheduleDialog() |
| | | } |
| | | }) |
| | | const submitScheduleForm = async () => { |
| | | const valid = await scheduleFormRef.value.validate() |
| | | if (!valid) return |
| | | |
| | | calculateWorkHours() |
| | | const newSchedule = {...scheduleForm} |
| | | |
| | | try { |
| | | await save(newSchedule) |
| | | ElMessage.success('保存排班成功') |
| | | |
| | | handleFilter() |
| | | closeScheduleDialog() |
| | | } catch (err) { |
| | | ElMessage.error('保存失败') |
| | | } |
| | | } |
| | | |
| | | // 删除排班 |
| | | const handleDelete = (row) => { |
| | | ElMessageBox.confirm( |
| | | `确定要删除 ${row.employeeName} 的排班记录吗?`, |
| | | '删除提示', |
| | | { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | } |
| | | `确定要删除 ${row.staffName} 的排班记录吗?`, |
| | | '删除提示', |
| | | { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | } |
| | | ).then(() => { |
| | | const index = scheduleList.value.findIndex(item => item.id === row.id) |
| | | if (index !== -1) { |
| | | scheduleList.value.splice(index, 1) |
| | | ElMessage.success('删除成功') |
| | | } |
| | | del(row.id) |
| | | ElMessage.success('删除成功') |
| | | handleFilter() |
| | | }).catch(() => { |
| | | ElMessage.info('已取消删除') |
| | | }) |
| | |
| | | ElMessage.warning('请选择要删除的记录') |
| | | return |
| | | } |
| | | |
| | | |
| | | ElMessageBox.confirm( |
| | | `确定要删除选中的 ${selectedRows.value.length} 条排班记录吗?`, |
| | | '批量删除提示', |
| | | { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | } |
| | | `确定要删除选中的 ${selectedRows.value.length} 条排班记录吗?`, |
| | | '批量删除提示', |
| | | { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | } |
| | | ).then(() => { |
| | | const selectedIds = selectedRows.value.map(row => row.id) |
| | | scheduleList.value = scheduleList.value.filter(item => !selectedIds.includes(item.id)) |
| | | selectedRows.value = [] |
| | | delByIds(selectedRows.value.map(item => item.id)) |
| | | handleFilter() |
| | | ElMessage.success('批量删除成功') |
| | | }).catch(() => { |
| | | ElMessage.info('已取消删除') |
| | |
| | | selectedRows.value = selection |
| | | } |
| | | |
| | | // 监听时间变化,自动计算工作时长 |
| | | const watchTimeChange = () => { |
| | | if (scheduleForm.startTime && scheduleForm.endTime) { |
| | | calculateWorkHours() |
| | | } |
| | | } |
| | | |
| | | // 生命周期 |
| | | onMounted(() => { |
| | | // 页面初始化 |
| | | handleFilter() |
| | | }) |
| | | </script> |
| | | |
| | |
| | | .scheduling-container { |
| | | padding: 10px; |
| | | } |
| | | |
| | | |
| | | .page-header { |
| | | padding: 15px; |
| | | } |
| | | |
| | | |
| | | .page-header h2 { |
| | | font-size: 24px; |
| | | } |
| | | |
| | | |
| | | .header-controls { |
| | | flex-direction: column; |
| | | gap: 10px; |