npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

gantt-planing-vue

v0.10.0

Published

Vue 3 Gantt chart & 5-in-1 project-planning diagram component (Gantt, Time-Scaled network, ADM, PERT/PDM, Linear time-location) — task tree, CPM critical path, virtual scroll, CAD viewport

Readme

gantt-planing-vue

现代化 Vue 3 工程项目进度管理与 5 合 1 图表引擎组件库(甘特图 + 时标网络图 + 双代号 ADM + 单代号 PERT/PDM 前导图 + 形象进度时距图),原生支持 CAD 级平移缩放视口与关键路径法(CPM)算法。

Vue 3 TypeScript Vite License: MIT


🌟 核心特性

1. 5 合 1 图表引擎(统一底层数据驱动)

  • 甘特图(Gantt Chart):
    • 无限级任务树(WBS、工期、进度、起止日期),大数据高性能手动虚拟滚动(Phantom 容器 + translateY 视口裁剪)。
    • 任务条交互:整体平移改期、右侧手柄拉伸工期,松手自动补齐到落点所在刻度格;进度以实心条按 progress 绘制。
    • 任务形态:普通任务、project 摘要条(两端竖线封口)、milestone 里程碑(菱形标记)。
    • 依赖连线:拖动任务条上的锚点直接拉线连接紧后任务,正交折线 + 箭头自动避让。
    • 刻度模式:年 / 季 / 月 / 周 / 日 / 12 小时 / 6 小时 / 小时,共 8 档(ScaleMode),支持国际化(locale)。
    • 左侧表格由业务方自建:组件只负责时间轴 + 横道 + 连线,选中态通过 activeTaskId 受控回写(v-model:active-task-id)。
    • 快捷键:Tab / Shift + Tab(升降级)、Delete / Backspace、Ctrl|Cmd + D(删除)、Ctrl|Cmd + X / C / V(剪切/复制/粘贴)、Esc(取消选中)。
  • 时标网络图(Time-Scaled Network Diagram):水平实箭线表示工作持续时间,工程标准**自由时差波形线(FF)**自动生成,紧后工作折线/垂直逻辑转移线。
  • 双代号网络图(ADM):节点为事件编号圆圈 $(i) \to (j)$(满足拓扑序 $i < j$),箭线上标工作名、下标持续时间,逻辑断路与虚工作自动生成虚箭线。
  • 单代号 / PERT 前导图(PDM):工程级标准六参数活动卡片(ES / DU / EF / 工作名 / LS / TF / LF),基于拓扑分层的 Sugiyama 正交避让连线。
  • 形象进度图(时距图 / Time-Location Diagram):横轴时间推进 × 纵轴里程桩号,支持构造物符号、路基填挖、停工区间、共线段、里程桩号与高程曲线,Canvas 光栅化 + 2 倍图导出 PNG/PDF。
    • 视图旋转:工具栏内置旋转按钮,点一下转 90°(0° / 90° / 180° / 270°),与图片预览的「点一下转一下」一致。缩放、平移、点击拾取与导出的 PNG/PDF 全部跟着转,是真旋转而非只把画面转过去。详见 旋转视图。

2. 关键路径法(CPM)引擎

  • 内置标准 CPM 前向正推(Forward Pass,求 $ES, EF$)与逆向逆推(Backward Pass,求 $LS, LF$)。
  • 自动计算总时差 $TF$ 与自由时差 $FF$,识别关键工作($TF = 0$)并以红色标注关键线路。
  • 图表工具栏提供「关键路径」开关:开启后淡化非关键工作,突出关键线路。

3. CAD 级交互视口(useCadViewport)

  • 无级缩放:滚轮以鼠标光标为锚点缩放(10% ~ 450%)。
  • 画布平移:鼠标左键 / 中键拖拽无限平移。
  • CAD 控制台:放大、缩小、1:1 还原、一键全图自适应居中(Fit to Screen)。
  • 点阵背景底纹与图例系统。

4. 主题与尺寸可运行时调整

所有外观项都通过 CSS 自定义属性下发(样式表内只写 var(...)),因此改动 props 即时换肤,无需重新编译;变量只挂在组件根元素上,不会污染宿主应用全局。


