<script setup>
// Vue 核心响应式 API
import {
  ref,
  watch,
  onMounted,
  onBeforeUnmount,
  reactive,
  nextTick,
} from "vue";
// FullCalendar Vue 3 组件
import FullCalendar from "@fullcalendar/vue3";
// FullCalendar 插件：月视图
import dayGridPlugin from "@fullcalendar/daygrid";
// FullCalendar 插件：周视图（时间网格）
import timeGridPlugin from "@fullcalendar/timegrid";
// FullCalendar 插件：交互功能（拖拽、点击等）
import interactionPlugin from "@fullcalendar/interaction";
// FullCalendar 插件：列表视图
import listPlugin from "@fullcalendar/list";
// 国际化 hook
import { useI18n } from "vue-i18n";
// 页面标题 composable
import { usePageTitle } from "@/composables/usePageTitle";

import DatatimePickerForFullCalendar from "@/components/datatimePickerForFullCalendar.vue";

import { useToastStore } from "@/stores/toast";

// 用户状态管理
import { useUserStore } from "@/stores/user";

import { useRouter } from "vue-router";

import { scheduleApi } from "@/api/schedule";

import { useDateUtils } from "@/composables/useDateUtils";

import { useUsersStore } from "@/stores/users";

const usersStore = useUsersStore();

const DateUtils = useDateUtils();

const router = useRouter();

// 获取用户 store 实例，用于访问和更新用户信息
const userStore = useUserStore();

const toast = useToastStore();

// 设置页面标题
usePageTitle("appname.schedule");

// 获取国际化翻译函数和当前语言
const { t, locale } = useI18n();

// FullCalendar 组件的引用，用于调用日历 API
const calendarRef = ref(null);
// 当前视图的年份
const calendarNowShow = ref();

// 模态框相关状态
const showModal = ref(false);
const eventData = ref({
  id: 0,
  title: "",
  startDate: "",
  endDate: "",
  color: "#066FD1", // 默认蓝色工作事件
  isEditing: false, //是否处于编辑模式，false就是添加模式
  isEditable: false, //是否有权限编辑，无权限就让按钮灰掉
  userID: 0,
});

// 颜色选项
const colorOptions = ref([
  { value: "#066FD1", label: t("schedule.work"), name: t("schedule.work") },
  { value: "#09D119", label: t("schedule.duty"), name: t("schedule.duty") },
  { value: "#FF00FF", label: t("schedule.exam"), name: t("schedule.exam") },
  {
    value: "#FFFF00",
    label: t("schedule.standby"),
    name: t("schedule.standby"),
  },
  {
    value: "#D16C13",
    label: t("schedule.personal_holiday"),
    name: t("schedule.personal_holiday"),
  },
  {
    value: "#D10D21",
    label: t("schedule.public_holiday"),
    name: t("schedule.public_holiday"),
  },
]);

const pageData = reactive({
  //本页全局变量
  seleEventID: 0, //上次点击的eventid
  lastClickTime: 0, // 用于跟踪上次点击时间的响应式变量
  lastClickTimeStr: "",
  lastEventClickTime: 0, // 用于跟踪上次点击event时间的响应式变量
  lastEventClickID: 0,

  submitChecked: false,

  isCopy: false,
  copyTitle: "",
  copyColor: "",

  eventBindUserID: [],

  lastEventsSnapshot: null, // 上一次 getEvents 获取的原始数据快照，用于检测多浏览器同步变化
});

//通过eventid获取用户id
function getUserIdFromEventID(eventID) {
  const target = pageData.eventBindUserID.find(
    (item) => item.eventID === eventID,
  );
  if (target) {
    return target.userID;
  }
  return 0;
}

//通过用户id获取用户名
function getUsernameFromUserID(userID) {
  if (userID == 0) {
    return "";
  }

  return usersStore.getUsernameFromUserID(userID);
}

function unseleEvent(eventID) {
  //寻找哪个event被单击了并修改边框
  const target = calendarOptions.value.events.find(
    (item) => item.id === eventID,
  );
  if (target) {
    target.borderColor = "#F7F7F7";
  }
}

function unseleEventAll() {
  unseleEvent(pageData.seleEventID);
  pageData.seleEventID = 0;
}

