全功能施工项目管理甘特图 Demo:任务依赖箭头、当前日期标线、周末高亮、分组项目可视化

完整可运行 HTML 使用方式

  1. 复制全部代码,新建 .html 文件粘贴保存
  2. 直接双击文件用浏览器打开,无需本地服务、无跨域、正常预览完整甘特图
  3. 支持所有主流浏览器(Chrome/Edge/360/Firefox)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>项目管理甘特图 - Highcharts Gantt 可预览修复版</title>
    <!-- 稳定CDN,严格加载顺序:基础内核→甘特模块 -->
    <script src="https://cdn.jsdelivr.net/npm/highcharts@11.4.3/highcharts.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/highcharts@11.4.3/modules/gantt.min.js"></script>
    <style>
        * {margin: 0; padding: 0; box-sizing: border-box;}
        body {background: #fff; padding: 10px;}
        #container {
            width: 100%;
            height: 90vh;
            border: 1px solid #eee;
        }
    </style>
</head>
<body>
<div id="container"></div>

<script>
const day = 24 * 36e5,
    today = Math.floor(Date.now() / day) * day;

const options = {
    chart: {
        plotBorderColor: 'rgba(128,128,128,0.1)',
        plotBorderWidth: 1,
        plotBorderRadius: 5
    },

    plotOptions: {
        series: {
            borderRadius: '50%',
            connectors: {
                lineWidth: 1,
                lineColor: '#666',
                radius: 10,
                endMarker: {
                    verticalAlign: 'bottom',
                    align: 'center',
                    yOffset: 5
                },
                startMarker: {
                    symbol: 'arrow-half',
                    lineWidth: 1,
                    lineColor: '#666',
                    xOffset: -5
                }
            },
            groupPadding: 0,
            dataLabels: [{
                enabled: true,
                align: 'left',
                format: '{point.name}',
                padding: 10,
                style: {
                    fontWeight: 'normal',
                    textOutline: 'none'
                }
            }, {
                enabled: true,
                align: 'right',
                format: '{#if point.completed}{(multiply point.completed.amount 100):.0f}% {/if}',
                padding: 10,
                style: {
                    fontWeight: 'normal',
                    textOutline: 'none',
                    opacity: 0.6
                }
            }]
        }
    },

    series: [{
        name: '办公场地项目',
        data: [{
            name: '新办公室筹备',
            id: 'new_offices',
            owner: 'Peter',
            pointWidth: 3,
            color: '#666',
            dataLabels: {
                align: 'right',
                style: { color: '#666' },
                x: 72
            }
        }, {
            name: '办公楼装修施工',
            id: 'prepare_building',
            parent: 'new_offices',
            start: today - (8 * day),
            end: today + (6 * day),
            completed: { amount: 0.5 },
            owner: 'Linda'
        }, {
            name: '建筑竣工验收',
            id: 'inspect_building',
            dependency: 'prepare_building',
            parent: 'new_offices',
            start: today + 6 * day,
            end: today + 8 * day,
            owner: 'Ivy'
        }, {
            name: '验收通过里程碑',
            id: 'passed_inspection',
            dependency: 'inspect_building',
            parent: 'new_offices',
            start: today + 9.5 * day,
            milestone: true,
            owner: 'Peter'
        }, {
            name: '搬迁工作',
            id: 'relocate',
            owner: 'Josh',
            pointWidth: 3,
            color: '#666',
            dataLabels: {
                align: 'right',
                style: { color: '#666' },
                x: 57
            }
        }, {
            name: '员工搬迁',
            id: 'relocate_staff',
            parent: 'relocate',
            start: today + 10 * day,
            end: today + 11 * day,
            owner: 'Mark'
        }, {
            name: '实验室设备迁移',
            dependency: 'relocate_staff',
            parent: 'relocate',
            start: today + 11 * day,
            end: today + 13 * day,
            owner: 'Anne'
        }, {
            name: '食堂搬迁',
            dependency: 'relocate_staff',
            parent: 'relocate',
            start: today + 11 * day,
            end: today + 14 * day
        }]
    }, {
        name: '产品项目',
        data: [{
            name: '新品上线计划',
            id: 'new_product',
            owner: 'Peter',
            pointWidth: 3,
            color: '#666',
            dataLabels: {
                align: 'right',
                style: { color: '#666' },
                format: '上线',
                x: 50
            }
        }, {
            name: '产品研发',
            id: 'development',
            parent: 'new_product',
            start: today - day,
            end: today + (11 * day),
            completed: { amount: 0.6 },
            owner: 'Susan'
        }, {
            name: 'Beta测试里程碑',
            id: 'beta',
            dependency: 'development',
            parent: 'new_product',
            start: today + 12.5 * day,
            milestone: true,
            owner: 'Peter'
        }, {
            name: '最终版本完善开发',
            id: 'finalize',
            dependency: 'beta',
            parent: 'new_product',
            start: today + 13 * day,
            end: today + 17 * day
        }, {
            name: '正式上线里程碑',
            dependency: 'finalize',
            parent: 'new_product',
            start: today + 17.5 * day,
            milestone: true,
            owner: 'Peter'
        }]
    }],
    tooltip: {
        pointFormat: '<span style="font-weight: bold">{point.name}</span><br>' +
            '{point.start:%m月%d日}' +
            '{#unless point.milestone} → {point.end:%m月%d日}{/unless}' +
            '<br>' +
            '{#if point.completed}完成进度: {multiply point.completed.amount 100}%<br>{/if}' +
            '负责人: {#if point.owner}{point.owner}{else}未分配{/if}'
    },
    title: {
        text: '项目管理甘特图',
        align: 'left'
    },
    xAxis: [{
        currentDateIndicator: {
            color: '#ef4444',
            dashStyle: 'ShortDot',
            width: 2,
            label: { format: '' }
        },
        dateTimeLabelFormats: {
            day: '%d<br><span style="opacity: 0.5; font-size: 0.7em">%a</span>'
        },
        grid: { borderWidth: 0, cellHeight: 46 },
        gridLineWidth: 1,
        min: today - 3 * day,
        max: today + 19 * day,
        custom: { weekendPlotBands: { color: '#f2f2f2' } }
    }, {
        dateTimeLabelFormats: { month: '%m月%Y年' },
        labels: {
            align: 'left',
            x: 5,
            style: { fontSize: '0.7em', fontWeight: 'bold' }
        },
        grid: { borderWidth: 0, cellHeight: 24 },
        tickInterval: 30 * 24 * 36e5
    }],
    yAxis: {
        grid: {
            borderWidth: 0,
            enabled: true,
            columns: [{
                title: { text: '任务名称', textAlign: 'left', x: 18 },
                labels: { format: '{value}', indentation: 0 }
            }, {
                title: { text: '工期', textAlign: 'left', x: 8 },
                labels: {
                    format: '{#if point.x2}{(divide (subtract point.x2 point.x) 86400000)} 天{else} - {/if}',
                    style: { opacity: 0.7 }
                }
            }]
        },
        gridLineWidth: 0,
        staticScale: 30
    }
};