📦 安装

npm install gantt-planing-vue
# 或者
pnpm add gantt-planing-vue
# 或者
yarn add gantt-planing-vue

Vue 3.4+ 为 peerDependency,本库零运行时依赖。


🚀 快速上手

1. 全局注册插件

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import GanttPlaningVue from 'gantt-planing-vue'
import 'gantt-planing-vue/style.css'

const app = createApp(App)
app.use(GanttPlaningVue)
app.mount('#app')

2. 在组件中使用

组件不内置左侧表格。数据由 taskData 传入(task-data),变更通过 update:tasks 事件回传——注意入参与出参的名字不对称,所以请写成显式的 :task-data + @update:tasks,而不要写 v-model:tasks(后者会把 tasks 当作未知属性透传到根元素上)。

<script setup lang="ts">
import { ref } from 'vue'
import { GanttChart, ScaleMode, ViewMode, type Task, type TaskId } from 'gantt-planing-vue'

const tasks = ref<Task[]>([
  {
    id: 1,
    parent_id: 0,
    type: 'task',
    name: '基础工程',
    duration: 5,
    progress: 40,
    project: 'ProjectSample',
    start: new Date(2026, 8, 1),
    end: new Date(2026, 8, 5, 23, 59, 59, 999),
    children: [],
  },
  {
    id: 2,
    parent_id: 0,
    type: 'task',
    name: '主体结构施工',
    duration: 10,
    progress: 10,
    project: 'ProjectSample',
    dependencies: ['1'], // 紧前任务为基础工程
    start: new Date(2026, 8, 6),
    end: new Date(2026, 8, 15, 23, 59, 59, 999),
    children: [],
  },
])

const scaleMode = ref<ScaleMode>(ScaleMode.Day)
const viewMode = ref<ViewMode>(ViewMode.GanttViewer)
/** 左侧表格自建,这里只把选中行受控回写,键盘快捷键才有操作目标 */
const activeTaskId = ref<TaskId>(0)
</script>

<template>
  <div style="width: 100vw; height: 100vh;">
    <!-- 切换模式:GanttViewer | TimeViewer | AdmViewer | PdmViewer | LinearViewer -->
    <GanttChart
      :task-data="tasks"
      :scale-mode="scaleMode"
      :view-mode="viewMode"
      v-model:active-task-id="activeTaskId"
      :column-width="38"
      @update:tasks="tasks = $event"
    />
  </div>
</template>

任务条拖拽改期后会派发 date-change 与 update:tasks,两者都可用于同步后端。

3. 里程碑与摘要任务

// 里程碑:渲染为菱形标记(居中于所在刻度格)
{ id: 3, type: 'milestone', name: '主体封顶', duration: 1, progress: 100, /* ... */ }

// 摘要 / 项目:渲染为两端带竖线的粗横杠,通常用其子任务的起止范围
{ id: 4, type: 'project', name: '一期工程', duration: 60, progress: 55, /* ... */ }

🎨 外观与主题 Props

数值型尺寸项直接生效;颜色项留空即使用内置配色。

| 分类 | Props | | --- | --- | | 尺寸 | headerHeight、columnWidth、rowHeight、ganttHeight(不传则撑满父容器) | | 条形态 | barCornerRadius、handleWidth、barFill(条高占行高百分比,默认 64) | | 字体 | fontFamily、fontSize(不传则继承宿主应用) | | 普通任务 | barBackgroundColor、barBackgroundSelectedColor、barProgressColor、barProgressSelectedColor | | 摘要任务 | projectBackgroundColor、projectBackgroundSelectedColor、projectProgressColor、projectProgressSelectedColor | | 里程碑 | milestoneBackgroundColor、milestoneBackgroundSelectedColor | | 其他 | arrowColor、arrowIndent、todayColor |

需要更细的换肤(如摘要条端封颜色),可直接覆盖根元素上的 CSS 变量: --gantt-selected-outline、--gantt-project-cap-color、--gantt-actual-bg、--gantt-bar-height 等。


