| | |
| | | 'shift-box-early': m.shift === '早班', |
| | | 'shift-box-mid': m.shift === '中班', |
| | | 'shift-box-night': m.shift === '夜班', |
| | | 'shift-box-rest': m.shift === '休息', |
| | | 'shift-box-rest': !m.shift || m.shift === '休息', |
| | | 'shift-box-leave': m.shift === '请假', |
| | | 'shift-box-other': m.shift === '夜11', |
| | | 'shift-box-business': m.shift === '夜12', |
| | | }"> |
| | | <span class="shift-text">{{ getShiftNameByValue(m.shift) || '—' }}</span> |
| | | <span class="shift-text">{{ getShiftNameByValue(m.shift) || '休息' }}</span> |
| | | </div> |
| | | <template #dropdown> |
| | | <el-dropdown-menu> |
| | |
| | | </div> --> |
| | | <div class="user-total"> |
| | | <span class="total-label">合计出勤:</span> |
| | | <span class="total-value">{{ item.work_time }}天</span> |
| | | <span class="total-value">{{ item.year.totalYearAttendance }}天</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="search_thing"> |
| | | <div class="search_label" |
| | | style="width: 90px"> |
| | | <span style="color: red; margin-right: 4px">*</span>部门: |
| | | </div> |
| | | <div class="search_input"> |
| | | <el-tree-select v-model="schedulingQuery.deptId" |
| | | :data="deptOptions" |
| | | :props="{ value: 'id', label: 'label', children: 'children' }" |
| | | value-key="id" |
| | | placeholder="请选择部门" |
| | | check-strictly |
| | | clearable |
| | | @change="onSchedulingDeptChange" |
| | | style="width: 100%" /> |
| | | </div> |
| | | </div> |
| | | <div class="search_thing"> |
| | | <div class="search_label" |
| | | style="width: 90px"> |
| | | <span style="color: red; margin-right: 4px">*</span>人员名称: |
| | | </div> |
| | | <div class="search_input"> |
| | |
| | | style="width: 100%" |
| | | multiple |
| | | clearable |
| | | collapse-tags> |
| | | collapse-tags |
| | | :disabled="!schedulingQuery.deptId"> |
| | | <el-option v-for="item in personList" |
| | | :key="item.id" |
| | | :label="item.staffName" |
| | |
| | | <div class="search_input"> |
| | | <el-select v-model="schedulingQuery.shift" |
| | | placeholder="请选择" |
| | | style="width: 100%"> |
| | | <el-option v-for="item in classType" |
| | | style="width: 100%" |
| | | :disabled="!schedulingQuery.deptId"> |
| | | <el-option v-for="item in schedulingClassType" |
| | | :key="item.id" |
| | | :label="getShiftNameByValue(item.shift)" |
| | | :value="item.id"> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted, getCurrentInstance } from "vue"; |
| | | import { |
| | | ref, |
| | | reactive, |
| | | computed, |
| | | watch, |
| | | onMounted, |
| | | getCurrentInstance, |
| | | } from "vue"; |
| | | import { useRouter } from "vue-router"; |
| | | import { |
| | | page, |
| | |
| | | |
| | | // 人员列表 |
| | | const personList = ref([]); |
| | | const personListAll = ref([]); |
| | | |
| | | // 加载状态 |
| | | const loading = ref(false); |
| | |
| | | // 排班查询条件 |
| | | const schedulingQuery = reactive({ |
| | | week: "", |
| | | deptId: "", |
| | | userId: null, |
| | | shift: "", |
| | | }); |
| | | |
| | | const schedulingClassType = computed(() => { |
| | | if (!schedulingQuery.deptId) return classType.value || []; |
| | | return (classType.value || []).filter(item => { |
| | | if (["998", "999"].includes(String(item?.id))) return true; |
| | | const itemDeptId = item.deptId ?? item.sysDeptId ?? item.dept_id; |
| | | return String(itemDeptId) === String(schedulingQuery.deptId); |
| | | }); |
| | | }); |
| | | |
| | | // 列表数据 |
| | |
| | | proxy.$modal.msgError("请选择周次"); |
| | | return; |
| | | } |
| | | if (!schedulingQuery.deptId) { |
| | | proxy.$modal.msgError("请选择部门"); |
| | | return; |
| | | } |
| | | let time = schedulingQuery.week.getTime(); |
| | | |
| | | // 格式化日期为 YYYY-MM-DD 格式 |
| | |
| | | proxy.$modal.msgSuccess("操作成功"); |
| | | schedulingVisible.value = false; |
| | | schedulingQuery.week = ""; |
| | | schedulingQuery.deptId = ""; |
| | | schedulingQuery.userId = null; |
| | | schedulingQuery.shift = ""; |
| | | personList.value = []; |
| | | refresh(); |
| | | }) |
| | | .catch(err => { |
| | |
| | | } |
| | | proxy.$download.saveAs(blob, fileName + ".xlsx"); |
| | | }) |
| | | .catch(err => { |
| | | }) |
| | | .catch(err => {}) |
| | | .finally(() => { |
| | | downLoading.value = false; |
| | | }); |
| | |
| | | // 查询规则列表 |
| | | const fetchData = () => { |
| | | getAttendanceRules({ current: -1, size: -1 }).then(res => { |
| | | classType.value = res.data.records; |
| | | const records = Array.isArray(res?.data?.records) ? res.data.records : []; |
| | | const appendList = [ |
| | | { id: 998, shift: "休息" }, |
| | | { id: 999, shift: "请假" }, |
| | | ]; |
| | | const exists = new Set(records.map(r => String(r?.id))); |
| | | appendList.forEach(item => { |
| | | if (!exists.has(String(item.id))) { |
| | | records.push(item); |
| | | } |
| | | }); |
| | | classType.value = records; |
| | | }); |
| | | }; |
| | | // 获取用户 |
| | |
| | | staffState: 1, |
| | | }).then(res => { |
| | | let arr = res.data.records; |
| | | personList.value = arr; |
| | | personListAll.value = arr; |
| | | updatePersonListByDept(); |
| | | }); |
| | | }; |
| | | |
| | | const findDeptNodeById = (deptId, deptList = deptOptions.value) => { |
| | | const list = Array.isArray(deptList) ? deptList : []; |
| | | for (const node of list) { |
| | | if (String(node.id) === String(deptId)) return node; |
| | | if (node.children && node.children.length) { |
| | | const found = findDeptNodeById(deptId, node.children); |
| | | if (found) return found; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const collectDeptIds = node => { |
| | | const ids = []; |
| | | if (!node) return ids; |
| | | ids.push(String(node.id)); |
| | | if (node.children && node.children.length) { |
| | | node.children.forEach(child => { |
| | | ids.push(...collectDeptIds(child)); |
| | | }); |
| | | } |
| | | return ids; |
| | | }; |
| | | |
| | | const updatePersonListByDept = () => { |
| | | if (!schedulingQuery.deptId) { |
| | | personList.value = []; |
| | | return; |
| | | } |
| | | const node = findDeptNodeById(schedulingQuery.deptId); |
| | | const deptIds = new Set(collectDeptIds(node)); |
| | | personList.value = (personListAll.value || []).filter(item => { |
| | | const itemDeptId = item.deptId ?? item.sysDeptId ?? item.dept_id; |
| | | return deptIds.has(String(itemDeptId)); |
| | | }); |
| | | }; |
| | | |
| | | const setDefaultShiftByDept = () => { |
| | | if (!schedulingQuery.deptId) { |
| | | schedulingQuery.shift = ""; |
| | | return; |
| | | } |
| | | const first = schedulingClassType.value?.[0]; |
| | | schedulingQuery.shift = first ? first.id : ""; |
| | | }; |
| | | |
| | | const onSchedulingDeptChange = () => { |
| | | schedulingQuery.userId = null; |
| | | updatePersonListByDept(); |
| | | setDefaultShiftByDept(); |
| | | }; |
| | | |
| | | // 根据字典获取日期 |
| | |
| | | } |
| | | monthList.value.reverse(); |
| | | }); |
| | | |
| | | watch( |
| | | () => classType.value, |
| | | () => { |
| | | if (schedulingVisible.value && schedulingQuery.deptId) { |
| | | setDefaultShiftByDept(); |
| | | } |
| | | } |
| | | ); |
| | | |
| | | watch( |
| | | () => schedulingVisible.value, |
| | | val => { |
| | | if (!val) return; |
| | | schedulingQuery.week = ""; |
| | | schedulingQuery.deptId = ""; |
| | | schedulingQuery.userId = null; |
| | | schedulingQuery.shift = ""; |
| | | personList.value = []; |
| | | } |
| | | ); |
| | | </script> |
| | | |
| | | <style scoped> |
| | |
| | | .user-stats { |
| | | /* display: flex; */ |
| | | /* flex-wrap: wrap; |
| | | gap: 10px; */ |
| | | gap: 10px; */ |
| | | margin-bottom: 4px; |
| | | } |
| | | |