function seleEvent(eventID) {
  //单击了event
  //取消上次选中
  if (pageData.seleEventID != 0) {
    unseleEvent(pageData.seleEventID);
  }
  //寻找哪个event被单击了并修改边框
  const target = calendarOptions.value.events.find(
    (item) => item.id === eventID,
  );
  if (target) {
    target.borderColor = "#000000";
  }
  pageData.seleEventID = eventID;
}

// 日历配置选项
const calendarOptions = ref({
  // 日历高度：占满可用空间
  height: "100%",
  // 内容高度自适应
  contentHeight: "auto",
  // 使用当前应用语言
  locale: locale.value,
  // 注册使用的插件
  plugins: [dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin],
  // 显示当前时间指示线
  nowIndicator: true,
  // 显示周末
  weekends: true,
  // 初始视图：月视图
  initialView: "dayGridMonth",
  // 允许选择日期/时间段
  selectable: true,
  // 允许拖拽调整事件
  editable: true,
  // 日期格中事件过多时显示"+N more"
  dayMaxEvents: true,

  // 日期标题可点击跳转 //不跳转
  //navLinks: true,

  // 一周的第一天：1 = 周一
  firstDay: 1,
  // 自动展开行高
  expandRows: true,
  // 固定头部日期
  stickyHeaderDates: true,

  // 日期格子挂载时的样式处理
  dayCellDidMount(info) {
    // 周六周日显示灰色背景
    if (info.date.getDay() === 0 || info.date.getDay() === 6) {
      info.el.style.backgroundColor = "#f5f5f5";
    }
    // 添加边框样式
    info.el.style.border = "1px solid #e5e7eb";
  },

  // 顶部工具栏配置
  headerToolbar: {
    // 左侧：年份和月份导航按钮
    left: "prevYear,prev,today,next,nextYear",
    // 中间：标题（显示当前月份/年份）
    center: "title",
    // 右侧：留空（可通过 customButtons 扩展）
    right: "",
  },

  // 自定义按钮：扩展工具栏功能
  customButtons: {
    // 上一年按钮
    prevYear: {
      text: t("schedule.previous_year"),
      click() {
        calendarRef.value.getApi().prevYear();
        getEvents();
      },
    },
    // 下一年按钮
    nextYear: {
      text: t("schedule.next_year"),
      click() {
        calendarRef.value.getApi().nextYear();
        getEvents();
      },
    },
    // 上一个月按钮
    prev: {
      text: t("schedule.previous_month"),
      click() {
        calendarRef.value.getApi().prev();
        getEvents();
      },
    },
    // 下一个月按钮
    next: {
      text: t("schedule.next_month"),
      click() {
        calendarRef.value.getApi().next();
        getEvents();
      },
    },
    // 今天按钮：跳转到今天
    today: {
      text: t("schedule.today"),
      click() {
        calendarRef.value.getApi().today();
        getEvents();
      },
    },
    // 周视图按钮：切换到周视图
    week: {
      text: t("schedule.week"),
      click() {
        calendarRef.value.getApi().changeView("timeGridWeek");
      },
    },
  },

  // 日历事件列表（目前为空，后续可接入数据源）
  events: [],

  eventDidMount(info) {
    const titleEl = info.el.querySelector(".fc-event-title");
    if (titleEl) {
      // 等 DOM 完全渲染后再检测宽度
      requestAnimationFrame(() => applyScrollToTitle(titleEl));
    }
  },

  // 👇 加这个！日历渲染完成 / 切换年月都会触发
  datesSet(info) {
    calendarNowShow.value = info;
    //console.log(info);
  },

  // 日期点击事件处理函数
  dateClick(info) {
    const nowTime = new Date().getTime();
    const timeDifference = nowTime - pageData.lastClickTime;

    unseleEventAll(); //点击了日期就取消event的选择

    //判断和上次点击的是不是同一天
    if (info.dateStr === pageData.lastClickTimeStr) {
      // 判断是否为双击（400ms 内连续点击）
      if (timeDifference < 400 && timeDifference > 0) {
        // 双击功能：快速添加事件

        //先判断是否登录
        if (userStore.isLoggedIn) {
          openEventModal(info.dateStr, info.dateStr);
        } else {
          toast.warning(t("message.login_to_your_account"));
          router.replace("/login?redirect=/schedule");
        }
      }
    }
    pageData.lastClickTimeStr = info.dateStr;

    // 更新上次点击时间
    pageData.lastClickTime = nowTime;
  },

  //选择日期
  select(info) {
    if (info.end - info.start > 86400000) {
      //选择了多日
      //console.log("选择了多日:", info);
      //先判断是否登录
      if (userStore.isLoggedIn) {
        openEventModal(info.startStr, info.endStr);
      } else {
        toast.warning(t("message.login_to_your_account"));
        //router.replace("/login?redirect=/schedule");
      }
    } else {
      //选择单日 无功能
      //console.log("选择单日:", info);
    }
  },

  //事件event点击处理函数
  eventClick(info) {
    const nowTime = new Date().getTime();
    const timeDifference = nowTime - pageData.lastEventClickTime;

    //console.log(info)

    //判断event的title是否过长，如果是被截断的 就toast.info弹窗显示
    // const titleEl = info.el.querySelector('.fc-event-title');
    // if (titleEl && titleEl.scrollWidth > titleEl.clientWidth) {
    //   //title过长 得换一种方式显示
    //   //toast.info(info.event.title);
    // }

    // 单击功能：
    var eventid = parseInt(info.event.id);
    seleEvent(eventid);

    //判断和上次点击的是不是同一个event
    if (eventid === pageData.lastEventClickID) {
      // 判断是否为双击（400ms 内连续点击）
      if (timeDifference < 400 && timeDifference > 0) {
        //console.log("双击事件:", info);
        openEventModal(
          info.event.startStr,
          info.event.end ? info.event.endStr : info.event.startStr,
          parseInt(info.event.id),
          info.event.title,
          info.event.backgroundColor,
          true,
          info.event.durationEditable,
        );
        // 双击功能：
        unseleEventAll();
      }
    }
    pageData.lastEventClickID = eventid;

    // 更新上次点击时间
    pageData.lastEventClickTime = nowTime;
  },

  //event拖动处理
  eventDrop(info) {
    updateEditData(
      parseInt(info.event.id),
      info.event.title,
      info.event.startStr,
      info.event.end === null
        ? info.event.startStr
        : DateUtils.toRealEnd(info.event.end),
      info.event.backgroundColor,
    );
  },
});

