Gantt 甘特图
项目排期语义的任务图表组件(data 族):行树 WBS(父任务摘要条 = 子任务时间并集)× 横向时间轴,任务条 / 里程碑 / 摘要条三形态 + 进度填充;依赖连线(FS/SS/FF/SF 四型,SVG 单画布覆盖层);拖拽三件套(拖条改期 / 左右手柄拉伸 / 拖改进度,pointerup 收口一次性写回并派发事件);时间刻度六档(hour/day/week/month/quarter/year)双层表头;今日线、周末/假日列高亮;行虚拟滚动支撑万级任务;三级只读 + 任务级禁拖。数据契约以扁平 parent 指针为主(嵌套 children 输入自动拍平兼容)。
基础用法
行树 WBS + 依赖连线 + 里程碑 + 进度(tasks JSON,扁平 parent / 嵌套 children 双通道)
- 父任务渲染摘要条(时间 = 子任务并集、进度 = 子任务工期加权平均),行首折叠钮收起/展开子行,展开集合写回
expanded属性(JSON 数组)并派发oas-expand-change;折叠后子行连同其依赖连线一并隐藏(连线随行可见性走,不穿到摘要条); - 里程碑渲染为菱形:
type: "milestone"显式声明优先(即使携带end也按里程碑渲染,end忽略并console.warn提示数据矛盾一次),无end亦推导为里程碑;有子任务时恒按摘要条渲染(子级承载聚合语义,形态与聚合须一致;仅当同时显式声明type: "milestone"时console.warn提示数据矛盾一次);start晚于end(日期颠倒)在清洗层自动交换并console.warn一次(不渲染 2px 假条); dependencies声明依赖(type缺省fs,支持fs/ss/ff/sf四型),SVG 单画布绘制折线 + 箭头;- 悬停任务条出 tooltip(名称 + 起止 + 进度);
template[slot="tooltip"]可覆盖内容([data-task-name]/[data-task-range]/[data-task-progress]绑定点)。
刻度六档(scale)
时间刻度六档:hour / day(默认)/ week / month / quarter / year(双层表头:上层主刻度合并 + 下层辅刻度)
切换 scale 重排时间轴(列宽随档位自适应,下限保证标签有立足位),派发 oas-scale-change;非法值回落 day。列宽被容器压窄到放不下标签时辅刻度按 N 抽稀(保留格线、隐去部分文本,如日档窄列每 2 格),避免日号/月号首尾相接。拖拽吸附以当前刻度为单位(snap="false" 关闭吸附,按像素比例平移并保留时间精度)。
拖拽三件套
拖条改期 / 手柄拉伸 / 拖改进度(pointerup 收口一次性写回;Esc 或 pointercancel 取消零事件)
- 拖条身 = 整体平移(保持工期);拖左右手柄 = 改开始/结束(不越过对侧);拖条内圆点 = 改进度;
- 收口(pointerup)才写回并派发
oas-task-change(detail: { id, task, oldStart, oldEnd, start, end })/oas-progress-change(detail: { id, task, progress })+oas-tasks-change(全量),零位移松开零事件; - 拖拽中 Esc(或 pointercancel)取消 → 视觉回滚、零事件零写回;拖拽中外部重写
tasks属性 → 拖拽终止回滚(外部数据为准); - 聚焦任务条后 Shift + ←/→ 键盘改期一格(RTL 方向镜像)。
只读三级 + 任务级禁用
readonly(全禁)/ dates-readonly(禁改期)/ progress-readonly(禁进度);只读态不渲染拖拽手柄(视觉即语义)
任务数据里的 disabled: true 单独禁该条(其他任务不受影响)。
今日线与周末/假日高亮
今日线(show-today 默认开)+ 周末列高亮(weekends 默认开)+ holidays 假日高亮(演示区间动态覆盖今天)
关闭今日线 / 关闭周末高亮 / 假日高亮(holidays JSON)
今日线为装饰层(aria-hidden),落在时间轴范围内才渲染;周末/假日列高亮在 day/hour 档生效。
行虚拟滚动(万级任务)
height + row-height 启用视口窗口渲染(演示 300 行;只渲染可视窗口 + buffer)
方法:scrollToTask(id) 定位任务行、scrollToDate(date) / scrollToToday() 水平定位、updateTask(id, patch) 单条增量更新(走清洗层,派发 oas-tasks-change)。
展开集合受控 / 标签与吸附 / 本地化
expanded 受控(JSON 数组 = 已展开集合;显式 [] 全收起)+ label-position 标签(缺省 none 不渲染——行名列已承载名称;inside 条内 / right 条旁需显式开启)
snap=false 非吸附(半格平移保留时间精度)+ locale / first-day-of-week 本地化
template[slot="task"] 覆盖条内标签内容([data-task-name] 绑定名称;缺省 label-position="none" 不渲染标签,需显式开启后模板才生效);每条任务渲染后派发 oas-task-render(detail: { task, element }),宿主可改写条内 DOM。
API
oas-gantt
属性
| 属性 | 说明 | 类型 | 默认值 |
|---|---|---|---|
dates-readonly | 禁改期/拉伸(进度仍可拖) | boolean | — |
expanded | 已展开集合(JSON 数组,受控):属性缺席缺省全展开;显式 [] 全收起;点折叠钮写回 | string | — |
first-day-of-week | 周起始日(0-6);缺省按 locale 推导(week 档对齐用) | string | — |
height | 组件高度 px(默认 320) | string | 320 |
holidays | 假日列表(JSON ["YYYY-MM-DD",…]):对应列高亮(优先于周末底色) | string | — |
label-position | 任务条标签位置:inside 条内 / right 条旁 / left 条左;缺省 none(行名列已承载名称,条旁不再重复渲染);非法值回落 none | string | — |
locale | 本地化(覆盖 config-provider 注入与全局 locale) | string | — |
progress-readonly | 禁改进度(改期仍可拖) | boolean | — |
readonly | 整图只读(禁改期/禁进度,不渲染拖拽手柄) | boolean | — |
row-height | 行高 px(默认 36,下限 20) | string | 36 |
scale | 时间刻度:hour / day(默认)/ week / month / quarter / year;非法值回落 day | string | — |
show-today | 今日线(默认开;false 关闭) | string | — |
snap | 拖拽吸附当前刻度(默认开;false 按像素比例平移并保留时间精度) | string | — |
tasks | 甘特任务(JSON):[{ id?, name, start, end?, type?, progress?, parent?, children?, dependencies?, color?, disabled?, expanded? }]——扁平 parent 指针为主,嵌套 children 自动拍平;type:"milestone" 显式优先(带 end 也按里程碑渲染,end 忽略),有子任务时恒为摘要;无 end 亦推导为里程碑;start 晚于 end 自动交换 | GanttTask[] | [] |
weekends | 周末列高亮(默认开;day/hour 档生效;false 关闭) | string | — |
Property(JS property;是否写回 attribute 见各行说明)
| Property | 说明 | 类型 | 默认值 |
|---|---|---|---|
tasks | 甘特任务(GanttTask[]):el.tasks 读(拷贝,嵌套输入已拍平为 parent 指针);el.tasks = [...] 写(同步 tasks 属性 + 重渲染 + 派发 oas-tasks-change) | GanttTask[] | [] |
事件
| 事件 | 说明 |
|---|---|
oas-expand-change | 行树折叠/展开时派发,detail: |
oas-progress-change | 拖进度手柄收口时派发,detail: |
oas-scale-change | scale 属性变化时派发,detail: { scale };首次吸收不派发 |
oas-task-change | 拖拽/拉伸/键盘改期收口(pointerup)时派发,detail: { id, task, oldStart, oldEnd, start, end };零位移不派发 |
oas-task-click | 点击任务条/里程碑时派发,detail: |
oas-task-dblclick | 双击任务条时派发,detail: { id, task }——宿主接编辑表单 |
oas-task-render | 每条任务渲染后派发,detail: { task, element }——宿主可改写条内 DOM |
oas-tasks-change | 任务数据变化(程序写 tasks / updateTask / 拖拽写回)时派发,detail: |
插槽
| 名称 | 说明 |
|---|---|
template[slot="empty"] | 空数据态内容(缺省「暂无任务」) |
template[slot="task"] | 任务条标签模板(克隆进条身,[data-task-name] 节点自动填任务名) |
template[slot="tooltip"] | 悬停浮层模板([data-task-name] / [data-task-range] / [data-task-progress] 绑定点) |
CSS 变量
| CSS 变量 | 默认值 |
|---|---|
--oas-gantt-bar-bg | color-mix(in srgb, var(--oas-gantt-bar-color, var(--oas-color-primary)) 22%, transparent) |
--oas-gantt-bar-height | 22px |
--oas-gantt-bar-progress-bg | var(--oas-gantt-bar-color, var(--oas-color-primary)) |
--oas-gantt-grid-line-color | var(--oas-color-border) |
--oas-gantt-header-bg | var(--oas-color-bg) |
--oas-gantt-header-height | 44px |
--oas-gantt-height | 320px |
--oas-gantt-holiday-bg | color-mix(in srgb, var(--oas-color-warning) 12%, transparent) |
--oas-gantt-link-color | var(--oas-color-primary) |
--oas-gantt-list-width | 220px |
--oas-gantt-milestone-color | var(--oas-color-warning) |
--oas-gantt-row-height | 36px |
--oas-gantt-summary-bg | var(--oas-color-text-secondary-strong) |
--oas-gantt-today-color | var(--oas-color-danger) |
--oas-gantt-weekend-bg | color-mix(in srgb, var(--oas-color-bg-hover) 60%, transparent) |