滚动时机修改
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
// Vue 核心响应式 API
|
// Vue 核心响应式 API
|
||||||
import { ref, watch, onMounted, onBeforeUnmount, reactive } from "vue";
|
import { ref, watch, onMounted, onBeforeUnmount, reactive, nextTick } from "vue";
|
||||||
// FullCalendar Vue 3 组件
|
// FullCalendar Vue 3 组件
|
||||||
import FullCalendar from "@fullcalendar/vue3";
|
import FullCalendar from "@fullcalendar/vue3";
|
||||||
// FullCalendar 插件:月视图
|
// FullCalendar 插件:月视图
|
||||||
@@ -268,14 +268,7 @@ const calendarOptions = ref({
|
|||||||
const titleEl = info.el.querySelector('.fc-event-title')
|
const titleEl = info.el.querySelector('.fc-event-title')
|
||||||
if (titleEl) {
|
if (titleEl) {
|
||||||
// 等 DOM 完全渲染后再检测宽度
|
// 等 DOM 完全渲染后再检测宽度
|
||||||
requestAnimationFrame(() => {
|
requestAnimationFrame(() => applyScrollToTitle(titleEl))
|
||||||
const overflow = titleEl.scrollWidth - titleEl.clientWidth
|
|
||||||
if (overflow > 0) {
|
|
||||||
// 将溢出量存入 CSS 变量,让动画能精确滚到末尾
|
|
||||||
titleEl.style.setProperty('--scroll-distance', `-${overflow}px`)
|
|
||||||
titleEl.setAttribute('data-truncated', 'true')
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -403,6 +396,7 @@ function updateEditData(id, title, start, end, color) {
|
|||||||
case 0:
|
case 0:
|
||||||
closeEventModal();
|
closeEventModal();
|
||||||
getEvents();//从新从后端获取最新数据
|
getEvents();//从新从后端获取最新数据
|
||||||
|
recalcScrollTitles();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
toast.danger(t("message.server_error"));
|
toast.danger(t("message.server_error"));
|
||||||
@@ -495,6 +489,7 @@ const saveEvent = () => {
|
|||||||
// 关闭模态框
|
// 关闭模态框
|
||||||
closeEventModal();
|
closeEventModal();
|
||||||
getEvents();
|
getEvents();
|
||||||
|
recalcScrollTitles();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
toast.danger(t("message.server_error"));
|
toast.danger(t("message.server_error"));
|
||||||
@@ -572,6 +567,7 @@ function delEvent() {
|
|||||||
case 0:
|
case 0:
|
||||||
closeEventModal();
|
closeEventModal();
|
||||||
getEvents();//从新从后端获取最新数据
|
getEvents();//从新从后端获取最新数据
|
||||||
|
recalcScrollTitles();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
toast.danger(t("message.server_error"));
|
toast.danger(t("message.server_error"));
|
||||||
@@ -613,6 +609,42 @@ function pastEvent() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ─── 滚动标题工具函数 ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对单个 .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, () => {
|
watch(locale, () => {
|
||||||
// 更新日历语言
|
// 更新日历语言
|
||||||
@@ -649,35 +681,39 @@ watch(locale, () => {
|
|||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
let timer = null;
|
let timer = null
|
||||||
|
let resizeObserver = null
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
getEvents();
|
getEvents();
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
getEvents();
|
getEvents();
|
||||||
}, 2000);
|
}, 2000);
|
||||||
|
|
||||||
// const handleKeydown = (event) => {
|
// 监听日历容器宽度变化,重新计算标题滚动距离
|
||||||
// // Ctrl+C 事件
|
// 用 setTimeout 防抖,避免 resize 过程中频繁触发
|
||||||
// if (event.ctrlKey && event.key === "c") {
|
let resizeTimer = null
|
||||||
// event.preventDefault(); // 可选:阻止默认复制行为
|
resizeObserver = new ResizeObserver(() => {
|
||||||
// console.log("Ctrl+C 被按下");
|
clearTimeout(resizeTimer)
|
||||||
// // 你的业务逻辑
|
resizeTimer = setTimeout(() => {
|
||||||
// }
|
recalcScrollTitles()
|
||||||
// // Ctrl+V 事件
|
}, 150)
|
||||||
// if (event.ctrlKey && event.key === "v") {
|
})
|
||||||
// event.preventDefault(); // 可选:阻止默认粘贴行为
|
// calendarRef.$el 就是 <FullCalendar> 渲染出的根 DOM 节点
|
||||||
// console.log("Ctrl+V 被按下");
|
if (calendarRef.value?.$el) {
|
||||||
// // 你的业务逻辑
|
resizeObserver.observe(calendarRef.value.$el)
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// document.addEventListener("keydown", handleKeydown);
|
|
||||||
// // 清理事件监听器
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
//document.removeEventListener("keydown", handleKeydown);
|
|
||||||
if (timer) {
|
|
||||||
clearInterval(timer); // 清除定时器
|
|
||||||
timer = null; // 置空,好习惯
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (timer) {
|
||||||
|
clearInterval(timer)
|
||||||
|
timer = null
|
||||||
|
}
|
||||||
|
if (resizeObserver) {
|
||||||
|
resizeObserver.disconnect()
|
||||||
|
resizeObserver = null
|
||||||
|
}
|
||||||
|
clearTimeout(resizeTimer)
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user