function editSaveEvent() {
  //console.log(eventData)
  updateEditData(
    eventData.value.id,
    eventData.value.title,
    eventData.value.startDate,
    eventData.value.startDate === eventData.value.endDate
      ? eventData.value.startDate
      : DateUtils.toRealEnd(eventData.value.endDate),
    eventData.value.color,
  );
}

function updateEditData(id, title, start, end, color) {
  //需要发送到后端修改event
  //console.log(info.event)
  scheduleApi
    .editEvent({
      id: id,
      title: title,
      start: start,
      end: end,
      color: color,
    })
    .then((r) => {
      //console.log(r);
      if (r.errCode == 0) {
        //前端提交是否错误
        switch (
          r.raw.err_code //后端返回是否错误
        ) {
          case 0:
            closeEventModal();
            getEvents(); //从新从后端获取最新数据
            setTimeout(recalcScrollTitles, 150);
            break;
          default:
            toast.danger(t("message.server_error"));
            break;
        }
      }
    });
}

// 打开模态框
const openEventModal = (
  dateStr,
  dataEnd,
  id = 0,
  title = "",
  color = "#066FD1",
  isEditing = false,
  isEditable = true,
) => {
  eventData.value = {
    id: id,
    title: title,
    startDate: dateStr,
    endDate: dataEnd,
    color: color,
    isEditing: isEditing,
    isEditable: isEditable,
  };

  //console.log(eventData.value);

  showModal.value = true;
};

// 关闭模态框
const closeEventModal = () => {
  showModal.value = false;
};

