#要实现效果
-
以横向条形图的形式展示不同停机坪(Y轴)在一天24小时(X轴,0-24点)内的状态变化。
能够清晰看到每个停机坪在哪些时间段是被占用的,哪些是空闲的。
支持多任务段与空隙处理: -
通过 convertData函数动态生成系列数据,支持一个停机坪在同一天内有多个不连续的任务段(例如:上午作业,中午空闲,下午维护)。
利用“透明占位系列”(gap-i)和“任务系列”(task−{i})和“任务系列”(task-i)和“任务系列”(task−{i})堆叠的方式,正确渲染任务之间的时间间隔(空隙),确保时间轴的准确性。
状态颜色区分: -
根据任务状态(如“正在占用”、“已预约”、“空闲”、“维护”)自动映射不同的颜色(红、橙、绿、灰),直观反映停机坪的业务状态。
内部标签显示: -
在条形图内部直接显示任务状态文本(如“正在占用 (作业)”),方便用户快速识别,无需鼠标悬停。
-
设置了文本溢出截断(overflow: ‘truncate’),防止文字过长影响布局。
自定义 Tooltip(提示框):
当鼠标悬停在图表上时,显示该停机坪当天所有任务段的详细列表,包括状态名称和具体的起止时间(例如:0:00 - 16:00)。
代码
<template>
<div id="gantt-chart" ref="ganttChartRef"></div>
</template>
import * as echarts from 'echarts'
const ganttChartRef = ref<HTMLElement | null>(null);
let ganttChart: echarts.ECharts | null = null;
// --- 甘特图逻辑 ---
const initGanttChart = () => {
nextTick(() => {
if (!ganttChartRef.value) return;
// 1. 模拟数据
const rawTimeData = [
{ name: '01号停机坪', tasks: [{ status: '已预约 (巡检)', start: 0, end: 16 }, { status: '正在占用 (作业)', start: 16, end: 22 }, { status: '维护 (离线)', start: 22, end: 24 }] },
{ name: '02号停机坪', tasks: [{ status: '正在占用 (作业)', start: 0, end: 12 }, { status: '维护 (离线)', start: 12, end: 24 }] },
{ name: '03号停机坪', tasks: [{ status: '正在占用 (作业)', start: 0, end: 24 }] },
{ name: '04号停机坪', tasks: [{ status: '已预约 (物流)', start: 0, end: 14 }, { status: '已预约 (物流)', start: 14, end: 24 }] },
{ name: '05号停机坪', tasks: [{ status: '空闲可用', start: 0, end: 14 }, { status: '已预约 (巡检)', start: 14, end: 24 }] },
{ name: '06号停机坪', tasks: [{ status: '正在占用 (作业)', start: 0, end: 24 }] }
];
const colorMap: Record<string, string> = {
'正在占用 (作业)': '#c23531',
'空闲可用': '#61a0a8',
'已预约 (物流)': '#d48806',
'已预约 (巡检)': '#d48806',
'维护 (离线)': '#999999'
};
const convertData = (data: any[]) => {
const categories = data.map(item => item.name);
const seriesList: any[] = [];
const maxTasks = Math.max(...data.map(item => item.tasks.length));
for (let i = 0; i < maxTasks; i++) {
// 占位系列
seriesList.push({
name: `gap-${i}`,
type: 'bar',
stack: 'total',
silent: true,
itemStyle: { color: 'transparent' },
data: data.map(item => {
const task = item.tasks[i];
if (!task) return 0;
if (i === 0) return task.start;
const prevTask = item.tasks[i - 1];
if (!prevTask) return task.start;
const gap = task.start - prevTask.end;
return gap > 0 ? gap : 0;
})
});
// 任务系列
seriesList.push({
name: `task-${i}`,
type: 'bar',
stack: 'total',
label: {
show: true,
position: 'inside',
formatter: (params: any) => {
const task = data[params.dataIndex].tasks[i];
return task ? task.status : '';
},
color: '#fff',
fontSize: 10,
overflow: 'truncate',
width: 60
},
itemStyle: {
color: (params: any) => {
const task = data[params.dataIndex].tasks[i];
return task ? (colorMap[task.status] || '#ccc') : 'transparent';
}
},
data: data.map(item => {
const task = item.tasks[i];
if (!task) return 0;
return task.end - task.start;
})
});
}
return { categories, seriesList };
};
const result = convertData(rawTimeData);
const option = {
backgroundColor: 'transparent',
tooltip: {
trigger: 'axis',
axisPointer: { type: 'shadow' },
formatter: (params: any) => {
if (!params || params.length === 0) return '';
const dataIndex = params[0].dataIndex;
const item = rawTimeData[dataIndex];
let res = `<div style="font-weight:bold; margin-bottom:5px;">${item.name}</div>`;
item.tasks.forEach((task: any) => {
res += `<div style="display:flex; justify-content:space-between; gap:10px; font-size:12px;">
<span style="color:${colorMap[task.status] || '#fff'}">● ${task.status}</span>
<span>${task.start}:00 - ${task.end}:00</span>
</div>`;
});
return res;
}
},
grid: {
left: '15%',
right: '5%',
top: '5%',
bottom: '10%'
},
xAxis: {
type: 'value',
min: 0,
max: 24,
axisLabel: { formatter: '{value}:00', color: '#fff' },
splitLine: { show: true, lineStyle: { type: 'dashed', color: 'rgba(255,255,255,0.1)' } }
},
yAxis: {
type: 'category',
data: result.categories,
axisTick: { show: false },
axisLine: { show: false },
axisLabel: { color: '#fff' }
},
series: result.seriesList
};
if (!ganttChart) {
ganttChart = echarts.init(ganttChartRef.value);
}
ganttChart.setOption(option);
// 监听容器大小变化
window.addEventListener('resize', () => {
ganttChart?.resize();
});
});
};
onMounted(() => {
initGanttChart();
});
实现效果

在一天24小时(X轴,0-24点)内的状态变化】&spm=1001.2101.3001.5002&articleId=160119345&d=1&t=3&u=98752bb8bdd44b619457e36088b4b226)
252

被折叠的 条评论
为什么被折叠?



