feat(mes): 完善排班日历功能,新增假期过滤及班组排班记录查询逻辑

pull/871/MERGE
YunaiV 2026-02-19 21:25:17 +08:00
parent 93a76b19db
commit f4239e8a0e
5 changed files with 70 additions and 20 deletions

View File

@ -16,13 +16,18 @@
>
{{ lunarDisplay }}
</div>
<!-- 班次信息节假日不显示排班 -->
<!-- 班次列表节假日不显示排班 -->
<template v-if="!isHoliday">
<!-- TODO @AI最好有个地方说明下这个逻辑 -->
<!--
配色规则sort 对应轮班方式中的班次顺序
sort=1 白班 success绿色
sort=2 中班 三班倒用 warning橙色两班倒用 info灰色
sort=3 夜班 info灰色
-->
<div v-for="item in teamShifts" :key="item.sort" class="mt-2px">
<!-- sort=1 白班绿色 -->
<el-button v-if="item.sort === 1" type="success" size="small" class="!w-full !text-12px">
{{ item.teamName }}
{{ item.shiftName }} · {{ item.teamName }}
</el-button>
<!-- sort=2 中班三班倒时用橙色两班倒时用灰色 -->
<el-button
@ -31,11 +36,11 @@
size="small"
class="!w-full !text-12px"
>
{{ item.teamName }}
{{ item.shiftName }} · {{ item.teamName }}
</el-button>
<!-- sort=3 夜班灰色 -->
<el-button v-else-if="item.sort === 3" type="info" size="small" class="!w-full !text-12px">
{{ item.teamName }}
{{ item.shiftName }} · {{ item.teamName }}
</el-button>
</div>
</template>

View File

@ -0,0 +1,37 @@
<!-- 排班日历 - 配色图例说明 -->
<template>
<div class="flex items-center flex-wrap gap-x-16px gap-y-4px text-12px text-#606266 px-2px py-6px">
<span class="text-#909399 shrink-0">配色说明</span>
<span class="flex items-center gap-4px">
<span class="legend-dot bg-#95d475" ></span>
白班
</span>
<span class="flex items-center gap-4px">
<span class="legend-dot bg-#f0a020" ></span>
中班三班倒
</span>
<span class="flex items-center gap-4px">
<span class="legend-dot bg-#909399" ></span>
中班两班倒/ 夜班
</span>
<span class="flex items-center gap-4px">
<span class="legend-dot bg-#f56c6c opacity-60" ></span>
<span class="text-#f56c6c">红色日期</span>
= 周末
</span>
<span class="flex items-center gap-4px">
<el-tag size="small" effect="dark" type="success" class="!text-11px !h-18px !px-4px"></el-tag>
= 节假日不显示排班
</span>
</div>
</template>
<style scoped>
.legend-dot {
display: inline-block;
width: 10px;
height: 10px;
border-radius: 2px;
flex-shrink: 0;
}
</style>

View File