// 保存日程事件
const saveEvent = () => {
  if (!eventData.value.title.trim()) {
    //alert("请输入日程内容");
    pageData.submitChecked = true;
    toast.warning(t("schedule.event_title_required"));
    return;
  }
  pageData.submitChecked = false;

  if (!eventData.value.startDate || !eventData.value.endDate) {
    //alert("请选择日期");
    toast.warning(t("schedule.date_required"));
    return;
  }

  const selectedColor = colorOptions.value.find(
    (color) => color.value === eventData.value.color,
  );
  const colorName = selectedColor ? selectedColor.name : eventData.value.color;

  const newEvent = {
    title: eventData.value.title.trim(),
    start: eventData.value.startDate,
    end: eventData.value.endDate,
    allDay: true,
    backgroundColor: eventData.value.color,
    borderColor: eventData.value.color,
    textColor: "#ffffff",
    extendedProps: {
      type: colorName,
      description: eventData.value.title.trim(),
    },
  };

  // 添加到日历事件列表
  //提交到后端

  //console.log(newEvent)

  scheduleApi
    .addEvent({
      title: newEvent.title,
      start: newEvent.start,
      end:
        newEvent.end === newEvent.start
          ? newEvent.end
          : DateUtils.toRealEnd(newEvent.end),
      color: newEvent.backgroundColor,
    })
    .then((r) => {
      //console.log(r);
      if (r.errCode == 0) {
        //前端提交是否错误
        switch (
          r.raw.err_code //后端返回是否错误
        ) {
          case 0:
            //calendarOptions.value.events.push(newEvent);
            toast.success(t("schedule.event_added_successfully"));
            // 关闭模态框
            closeEventModal();
            getEvents();
            setTimeout(recalcScrollTitles, 150);
            break;
          default:
            toast.danger(t("message.server_error"));
            break;
        }
      } else {
        toast.danger(t("message.server_error"));
      }
    });
};

//从后端获取events
const getEvents = () => {
  //console.log(calendarNowShow.value)
  scheduleApi
    .getEvents({
      start: DateUtils.dateToStr(calendarNowShow.value.start),
      end: DateUtils.toRealEnd(calendarNowShow.value.end),
    })
    .then((r) => {
      //console.log(r);
      if (r.errCode == 0) {
        //前端提交是否错误
        switch (
          r.raw.err_code //后端返回是否错误
        ) {
          case 0:
            calendarOptions.value.events = [];
            var events = r.raw.return.list;
            //console.log(events);
            pageData.eventBindUserID = [];
            events?.forEach((item) => {
              var bind = {
                eventID: item.ID,
                userID: item.UserID,
              };
              pageData.eventBindUserID.push(bind);

              calendarOptions.value.events.push({
                id: item.ID, // 后端 ID
                title: item.Title, // 标题
                start: item.StartDate, // 开始日期
                end:
                  item.StartDate === item.EndDate
                    ? item.EndDate
                    : DateUtils.toCalendarEnd(item.EndDate), // 结束日期
                backgroundColor: item.BgColor, // 背景色
                borderColor:
                  item.ID === pageData.seleEventID ? "#000000" : "#F7F7F7",
                allDay: true, // 全天事件
                editable: item.edit,
              });
            });

            // 检测数据是否变化（多浏览器同步场景），变了就重新计算滚动
            const newSnapshot = JSON.stringify(events);
            if (newSnapshot !== pageData.lastEventsSnapshot) {
              pageData.lastEventsSnapshot = newSnapshot;
              setTimeout(recalcScrollTitles, 150);
            }

            break;
          default:
            toast.danger(t("message.server_error"));
            break;
        }
      }
    });
};

//删除event
function delEvent() {
  scheduleApi
    .deleEvent({
      id: eventData.value.id,
    })
    .then((r) => {
      //console.log(r);
      if (r.errCode == 0) {
        //前端提交是否错误
        switch (
          r.raw.err_code //后端返回是否错误
        ) {
          case 0:
            closeEventModal();
            getEvents(); //从新从后端获取最新数据
            setTimeout(recalcScrollTitles, 150);
            break;
          default:
            toast.danger(t("message.server_error"));
            break;
        }
      } else {
        toast.danger(t("message.server_error"));
      }
    });
}

// 颜色选择处理
const selectColor = (colorValue) => {
  if (eventData.value.isEditable) {
    eventData.value.color = colorValue;
  }
};

function copyEvent() {
  pageData.copyTitle = eventData.value.title;
  pageData.copyColor = eventData.value.color;
  pageData.isCopy = true;
  toast.info(t("schedule.copied"));
}

function pastEvent() {
  if (pageData.isCopy) {
    if (eventData.value.isEditable) {
      eventData.value.color = pageData.copyColor;
      eventData.value.title = pageData.copyTitle;
      toast.info(t("schedule.pasted"));
    } else {
      toast.warning(t("schedule.not_your_schedule"));
    }
  }
}

// ─── 滚动标题工具函数 ───────────────────────────────────────────────────────