// 周末底色渲染插件
Highcharts.addEvent(Highcharts.Axis, 'foundExtremes', e => {
    const weekendColor = e.target.options.custom?.weekendPlotBands?.color;
    if (!weekendColor) return;
    const axis = e.target, chart = axis.chart, day = 24 * 36e5;
    const isWeekend = t => /[06]/.test(chart.time.dateFormat('%w', t));
    const plotBands = [];
    let inWeekend = false;
    for (let x = Math.floor(axis.min / day) * day; x <= Math.ceil(axis.max / day) * day; x += day) {
        const last = plotBands.at(-1);
        if (isWeekend(x) && !inWeekend) {
            plotBands.push({ from: x, color: weekendColor });
            inWeekend = true;
        }
        if (!isWeekend(x) && inWeekend && last) {
            last.to = x;
            inWeekend = false;
        }
    }
    axis.options.plotBands = plotBands;
});

// 延迟初始化,保证模块全部加载完成
window.addEventListener('load', function(){
    Highcharts.ganttChart('container', options);
})
</script>
</body>
</html>

图表类型 & 示例解析

1. 图表类型

Highcharts Gantt 甘特图(项目排期图),支持树形分层任务、任务依赖箭头、里程碑标记、进度百分比、多列侧边栏、双层时间轴。

2. 核心功能模块拆解

  1. 分层树形任务 分为两大项目分组:办公场地、新品研发;每组下存在父任务、子任务,自动缩进分层展示,区分项目大类与细分工作项。
  2. 任务前置依赖联动 通过 dependency 绑定任务 ID,自动生成带箭头连接线,直观展示任务先后顺序,前序任务完成后方可执行后续工作。
  3. 里程碑节点 milestone: true 生成菱形标记,仅占单个时间点,用于验收、上线、测试等关键节点。
  4. 任务进度百分比 completed.amount 配置完成比例,任务条内部填充进度,右侧标签直接展示百分比数值。
  5. 双层 X 时间轴 上层:按日展示星期与日期;下层:按月展示年月,兼顾精细查看与全局周期预览。
  6. 双列表 Y 轴侧边栏 左侧第一列:任务名称;第二列:自动计算任务工期(天数),无需额外表格搭配。
  7. 辅助视觉增强
    • 红色虚线:当前系统日期标线,直观区分过去 / 未来任务;
    • 周末自动灰色底色区分,快速识别休息日;
    • 悬浮 Tooltip:展示起止日期、完成进度、任务负责人、前置依赖;
  8. 插件扩展能力 内置 Axis 扩展事件,自动计算并渲染周末底色,无需手动批量配置时间区间色块。

在这套全功能项目甘特图案例中,Highcharts Gantt 提供开箱即用的专业排期可视化能力,解决传统表格、简易图表无法直观展示任务时序、依赖关系、分层结构的痛点。

  1. 完备的任务结构体系:原生支持父子任务分层、ID 绑定前置依赖、里程碑标记、进度百分比填充,完整覆盖项目管理核心要素;
  2. 多维度信息一体化展示:双层 X 时间轴 + 双列表 Y 侧边栏,任务名称、工期、起止时间、负责人、完成进度统一在图表内呈现,无需搭配辅助表格;
  3. 高度自定义视觉与交互:可自由配置任务条圆角、连接线箭头样式、周末高亮色块、当前日期标线,悬浮提示可自定义多字段格式化;
  4. 插件化扩展机制:基于 Highcharts 原生事件系统扩展周末底色自动渲染逻辑,扩展性强,可根据业务新增节假日、预警色块、延期标记等功能;
  5. 无障碍与适配优化:内置完整无障碍朗读描述,支持键盘导航,布局自适应缩放,兼容 PC 端管理后台与数据大屏场景;
  6. 轻量化集成:单库引入即可运行,无需复杂依赖,配置代码结构清晰,便于前后端对接动态渲染项目数据。
我也要推广
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值