🔄 旋转视图

形象进度图的工具栏内置一组旋转按钮:⟲ 逆时针 90°、⟳ 顺时针 90°、角度按钮复位。旋转角只有四档(Rotation = 0 | 90 | 180 | 270),图纸连同坐标文字一起侧倒,与图片预览的「点一下转一下」是同一个观感。

旋转不是只把画面转过去。 图纸是 Canvas 绘制的,视口里每一处交互都锚定在「屏幕 x = 图纸 x」上,所以组件内部把屏幕坐标系统一逆变换回图纸坐标系,因此旋转 90° 后:

  • 滚轮缩放:锚点仍然落在光标下(不会跑到对角去);
  • 拖拽平移:鼠标沿屏幕上图纸的方向拖动即可,手感自洽;
  • 点击拾取:点中的仍是光标正下方那条线,select-task 不会错位;
  • 导出 PNG / PDF:按当前旋转角转置,所见即所得(转着导出,图也是转的)。

旋转后组件只重新居中、不动缩放级别 —— 缩放是你此刻的观看意图,不该被旋转重置。

一个必须知道的副作用:旋转 90° / 270° 后,容器宽 = 图纸的时间轴、容器高 = 里程轴。也就是说容器又矮又宽时旋转反而只能看到很短的一段里程;又高又窄时时间轴能看很长,但一次只能看到很少的里程。所以旋转在这类工程图里主要是展示 / 投屏 / 打印用途,并不是提升信息密度的手段。

只作用于形象进度图:标准甘特图、时标网络图 / ADM / PERT 的图形形状本身就是横长的,旋转没有意义,这些视图不提供旋转按钮。

需要把旋转挂到自己的工具栏时,设 showRotateControls: false,改用组件实例方法:

<LinearProgressViewer ref="viewerRef" :show-rotate-controls="false" :tasks="tasks" />
viewerRef.value.rotate(1)          // 顺时针 90°
viewerRef.value.rotate(-1)         // 逆时针 90°
viewerRef.value.setRotation(180)   // 直接指定角度
viewerRef.value.resetRotation()    // 复位为 0°
viewerRef.value.rotation           // 当前角度

🛠️ 单独使用 CAD 网络图查看器

<script setup lang="ts">
import { ref } from 'vue'
import { DiagramViewer, type Task } from 'gantt-planing-vue'

const tasks = ref<Task[]>([/* 任务数据 */])
const mode = ref<'time' | 'adm' | 'pert'>('pert')
</script>

<template>
  <div style="width: 1000px; height: 600px;">
    <DiagramViewer
      :tasks="tasks"
      :mode="mode"
      :show-toolbar="true"
      :show-legend="true"
      @select-task="(t) => console.log('选中', t)"
    />
  </div>
</template>

🧮 独立调用 CPM 关键路径算法

import { calculateCpm } from 'gantt-planing-vue'

const result = calculateCpm(tasks)
console.log('总工期:', result.totalDuration)
console.log('关键线路任务 ID 列表:', result.criticalPath)

// 每个活动的六参数:
result.activityList.forEach(act => {
  console.log(`${act.name}: ES=${act.es}, EF=${act.ef}, LS=${act.ls}, LF=${act.lf}, 总时差TF=${act.tf}, 自由时差FF=${act.ff}, 关键工作=${act.isCritical}`)
})

💻 本地运行 Demo

# 进入项目根目录
cd gantt-planing-vue

# 安装依赖
npm install

# 启动 Vite 开发服务器预览 Demo
npm run dev

# 运行类型检查
npm run typecheck

# 构建生产产物
npm run build

📚 文档

| 文档 | 内容 | | --- | --- | | docs/USAGE.md | 完整使用手册:Props / 事件 / 插槽速查、TaskId 与 idMode、刻度与国际化、快捷键与只读模式、按需导入与类型清单 | | CHANGELOG.md | 版本变更记录(含破坏性变更逐条说明) | | src/components/diagram/README.md | 网络图 / 形象进度图模块的内部结构与算法入口 |


📄 开源许可证

MIT License © 2026