/**
 * 对单个 .fc-event-title 元素重新计算是否需要滚动。
 * 先清除旧状态，再测量，按需设置动画。
 */
function applyScrollToTitle(titleEl) {
  // 先重置，避免旧的 --scroll-distance 干扰测量
  titleEl.removeAttribute("data-truncated");
  titleEl.style.removeProperty("--scroll-distance");

  const overflow = titleEl.scrollWidth - titleEl.clientWidth;
  if (overflow > 0) {
    titleEl.style.setProperty("--scroll-distance", `-${overflow}px`);
    titleEl.setAttribute("data-truncated", "true");
  }
}

/**
 * 重新计算日历中所有 event 标题的滚动状态。
 * 适用于：屏幕宽度变化、数据刷新后。
 * 用 nextTick + rAF 双重等待，确保 DOM 和布局都已更新完毕。
 */
function recalcScrollTitles() {
  // nextTick 等 Vue 完成 DOM 更新，rAF 再等浏览器完成布局计算
  nextTick(() => {
    requestAnimationFrame(() => {
      const calendarEl = calendarRef.value?.$el;
      if (!calendarEl) return;
      calendarEl
        .querySelectorAll(".fc-event-title")
        .forEach(applyScrollToTitle);
    });
  });
}

// ─────────────────────────────────────────────────────────────────────────────

// 监听语言变化，更新日历的本地化和按钮文字
watch(locale, () => {
  // 更新日历语言
  calendarOptions.value.locale = locale.value;
  // 更新自定义按钮的文字
  calendarOptions.value.customButtons.prevYear.text = t(
    "schedule.previous_year",
  );
  calendarOptions.value.customButtons.nextYear.text = t("schedule.next_year");
  calendarOptions.value.customButtons.prev.text = t("schedule.previous_month");
  calendarOptions.value.customButtons.next.text = t("schedule.next_month");
  calendarOptions.value.customButtons.today.text = t("schedule.today");
  calendarOptions.value.customButtons.week.text = t("schedule.week");

  colorOptions.value = [
    { value: "#066FD1", label: t("schedule.work"), name: t("schedule.work") },
    { value: "#09D119", label: t("schedule.duty"), name: t("schedule.duty") },
    { value: "#FF00FF", label: t("schedule.exam"), name: t("schedule.exam") },
    {
      value: "#FFFF00",
      label: t("schedule.standby"),
      name: t("schedule.standby"),
    },
    {
      value: "#D16C13",
      label: t("schedule.personal_holiday"),
      name: t("schedule.personal_holiday"),
    },
    {
      value: "#D10D21",
      label: t("schedule.public_holiday"),
      name: t("schedule.public_holiday"),
    },
  ];
});

let timer = null;
let resizeObserver = null;

onMounted(() => {
//模块已停用，跳转到新模块
router.push('/calendars')
return

  getEvents();
  timer = setInterval(() => {
    getEvents();
  }, 2000);

  // 监听日历容器宽度变化，重新计算标题滚动距离
  // 用 setTimeout 防抖，避免 resize 过程中频繁触发
  let resizeTimer = null;
  resizeObserver = new ResizeObserver(() => {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(() => {
      recalcScrollTitles();
    }, 150);
  });
  // calendarRef.$el 就是 <FullCalendar> 渲染出的根 DOM 节点
  if (calendarRef.value?.$el) {
    resizeObserver.observe(calendarRef.value.$el);
  }

  onBeforeUnmount(() => {
    if (timer) {
      clearInterval(timer);
      timer = null;
    }
    if (resizeObserver) {
      resizeObserver.disconnect();
      resizeObserver = null;
    }
    clearTimeout(resizeTimer);
  });
});
</script>