@ -2,17 +2,15 @@
<template>
<div class="flex">
<!-- 左侧班组列表选择 -->
<!-- TODO @AI默认选中首个 -->
<div
class="w-150px shrink-0 mr-12px border border-solid border-#dcdfe6 rounded-4px overflow-hidden"
>
<!-- TODO @AI可以把 @click 在封装下么更统一一些 -->
<div
v-for="team in teamList"
:key="team.id"
class="px-16px py-10px cursor-pointer text-14px text-#606266 border-b border-b-solid border-b-#ebeef5 last:border-b-0 hover:bg-#f5f7fa transition-colors"
:class="selectedTeamId === team.id ? 'bg-#ecf5ff text-#409eff font-500' : ''"
@click="selectedTeamId = team.id; onTeamSelected()"
@click="onSelectTeam(team.id)"
>
{{ team.name }}
</div>
@ -20,6 +18,7 @@
<!-- 右侧日历 -->
<div class="flex-1">
<CalendarLegend />
<el-calendar v-model="currentDate" v-loading="loading">
<template #date-cell="{ data }">
<CalendarDateCell
@ -40,6 +39,7 @@ import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
import { formatDate } from '@/utils/formatTime'
import { HolidayType } from '@/views/mes/utils/constants'
import CalendarDateCell from './CalendarDateCell.vue'
import CalendarLegend from './CalendarLegend.vue'
const loading = ref(false)
const currentDate = ref(new Date()) //
@ -48,9 +48,12 @@ const teamList = ref<CalTeamVO[]>([]) // 所有班组列表
const calendarDayMap = ref<Map<string, CalCalendarDayVO>>(new Map()) // key: yyyy-MM-dd
const holidaySet = ref(new Set<string>()) // key: yyyy-MM-dd
/** 获取班组列表 */
/** 获取班组列表,并默认选中第一个 */
const getTeamList = async () => {
teamList.value = await CalTeamApi.getTeamList()
if (teamList.value.length > 0) {
onSelectTeam(teamList.value[0].id)
}
}
/** 获取节假日列表,构建节假日日期集合 */
@ -98,8 +101,9 @@ const fetchCalendar = async () => {
}
}
/** 选择班组后刷新日历 */
const onTeamSelected = () => {
/** 点击左侧班组后切换并刷新日历 */
const onSelectTeam = (id: number) => {
selectedTeamId.value = id
fetchCalendar()
}

View File

@ -2,20 +2,15 @@
<template>
<div class="flex">
<!-- 左侧班组类型选择 -->
<!-- TODO @AI默认选中首个 -->
<div
class="w-150px shrink-0 mr-12px border border-solid border-#dcdfe6 rounded-4px overflow-hidden"
>
<!-- TODO @AI可以把 @click 在封装下么更统一一些 -->
<div
v-for="dict in getIntDictOptions(DICT_TYPE.MES_CAL_CALENDAR_TYPE)"
:key="dict.value"
class="px-16px py-10px cursor-pointer text-14px text-#606266 border-b border-b-solid border-b-#ebeef5 last:border-b-0 hover:bg-#f5f7fa transition-colors"
:class="selectedType === dict.value ? 'bg-#ecf5ff text-#409eff font-500' : ''"
@click="
selectedType = dict.value
onTypeSelected()
"
@click="onSelectType(dict.value)"
>
{{ dict.label }}
</div>
@ -23,6 +18,7 @@
<!-- 右侧日历 -->
<div class="flex-1">
<CalendarLegend />
<el-calendar v-model="currentDate" v-loading="loading">
<template #date-cell="{ data }">
<CalendarDateCell
@ -43,6 +39,7 @@ import { formatDate } from '@/utils/formatTime'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { HolidayType } from '@/views/mes/utils/constants'
import CalendarDateCell from './CalendarDateCell.vue'
import CalendarLegend from './CalendarLegend.vue'
const loading = ref(false)
const currentDate = ref(new Date()) //
@ -95,8 +92,9 @@ const fetchCalendar = async () => {
}
}
/** 选择分类后刷新日历 */
const onTypeSelected = () => {
/** 点击左侧分类后切换并刷新日历 */
const onSelectType = (value: number) => {
selectedType.value = value
fetchCalendar()
}
@ -107,8 +105,12 @@ watch(currentDate, () => {
}
})
/** 初始化 */
/** 初始化:加载节假日,并默认选中第一个分类 */
onMounted(() => {
getHolidayList()
const opts = getIntDictOptions(DICT_TYPE.MES_CAL_CALENDAR_TYPE)
if (opts.length > 0) {
onSelectType(opts[0].value as number)
}
})
</script>

View File

@ -27,6 +27,7 @@
</el-form>
<!-- 日历 -->
<CalendarLegend />
<el-calendar v-model="currentDate" v-loading="loading">
<template #date-cell="{ data }">
<CalendarDateCell
@ -46,6 +47,7 @@ import { getSimpleUserList, UserVO } from '@/api/system/user'
import { formatDate } from '@/utils/formatTime'
import { HolidayType } from '@/views/mes/utils/constants'
import CalendarDateCell from './CalendarDateCell.vue'
import CalendarLegend from './CalendarLegend.vue'
const loading = ref(false)
const currentDate = ref(new Date()) //