这个甘特图之前插件里,没有找到能固定label标签在屏幕上的办法,用css各种办法都没有实现,所以我我直接手写定位,用js监听滚动条滚动的距离,然后同步移动甘特图label标签,造成一种定位的错觉,以下是代码:
我用的是介绍 | Pure Admin 保姆级文档(已更新至最新版v6.0.0)这个前端框架,感觉功能还是非常完善的,作者全职做开源,希望大家也多多支持。
这个是全部甘特图的示例代码
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from "vue";
// https://zunnzunn.github.io/vue-ganttastic/introduction.html
import { GGanttChart, GGanttRow } from "@infectoone/vue-ganttastic";
// 添加滚动位置状态
const scrollLeft = ref(0);
// 添加容器引用
const containerRef = ref(null);
// 现有数据保持不变
const context = ref([
[
{
week: "星期一",
beginDate: "06:00",
endDate: "22:00",
label_column_title: "123",
ganttBarConfig: {
id: "0",
hasHandles: true,
label: "需求收集和分析 负责人:小张",
style: {
background: "#e96560"
}
}
}
],
[
{
week: "星期二",
beginDate: "09:00",
endDate: "18:00",
ganttBarConfig: {
id: "1",
hasHandles: true,
label: "系统设计 负责人:小强",
style: {
background: "#5ccfa3"
}
}
}
],
[
{
week: "星期三",
beginDate: "07:00",
endDate: "20:00",
ganttBarConfig: {
id: "2",
hasHandles: true,
label: "编码实现 负责人:老李",
style: {
background: "#77d6fa"
}
}
}
],
[
{
week: "星期四",
beginDate: "06:00",
endDate: "21:00",
ganttBarConfig: {
id: "3",
hasHandles: true,
label: "编码实现 负责人:小明",
style: {
color: "#fff",
background: "#1b2a47"
}
}
}
],
[
{
week: "星期五",
beginDate: "05:00",
endDate: "19:00",
ganttBarConfig: {
id: "4",
hasHandles: true,
label: "内部测试 负责人:小雪",
style: {
background: "#5ccfa3"
}
}
}
],
[
{
week: "星期六",
beginDate: "10:00",
endDate: "22:00",
ganttBarConfig: {
id: "5",
hasHandles: true,
label: "系统优化和文档整理 负责人:小欣",
style: {
background: "#f8bc45"
}
}
}
],
[
{
week: "星期天",
beginDate: "04:00",
endDate: "23:59",
ganttBarConfig: {
id: "6",
immobile: false,
hasHandles: false,
label: "部署和上线 负责人:老王",
style: {
background: "#f3953d"
}
}
}
],
[
{
week: "星期天",
beginDate: "04:00",
endDate: "23:59",
ganttBarConfig: {
id: "6",
immobile: false,
hasHandles: false,
label: "部署和上线 负责人:老王",
style: {
background: "#f3953d"
}
}
}
]
]);
// 滚动事件处理函数
function handleScroll(e) {
scrollLeft.value = e.target.scrollLeft;
console.log("滚动事件触发", scrollLeft.value);
const labels = document.querySelectorAll(
".g-gantt-row-label, .g-gantt-row-label-container"
);
labels.forEach(label => {
label.style.position = "absolute";
label.style.left = scrollLeft.value + "px";
});
}
// 添加和移除滚动事件监听
onMounted(() => {
// 延迟添加事件监听,确保DOM已完全渲染
setTimeout(() => {
if (containerRef.value) {
containerRef.value.addEventListener("scroll", handleScroll);
console.log("滚动监听已添加", containerRef.value);
}
}, 500);
});
onUnmounted(() => {
if (containerRef.value) {
containerRef.value.removeEventListener("scroll", handleScroll);
console.log("滚动监听已移除");
}
});
function getWeekRange() {
const today = new Date();
const dayOfWeek = today.getDay();
const startDate = new Date(today);
startDate.setDate(today.getDate() - dayOfWeek + 1);
const endDate = new Date(startDate);
endDate.setDate(startDate.getDate() + 6);
const formatDate = date => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
return `${year}-${month}-${day}`;
};
const currentWeekStart = formatDate(startDate);
const currentWeekEnd = formatDate(endDate);
return {
currentWeekStart,
currentWeekEnd
};
}
const weekRangeInChina = getWeekRange();
</script>
<template>
<div ref="containerRef" class="gantt-container">
<g-gantt-chart
chart-start="00:00"
chart-end="23:59"
precision="hour"
date-format="HH:mm"
bar-start="beginDate"
bar-end="endDate"
grid
class="full-width-gantt"
>
<template #upper-timeunit>
<h1>
{{
`${weekRangeInChina.currentWeekStart} / ${weekRangeInChina.currentWeekEnd}`
}}
</h1>
</template>
<g-gantt-row
v-for="(item, index) in context"
:key="index"
:bars="item"
:label="item[0].week"
highlight-on-hover
/>
</g-gantt-chart>
</div>
</template>
<style>
/* 全局样式,确保能覆盖组件内部样式 */
.g-gantt-row-label,
.g-gantt-row-label-container {
position: relative !important;
transition: none !important;
}
.gantt-container {
width: 100%;
overflow-x: auto;
padding-bottom: 10px;
}
.full-width-gantt {
min-width: 1500px;
width: 200%;
}
/* 修改标签宽度样式 */
.g-gantt-row-label {
width: 100px !important;
min-width: 100px !important;
max-width: 100px !important;
box-sizing: border-box !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
}
</style>
重点处理方法是:
// 添加滚动位置状态
const scrollLeft = ref(0);
// 添加容器引用
const containerRef = ref(null);
// 添加和移除滚动事件监听
onMounted(() => {
// 延迟添加事件监听,确保DOM已完全渲染
setTimeout(() => {
if (containerRef.value) {
containerRef.value.addEventListener("scroll", handleScroll);
console.log("滚动监听已添加", containerRef.value);
}
}, 500);
});
// 滚动事件处理函数
function handleScroll(e) {
scrollLeft.value = e.target.scrollLeft;
console.log("滚动事件触发", scrollLeft.value);
const labels = document.querySelectorAll(
".g-gantt-row-label, .g-gantt-row-label-container"
);
labels.forEach(label => {
label.style.position = "absolute";
label.style.left = scrollLeft.value + "px";
});
}
onUnmounted(() => {
if (containerRef.value) {
containerRef.value.removeEventListener("scroll", handleScroll);
console.log("滚动监听已移除");
}
});