100 lines
2.8 KiB
TypeScript
100 lines
2.8 KiB
TypeScript
import type { Dayjs } from 'dayjs';
|
||
|
||
import type { MesCalCalendarApi } from '#/api/mes/cal/calendar';
|
||
|
||
import { ref, watch } from 'vue';
|
||
|
||
import dayjs from 'dayjs';
|
||
|
||
import { getCalendarList } from '#/api/mes/cal/calendar';
|
||
import { getHolidayList } from '#/api/mes/cal/holiday';
|
||
import { HolidayType } from '#/views/mes/utils/constants';
|
||
|
||
/**
|
||
* 排班日历通用 composable
|
||
*
|
||
* 封装日历组件中通用的响应式状态、假期加载、排班查询、月份切换逻辑
|
||
*/
|
||
export function useCalendar() {
|
||
const loading = ref(false);
|
||
const currentDate = ref<Dayjs>(dayjs());
|
||
const calendarDayMap = ref<Map<string, MesCalCalendarApi.CalendarDay>>(
|
||
new Map(),
|
||
);
|
||
const holidaySet = ref(new Set<string>());
|
||
|
||
/** 计算当前月份的起止时间 */
|
||
function getMonthRange() {
|
||
const startDay = currentDate.value
|
||
.startOf('month')
|
||
.format('YYYY-MM-DD 00:00:00');
|
||
const endDay = currentDate.value
|
||
.endOf('month')
|
||
.format('YYYY-MM-DD 23:59:59');
|
||
return { endDay, startDay };
|
||
}
|
||
|
||
/**
|
||
* 获取节假日列表,按当前月份范围加载
|
||
*
|
||
* 失败(无权限 / 接口异常)时不抛出,仅清空当月假期标记,
|
||
* 避免阻断使用方的主数据初始化
|
||
*/
|
||
async function loadHolidays() {
|
||
const { endDay, startDay } = getMonthRange();
|
||
const days = new Set<string>();
|
||
try {
|
||
const list = await getHolidayList({ endDay, startDay });
|
||
for (const item of list || []) {
|
||
const day = item.day ? dayjs(item.day).format('YYYY-MM-DD') : '';
|
||
if (day && item.type === HolidayType.HOLIDAY) {
|
||
days.add(day);
|
||
}
|
||
}
|
||
} catch {
|
||
// 没有 mes:cal-holiday:query 权限或接口异常时,仅忽略假期标记
|
||
}
|
||
holidaySet.value = days;
|
||
}
|
||
|
||
/** 查询排班日历,params 由调用方提供 queryType 相关参数 */
|
||
async function fetchCalendar(params: Record<string, any>) {
|
||
loading.value = true;
|
||
try {
|
||
const { endDay, startDay } = getMonthRange();
|
||
const list = await getCalendarList({ ...params, endDay, startDay });
|
||
const map = new Map<string, MesCalCalendarApi.CalendarDay>();
|
||
for (const item of list || []) {
|
||
const day = item.day ? dayjs(item.day).format('YYYY-MM-DD') : '';
|
||
if (day) {
|
||
map.set(day, { ...item, day });
|
||
}
|
||
}
|
||
calendarDayMap.value = map;
|
||
} finally {
|
||
loading.value = false;
|
||
}
|
||
}
|
||
|
||
/** 监听月份切换,调用回调刷新数据 */
|
||
function watchMonth(callback: () => void) {
|
||
watch(
|
||
() => currentDate.value.format('YYYY-MM'),
|
||
() => {
|
||
void loadHolidays();
|
||
callback();
|
||
},
|
||
);
|
||
}
|
||
|
||
return {
|
||
calendarDayMap,
|
||
currentDate,
|
||
fetchCalendar,
|
||
holidaySet,
|
||
loadHolidays,
|
||
loading,
|
||
watchMonth,
|
||
};
|
||
}
|