<template>
  <!-- {{userStore.userCookie.Value}} -->
  <!-- 日历容器：占满视口高度减去顶部导航高度 -->
  <div class="flex w-full flex-col relative">
    <!-- 事件编辑模态框 -->
    <div
      v-if="showModal"
      class="fixed inset-0 z-50 flex items-center justify-center bg-gray-800/20"
    >
      <!-- 👇 最关键：给外层加最大高度 + 溢出隐藏 -->
      <div
        class="modal-content bg-white rounded-lg shadow-lg w-full max-w-2xl max-h-[95vh] flex flex-col"
      >
        <!-- 模态框头部 -->
        <div
          class="modal-header border-b p-4 flex justify-between items-center flex-shrink-0"
        >
          <h5 class="modal-title text-lg font-semibold">
            {{
              userStore.isLoggedIn
                ? eventData.isEditing
                  ? t("schedule.edit_event_title")
                  : t("schedule.add_event")
                : t("schedule.view_event_title")
            }}
          </h5>
          <h5
            class="modal-title text-lg font-semibold absolute left-1/2 -translate-x-1/2"
          >
            {{
              userStore.isLoggedIn
                ? eventData.isEditing
                  ? t("schedule.someone_schedule", {
                      name: getUsernameFromUserID(
                        getUserIdFromEventID(eventData.id),
                      ),
                    })
                  : ""
                : ""
            }}
          </h5>
          <button
            @click="closeEventModal"
            class="btn-close text-gray-500 hover:text-gray-700"
          >
            <svg
              xmlns="http://www.w3.org/2000/svg"
              width="24"
              height="24"
              viewBox="0 0 24 24"
              fill="none"
              stroke="currentColor"
              stroke-width="2"
              stroke-linecap="round"
              stroke-linejoin="round"
              class="icon icon-tabler icons-tabler-outline icon-tabler-x"
            >
              <path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
              <path d="M18 6l-12 12"></path>
              <path d="M6 6l12 12"></path>
            </svg>
          </button>
        </div>

        <!-- 👇 主体区域：允许内部滚动 -->
        <div class="modal-body p-4 flex-1 overflow-y-auto">
          <!-- 日期选择区域 -->
          <DatatimePickerForFullCalendar
            v-model:startDate="eventData.startDate"
            v-model:endDate="eventData.endDate"
            :color="eventData.color"
            :title="eventData.title"
            :isEditable="eventData.isEditable"
          />

          <!-- 内容输入区域 -->
          <div class="mb-4">
            <div class="uni-easyinput input relative">
              <div
                class="uni-easyinput__content is-input-border border border-gray-300 rounded-md bg-white relative"
                :class="{
                  'border-gray-300': eventData.title || !pageData.submitChecked,
                  'border-red-500': !eventData.title && pageData.submitChecked,
                }"
              >
                <input
                  v-model="eventData.title"
                  type="text"
                  maxlength="140"
                  class="uni-easyinput__content-input w-full px-3 py-2 outline-none"
                  :placeholder="t('schedule.event_title_placeholder')"
                  @keyup.enter="saveEvent"
                  :disabled="!eventData.isEditable"
                />
              </div>
            </div>
          </div>

          <!-- 颜色选择区域 -->
          <div class="mb-4">
            <div class="color_box grid grid-cols-3 gap-2">
              <div
                v-for="color in colorOptions"
                :key="color.value"
                class="color_box_item"
              >
                <label
                  class="uni-label-pointer form-colorinput flex items-center gap-2 cursor-pointer"
                  @click="selectColor(color.value)"
                >
                  <div class="uni-radio-wrapper">
                    <div
                      class="uni-radio-input flex items-center justify-center w-6 h-6 rounded-full transition-all"
                      :style="{
                        backgroundColor: color.value,
                        borderColor: color.value,
                      }"
                    >
                      <svg
                        v-if="eventData.color === color.value"
                        width="18"
                        height="18"
                        viewBox="0 0 32 32"
                      >
                        <path
                          d="M1.952 18.080q-0.32-0.352-0.416-0.88t0.128-0.976l0.16-0.352q0.224-0.416 0.64-0.528t0.8 0.176l6.496 4.704q0.384 0.288 0.912 0.272t0.88-0.336l17.312-14.272q0.352-0.288 0.848-0.256t0.848 0.352l-0.416-0.416q0.32 0.352 0.32 0.816t-0.32 0.816l-18.656 18.912q-0.32 0.352-0.8 0.352t-0.8-0.32l-7.936-8.064z"
                          fill="#ffffff"
                        ></path>
                      </svg>
                    </div>
                  </div>
                  <span class="text-gray-700">{{ color.label }}</span>
                </label>
              </div>
            </div>
          </div>
        </div>

        <!-- 👇 底部固定：不被滚动、不压缩 -->
        <!-- 如果没登录直接不显示 -->
        <div
          v-if="userStore.isLoggedIn"
          class="modal-footer border-t p-4 flex justify-between items-center flex-shrink-0"
        >
          <div class="flex gap-2">
            <button
              v-if="eventData.isEditing"
              @click="delEvent"
              class="btn px-4 py-2 text-white bg-red-500 hover:bg-red-600 rounded-md disabled:bg-gray-400 disabled:cursor-not-allowed"
              :disabled="!eventData.isEditable"
            >
              {{ t("schedule.delete") }}
            </button>
          </div>
          <div class="flex gap-2">
            <button
              class="btn px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md"
              @click="copyEvent"
            >
              {{ t("schedule.copy") }}
            </button>
            <button
              class="btn px-4 py-2 text-gray-700 hover:bg-gray-100 rounded-md disabled:cursor-not-allowed"
              :disabled="!pageData.isCopy || !eventData.isEditable"
              @click="pastEvent"
            >
              {{ t("schedule.paste") }}
            </button>
            <button
              v-if="!eventData.isEditing"
              @click="saveEvent"
              class="btn btn-primary px-4 py-2 bg-cyan-600 text-white hover:bg-cyan-700 rounded-md disabled:bg-gray-400 disabled:cursor-not-allowed"
              :disabled="!eventData.isEditable"
            >
              {{ t("schedule.add_event_button") }}
            </button>
            <button
              v-if="eventData.isEditing"
              @click="editSaveEvent"
              class="btn btn-primary px-4 py-2 bg-teal-600 text-white hover:bg-teal-700 rounded-md disabled:bg-gray-400 disabled:cursor-not-allowed"
              :disabled="!eventData.isEditable"
            >
              {{ t("schedule.edit_event_title") }}
            </button>
          </div>
        </div>
      </div>
    </div>

    <!-- 日历主体区域，带边框和阴影 -->
    <div
      class="flex-1 rounded-lg border border-gray-200 bg-white p-0.5 shadow dark:border-dk-muted dark:bg-dk-card"
    >
      <!-- 内层容器：隐藏溢出内容 -->
      <div class="h-full w-full overflow-hidden rounded-md">
        <!-- FullCalendar 日历组件 -->
        <!-- ref="calendarRef" 用于获取组件实例调用日历 API -->
        <!-- :options 绑定日历配置对象 -->
        <FullCalendar ref="calendarRef" :options="calendarOptions" />
      </div>
    </div>
  </div>
