gaoluyang
昨天 b64a0deae5b5d33f9e20671a68936b27f0b9b00b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import type { Dayjs } from 'dayjs';
 
import type { MesCalCalendarApi } from '#/api/mes/cal/calendar';
 
import { ref, watch } from 'vue';
 
import { HolidayType } from '@vben/constants';
 
import dayjs from 'dayjs';
 
import { getCalendarList } from '#/api/mes/cal/calendar';
import { getHolidayList } from '#/api/mes/cal/holiday';
 
/**
 * 排班日历通用 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,
  };
}