admin-vue3/src/views/mes/cal/holiday/index.vue

148 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!-- MES 假期设置 - 日历视图 -->
<template>
<doc-alert title="【排班】班组设置、节假日设置" url="https://doc.iocoder.cn/mes/team/" />
<ContentWrap>
<el-calendar v-model="currentDate">
<template #date-cell="{ data }">
<div class="h-full p-4px" @click.stop="onClickDay(data)">
<div class="flex justify-between items-center">
<span class="text-16px font-500" :class="{ 'text-#f56c6c': isWeekend(data.day) }">
{{ data.day.split('-')[2] }}
</span>
<el-tag v-if="holidaySet.has(data.day)" size="small" effect="dark" type="success">
</el-tag>
<el-tag v-else size="small" effect="dark"> 班 </el-tag>
</div>
<div
class="text-12px text-#909399 mt-4px"
:class="{ 'text-#67c23a': hasFestival(data.day) }"
>
{{ getLunarDisplay(data.day) }}
</div>
</div>
</template>
</el-calendar>
<!-- 假期设置表单弹窗 -->
<HolidayForm ref="formRef" @success="getList" />
</ContentWrap>
</template>
<script setup lang="ts">
import { CalHolidayApi, CalHolidayVO } from '@/api/mes/cal/holiday'
import { formatDate } from '@/utils/formatTime'
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
import PluginLunar from 'dayjs-plugin-lunar'
import { SolarDay } from 'tyme4ts'
import HolidayForm from './HolidayForm.vue'
import { checkPermi } from '@/utils/permission'
import { HolidayType } from '@/views/mes/utils/constants'
dayjs.locale('zh-cn')
dayjs.extend(PluginLunar)
defineOptions({ name: 'MesCalHoliday' })
const message = useMessage()
const currentDate = ref(new Date())
const holidaySet = ref(new Set<string>()) // 节假日日期集合
const formRef = ref()
const lastFetchedMonth = ref('') // 用于避免同月重复请求
/** 获取假期列表(按当前日历可见范围过滤) */
const getList = async () => {
holidaySet.value.clear()
// 计算日历组件可见范围:当月 ± 1 月el-calendar 会显示上月末和下月初)
const current = dayjs(currentDate.value)
const startDay = current.subtract(1, 'month').startOf('month').format('YYYY-MM-DD 00:00:00')
const endDay = current.add(1, 'month').endOf('month').format('YYYY-MM-DD 23:59:59')
const list = await CalHolidayApi.getHolidayList({ startDay, endDay })
if (list) {
list.forEach((item: CalHolidayVO) => {
// 后端返回的 day 为时间戳long格式化为 yyyy-MM-dd
const day = item.day ? formatDate(item.day as any, 'YYYY-MM-DD') : ''
if (day && item.type === HolidayType.HOLIDAY) {
holidaySet.value.add(day)
}
})
}
lastFetchedMonth.value = current.format('YYYY-MM')
}
/** 监听月份切换,重新加载可见范围内的数据 */
watch(currentDate, (newDate) => {
const newMonth = dayjs(newDate).format('YYYY-MM')
if (newMonth !== lastFetchedMonth.value) {
getList()
}
})
/** 点击日期 */
const onClickDay = (data: { type: string; day: string }) => {
// 非当前月日期,不处理(避免切换月份)
if (data.type !== 'current-month') {
return
}
if (!checkPermi(['mes:cal-holiday:create'])) {
message.warning('没有假期设置权限')
return
}
formRef.value.open(data.day)
}
/** 判断是否周末 */
const isWeekend = (day: string): boolean => {
const date = new Date(day)
const weekDay = date.getDay()
return weekDay === 0 || weekDay === 6
}
/** 获取农历显示信息 */
const getLunarInfo = (day: string) => {
const parts = day.split('-')
const year = parseInt(parts[0])
const month = parseInt(parts[1])
const date = parseInt(parts[2])
try {
const solarDay = SolarDay.fromYmd(year, month, date)
const lunarDay = solarDay.getLunarDay()
const solarFestival = solarDay.getFestival() // 公历节日
const lunarFestival = lunarDay.getFestival() // 农历节日
// 节气dayIndex === 0 表示当天恰好是节气日
const termDay = solarDay.getTermDay()
const termName = termDay.getDayIndex() === 0 ? termDay.getSolarTerm().getName() : null
// 农历月日
const lunarMonthName = lunarDay.getLunarMonth().getName() // 正月、二月...
const lunarDayName = lunarDay.getName() // 初一、初二...
return {
solarFestival: solarFestival ? solarFestival.getName() : null,
lunarFestival: lunarFestival ? lunarFestival.getName() : null,
termName,
lunarText: lunarMonthName + lunarDayName
}
} catch {
return { solarFestival: null, lunarFestival: null, termName: null, lunarText: '' }
}
}
/** 获取农历显示文本 */
const getLunarDisplay = (day: string): string => {
const info = getLunarInfo(day)
// 优先显示节日、节气,其次显示农历日
return info.solarFestival || info.lunarFestival || info.termName || info.lunarText
}
/** 判断是否有节日 */
const hasFestival = (day: string): boolean => {
const info = getLunarInfo(day)
return !!(info.solarFestival || info.lunarFestival || info.termName)
}
/** 初始化 */
onMounted(() => {
getList()
})
</script>