</template>

<style scoped>
/*
  月视图日程标题：超出容器宽度时自动来回滚动
  - 先停留 1.2s 显示开头
  - 向左滚动到末尾（匀速）
  - 停留 1.2s 显示末尾
  - 向右滚回开头（匀速）
  - 往复循环

  关键：FullCalendar 内置给 .fc-h-event .fc-event-title 设置了 overflow:hidden，
  这会把 translateX 动画裁掉。解决方式是：
  1. 覆盖 .fc-event-title 的 overflow 为 visible
  2. 把 overflow:hidden 提升到父容器 .fc-event-title-container 做裁剪视口
*/

/* 父容器作为裁剪视口 */
:deep(.fc-daygrid-event .fc-event-title-container) {
  overflow: hidden !important;
}

/* 默认状态：单行截断省略（未超长时）
   注意：必须覆盖 FullCalendar 内置的 overflow:hidden，否则动画被自身裁掉 */
:deep(.fc-daygrid-event .fc-event-title) {
  white-space: nowrap !important;
  overflow: visible !important; /* 覆盖 fc-h-event .fc-event-title { overflow: hidden } */
  text-overflow: ellipsis !important;
  display: block !important;
  will-change: transform;
}

/* 需要滚动的标题：移除 ellipsis，启用来回滚动动画 */
:deep(.fc-daygrid-event .fc-event-title[data-truncated="true"]) {
  text-overflow: clip !important;
  display: inline-block !important;
  animation: marquee-bounce 6s ease-in-out infinite !important;
}

@keyframes marquee-bounce {
  /*  0%  ~ 20%：停在开头，让用户看清前段内容  */
  0%,
  20% {
    transform: translateX(0);
  }
  /*  20% ~ 60%：匀速向左滚动到末尾  */
  60% {
    transform: translateX(var(--scroll-distance, 0px));
  }
  /*  60% ~ 80%：停在末尾，让用户看清后段内容  */
  80% {
    transform: translateX(var(--scroll-distance, 0px));
  }
  /*  80% ~ 100%：匀速向右滚回开头  */
  100% {
    transform: translateX(0);
  }
}
</style>
