Skip to content

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 方向镜像);
  • 拖条 / 拉伸 / 拖连线靠近视口边缘时,横向与纵向自动滚动(越靠边越快,到边界即停);拖行重排仅纵向自动滚动。

行拖拽改父子 / 重排(reparent) ​

拖左侧名称行:上/下半区 = 目标前/后(同级),指针深入右侧 = 成为目标子级;收口派发 oas-reparent

拖左侧名称行到目标:落在目标行上半区 → 插到目标之前(同级);下半区 → 插到目标之后(同级);指针深入右侧 → 成为目标的子级。收口派发 oas-reparent(detail: { id, parent, index },parent 为 null 表示根级)+ oas-tasks-change(全量)。不允许把父拖进自己的后代(防环,零事件);readonly 或任务级 disabled 不启动;拖拽中 Esc / pointercancel 取消零事件。

依赖连线交互编辑 ​

悬停任务条出连线点:从左/右点拖到目标任务建依赖(端点定 FS/SS/FF/SF);点连线选中后 Delete 删除

悬停任务条出两个连线点:拖右侧点(完成端)到目标条 → 建依赖;拖左侧点(开始端)同理。里程碑 start == end,只出完成端单点(fs 惯例;其作为前置时的 ss/sf 与 fs/ff 等价)。落点取目标条的左半(开始端)/ 右半(完成端),与起点端组合决定类型(FS / SS / FF / SF),依赖记在后继任务上。同源同型依赖不重复添加;同源多型可并存,选中删除按类型作用域只删该条。点已有连线选中(高亮),按 Delete / Backspace 删除(仅组件持有焦点时响应,不劫持宿主输入;任务条聚焦时按 Delete 不会误删已选连线)。收口派发 oas-dependencies-change(detail: { taskId, dependencies })+ oas-tasks-change。readonly 不渲染连线点与命中区、不可删;拖拽中 Esc / pointercancel 取消零事件。触屏点任务条揭示连线点;连线命中路径可聚焦,Enter/Delete 删除该依赖。

多选、重命名与键盘 ​

点击行选中(Ctrl/Cmd 加选、Shift 连选);双击名称重命名;Delete 批量删除;Alt+↑↓ 同级移动、Alt+←→ 升降级;连线聚焦 Enter 删除

  • 多选:点击左侧名称行选中(单选);Ctrl/Cmd 点击切换;Shift 点击范围连选;选中态走 selection property(id 数组,可读写)与 oas-selection-change 事件。Delete/Backspace 删除所选(连同其后代),或调用 removeTasks(ids)。
  • 行内重命名:双击名称 → 输入框(Enter 提交 / Esc 还原 / 失焦提交),改 name 并派发 oas-tasks-change。
  • 键盘:行聚焦后 ↑/↓ 移动焦点、空格 选择、Alt+↑/↓ 同级上移/下移、Alt+→ 降为前一项子级、Alt+← 升为父级同级、F2 重命名;连线命中路径可聚焦,Enter/Delete 删除该依赖(删除后焦点交回组件,键盘不落空)。
  • 无障碍:名称列为 role="tree",每行 treeitem 带 aria-level / aria-posinset / aria-setsize(同级全集,含折叠子级;悬空/断环父级按根计);选中态同步 aria-selected,展开态同步 aria-expanded。
  • 触屏:点任务条揭示其连线点(无 hover);左列行首的拖拽手柄(⋮⋮)用于触屏行重排(整行纵向拖与列表滚动在触屏上冲突,改由手柄承载;手柄独占手势,其余区域仍可滚动),纯点按手柄不改选中。

任务管理(创建 / 编辑 / 依赖 / 导出) ​

宿主用命令式方法驱动增删改,无需整体重写 tasks(写回统一走清洗层并派发 oas-tasks-change):

  • addTask(task?, opts?):新增任务,返回新 id;opts: { parent?, before?, after? }。缺省名走 i18n gantt.newTask、开始为今天、非里程碑补 1 天(含端)。
  • moveTask(id, { parent?, index? }):改父级 / 调同级顺序,派发 oas-reparent + oas-tasks-change。
  • duplicateTask(id, opts?):深拷贝任务及其子树(各自新 id),紧跟原子树之后,返回新根 id。
  • addDependency(taskId, dep) / removeDependency(taskId, dep) / updateDependency(taskId, from, to):增 / 删 / 改依赖(dep: { id, type? }),派发 oas-dependencies-change。
  • updateTasks(patches):批量浅合并([{ id, ...patch }]),返回生效条数,只派发一次 oas-tasks-change。
  • 缩放:zoomIn() / zoomOut() 沿六档刻度步进;fit() 取最细且能容纳全部任务的档。
  • 属性 creatable(布尔,默认关):开启后行尾出「+」(摘要行加子级、叶子行加同级后继)、双击空白区按落点日期建任务,新建后进入行内重命名;只读 / 任务级禁用行不出按钮。
  • 事件 oas-task-add(detail { id, task }):命令式或行内新建后派发,供宿主定位并打开编辑。

命令式任务管理:新建 / 复制所选 / 加依赖 / 删除所选 / 缩放 / 导出;creatable 行内新建(点行尾「+」或双击空白)

新建任务复制所选加依赖(所选→下一项)删除所选改进度 +10缩小放大适配导出 JSON

用 oas-modal + oas-form 组装任务详情编辑器(组件只派发 oas-task-dblclick,不内建弹窗):

html
<oas-gantt id="g" creatable></oas-gantt>
<oas-modal id="edit" title="编辑任务">
  <oas-form id="edit-form">
    <oas-form-item label="名称" name="name" required><oas-input name="name"></oas-input></oas-form-item>
    <oas-form-item label="开始" name="start" required><oas-date-picker name="start"></oas-date-picker></oas-form-item>
    <oas-form-item label="结束" name="end"><oas-date-picker name="end"></oas-date-picker></oas-form-item>
    <oas-form-item label="进度" name="progress"><oas-slider name="progress" show-value></oas-slider></oas-form-item>
  </oas-form>
</oas-modal>
<script>
  const g = document.getElementById('g')
  const modal = document.getElementById('edit')
  const form = document.getElementById('edit-form')
  const field = (name) => form.querySelector(`oas-input[name="${name}"], oas-date-picker[name="${name}"], oas-slider[name="${name}"]`)
  let editing = ''
  g.addEventListener('oas-task-dblclick', (e) => {
    editing = e.detail.id
    const t = e.detail.task
    field('name').value = t.name
    field('start').value = t.start
    field('end').value = t.end ?? ''
    field('progress').value = t.progress ?? 0
    modal.setAttribute('visible', '') // 受控打开(弹窗点「确定」会自关)
  })
  modal.addEventListener('oas-ok', () => form.submit())
  form.addEventListener('oas-submit', (e) => {
    const v = e.detail.values // 表单值恒为字符串,数字字段按需转换
    g.updateTask(editing, { ...v, progress: Number(v.progress) })
  })
</script>

oas-task-dblclick / oas-task-click 与 oas-task-render 让宿主任意接管编辑与自定义渲染;组件本身只保证数据与交互闭环。

任务管理增强(依赖联动排程 / 框选 / 拖拽建任务) ​

  • 依赖联动排程:auto-schedule(布尔,默认关)——日期变更(拖拽 / 键盘 / updateTask / updateTasks)或依赖增改后,按 FS/SS/FF/SF 沿依赖图对后继做最小前推(只推迟、保持工期;跳过 disabled 与摘要行;成环安全),派发 oas-reschedule(detail { ids })与联动的 oas-tasks-change。
  • 框选多任务:左侧列表空白纵向拖按行带选中;时间轴空白拖(未开 creatable 时)按条相交选中;Ctrl/Cmd 追加。结果写入 selection 并派发 oas-selection-change;只读下仍可框选(选择属查看态)。
  • 拖拽建任务:creatable 开启时,在时间轴空白拖出区间即建相应跨度任务(双击空白按当天建保留)。

触屏:时间轴空白拖与二维滚动冲突,时间轴上的框选/拖建不接管触屏手势(留给原生滚动);触屏建任务用行尾「+」或双击空白,框选用左侧列表纵向拖。auto-schedule 下摘要任务作前置时按其后代聚合区间约束(忽略摘要自身 date 字段)。

auto-schedule:拖右侧「原型」条向右,后继「开发」按 FS 自动顺延;时间轴空白拖出区间建任务;左侧空白纵向拖框选多行

排程深化(依赖 lag/lead + 关键路径) ​

  • 依赖 lag/lead:dependencies: [{ id, type?, lag? }]——lag 单位为天、可负(负 = 提前/重叠),并入 auto-schedule 四型约束(fs: 后继 start ≥ 前置 end + lag、ss: 后继 start ≥ 前置 start + lag、ff/sf 同理按 end)。缺省 0,向后兼容。|lag| 超过 11574 天(≈31 年)或非有限数值时按 0 处理并 devWarn 一次(防止极端值把排期写成组件无法回读的 5 位年份)。
  • 关键路径:show-critical-path(布尔,默认关)——以当前排期为基准(ES 取现网 start)在依赖图 + 工期上反向推最晚时间算总时差,时差为 0 的任务条加 .critical 高亮(颜色走 --oas-gantt-critical-color)。只读展示,不改数据。
  • 时差标记:总时差为 0 → .critical(实线描边);总时差为负(已违反后继约束)→ .conflict(虚线描边,--oas-gantt-conflict-color)。el.tasks 里 lag 为分数(如 0.5)时会把该条升为时间精度串(按需取整)。

关键路径:a→b(长)、a→c(短)同为 a 的后继——b 在关键路径上高亮,c 有时差不高亮(关闭 show-critical-path 即无高亮)

排程约束与工作日日历 ​

  • 任务约束:GanttTask.constraint('asap' 默认 / 'snet' 不得早于 / 'mso' 固定开始 / 'fnlt' 不得晚于完成)+ constraintDate。auto-schedule 下:snet 取起始下限、mso 固定开始(不被依赖前推)、fnlt 为软截止(不自动移动)。违反(snet 早于下限 / mso 与依赖冲突或偏离 / fnlt 超期)在 show-critical-path 或 auto-schedule 开启时以 .conflict 标出。摘要行上的约束无意义(日期派生)→ 忽略并告警一次。
  • 工作日日历:workdays(JSON 周几数组 [0..6],opt-in;缺省/空 = 不限周几)+ holidays(假日恒为非工作日,与是否开 workdays 无关)。auto-schedule 的前推落点吸附到下一个工作日(跳过假日与 workdays 之外的日子)。运行期改 workdays/holidays 或整体重写 tasks 都会触发重新规整。
  • 事件顺序:auto-schedule 开启且联动改期时,无论交互提交(拖拽 / 键盘 / updateTask / updateTasks)还是宿主直接改写 tasks(属性通道),事件序统一为 oas-reschedule(联动订正)→ oas-tasks-change(订正后的最终数据);拖拽 / 键盘改期收口随后再派发 oas-task-change(拖动的那个任务,start/end 取订正后终值)。一次操作只派发一次 oas-tasks-change。宿主以 el.tasks / detail.task 为准即可。

工作日日历:workdays=[工作日] 下拖前置,后置自动吸附到下一个工作日;连线 +2(lag)标签可见

宿主集成配方(撤销重做 / 编辑弹窗 / 导出) ​

组件只保证「数据 + 交互闭环」,下列能力以官方配方给出(不改组件本体):

撤销 / 重做(宿主自建历史栈) ​

组件是受控数据模型:每次改动派发 oas-task-change(含 oldStart/oldEnd/start/end)与 oas-tasks-change。宿主据这些事件维护自己的历史栈最稳妥——组件内建历史会与宿主 tasks 真相形成双源:撤销写回内部再被宿主回写覆盖、粒度与宿主业务动作不一致、受控重渲染会把撤销结果弹回。典型做法:监听 oas-task-change/oas-reparent/oas-dependencies-change 记录逆操作,撤销/重做时用 updateTask / moveTask / updateTasks 回写。

编辑弹窗(双击任务条) ​

组件只派发 oas-task-dblclick;用 oas-modal + oas-form 组装详情编辑器:

双击任务条打开编辑弹窗(oas-modal + oas-form),保存经 updateTask 写回

导出(JSON / 打印 / 图片) ​

  • JSON:el.tasks 即为可序列化数据(嵌套输入已拍平)——JSON.stringify(el.tasks)。
  • 打印:加 @media print 展开时间轴、隐藏无关 UI;或先 fit() 再 window.print()。
  • 图片 / PDF:宿主侧渲染(HTML→canvas 或 SVG 序列化),示例:new XMLSerializer().serializeToString(el.shadowRoot.querySelector('.inner')) 后转 canvas。

导出:点按钮输出当前 tasks JSON(宿主可直接落库/下载)

导出 JSON

只读三级 + 任务级禁用 ​

readonly(全禁)/ dates-readonly(禁改期)/ progress-readonly(禁进度);只读态不渲染拖拽手柄(视觉即语义)

readonly:整图只读
dates-readonly:禁改期、进度可拖
progress-readonly:禁进度、改期可拖

任务数据里的 disabled: true 单独禁该条(其他任务不受影响):只锁自身数据——不可被拖(作源)、不可作依赖后继、不可作重排 drop-inside 目标;但可作他任务的前置(连线源)与重排前/后同级目标。

今日线与周末/假日高亮 ​

今日线(show-today 默认开)+ 周末列高亮(weekends 默认开)+ holidays 假日高亮(演示区间动态覆盖今天)

关闭今日线 / 关闭周末高亮 / 假日高亮(holidays JSON)

今日线为装饰层(aria-hidden),落在时间轴范围内才渲染;周末/假日列高亮在 day/hour 档生效。

基线对比(show-baseline) ​

show-baseline 开启:实际条下叠浅色基线条,title 标差值(比基线晚/早 N 天或一致)

show-baseline(默认关)开启后,任务带 baseline: { start, end? } 时在实际条下渲染一条浅色基线条;条的 title 标实际相对基线的差值(比基线晚/早 N 天、或「与基线一致」)。基线数据由宿主保存,组件只读不写回;基线条颜色走 --oas-gantt-baseline-color。baseline.progress 为基线进度(0-100),开启后在基线条内渲染进度覆盖层(--oas-gantt-baseline-progress-color)。

截止日、浮时与基线差异(deadline / show-float / baseline.progress) ​

show-baseline + show-float:基线进度、总浮时/自由浮时;deadline 超期标 conflict

  • GanttTask.deadline:截止日(YYYY-MM-DD;hour 档可带时刻)。条结束晚于截止日时加 .conflict,并在时间轴渲染 .deadline 虚线标记。
  • show-float:显示总浮时(LF − EF)与自由浮时(最近后继允许的延后量);条上同时写入 data-total-float / data-free-float(天)。摘要不参与 CPM;windowed 模式无法在切片上得到正确依赖图,会跳过并 devWarn。
  • baseline.progress:基线进度 0-100;开启 show-baseline 后基线条内渲染 .baseline-progress 覆盖层。
  • 宿主可用导出的纯函数 computeVariance(tasks) 得到基线差异:
ts
import { computeVariance } from '@oas-ui/ui'

const rows = computeVariance(el.tasks)
// [{ id, startDelta, endDelta, durationDelta, progressDelta }]
// 正数 = 当前晚于基线 / 工期更长 / 进度更多;无 baseline.progress 时 progressDelta 为 null

行虚拟滚动(万级任务) ​

height + row-height 启用视口窗口渲染(演示 300 行;只渲染可视窗口 + buffer)

方法通道:scrollToTask 跳到第 250 行

方法:scrollToTask(id) 定位任务行、scrollToDate(date) / scrollToToday() 水平定位、updateTask(id, patch) 单条增量更新(走清洗层,派发 oas-tasks-change)。

服务端行窗口(windowed) ​

十万行级场景:宿主只喂「可视窗口附近」的行切片,组件不持有全量数据。行窗口按滚动位置计算,未被已装载区间覆盖时派发 oas-window-request,宿主回填后按绝对行号渲染。

属性 windowed(开启)+ total(全量行数)+ window-start(切片首行绝对行号)+ range-start / range-end(宿主托管时间轴范围,ISO 日期,range-end 含当日——切片不含完整日期跨度时必用)。事件:

  • oas-window-request:detail: { start, end, reason }(半开区间、绝对行号;reason = init / scroll / resize / data),同一期望区间不重复派发。
  • oas-range-request:可视时间窗接近轴端时派发,detail: { startMs, endMs, reason },供宿主扩展范围。
html
<oas-gantt windowed total="200000" window-start="0" range-start="2026-01-01" range-end="2026-12-31"
  height="360" scale="day"></oas-gantt>
<script>
  const el = document.querySelector('oas-gantt[windowed]')
  el.addEventListener('oas-window-request', (e) => {
    const { start, end } = e.detail
    el.setAttribute('window-start', String(start))
    el.setAttribute('tasks', JSON.stringify(fetchTasks(start, end))) // 真实项目请求后端
  })
</script>

windowed 下的约定:切片须为扁平行(含 parent/children 的层级切片会 devWarn 并按扁平渲染,展开/收起请宿主侧展平);auto-schedule 与关键路径在部分数据上会算错,跳过并 devWarn;行拖拽重排禁用(index 只对切片有意义);切片越界(window-start + 装载行数 > total)时越界行按 total 夹取不渲染,并 devWarn 一次;跨窗口连线不绘制——前置任务不在已装载切片内时该依赖连线跳过(组件只持有切片,无法定位切片外端点;需要完整连线时请让宿主把相关前置一并放入切片,或在聚合层展示);一次用户操作只派发一次 oas-tasks-change;oas-tasks-change 的 detail.tasks 仅含切片——宿主须按 id 合并回全量,不得整体替换。

完整宿主取数配方(分段、取消在途、按 id 合并、原子回填)与可运行示例见 服务端窗口取数。

展开集合受控 / 标签与吸附 / 本地化 ​

  • 自定义字段透传:GanttTask 允许携带任意业务字段(如 assignee、tag)——组件原样保留(el.tasks / oas-task-render / 模板可见),不参与排程;显示走条标签模板或 oas-task-render,编辑走 oas-modal+oas-form 配方或 updateTask。
  • 行名列自定义模板:<template slot="row"> 每行克隆进 .name,其中 [data-task-name] 自动填任务名;可放任意控件——这就是「负责人」列的落点(负责人用自定义字段承载,模板负责显示与就地编辑)。模板内控件不会被行拖拽/选中劫持。示例:
html
<oas-gantt id="g">
  <template slot="row">
    <span data-task-name></span>
    <oas-select class="owner" size="small" options='[{"label":"张三","value":"zhang"},{"label":"李四","value":"li"}]'></oas-select>
  </template>
</oas-gantt>
<script>
  const g = document.getElementById('g')
  const tasks = [{ id: 'a', name: '设计', start: '2026-03-02', end: '2026-03-06', owner: 'zhang' }]
  g.tasks = tasks
  // 克隆后按行回填控件
  g.shadowRoot.querySelectorAll('.row-name').forEach((row) => {
    const t = tasks.find((x) => x.id === row.dataset.key)
    row.querySelector('.owner').value = t.owner
  })
  // 改负责人 → 写回自定义字段
  g.addEventListener('oas-change', (e) => {
    const row = e.target.closest('.row-name')
    if (row && e.target.classList.contains('owner')) g.updateTask(row.dataset.key, { owner: e.target.value })
  })
</script>

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 ​

属性 ​

属性说明类型默认值
auto-schedule依赖联动排程(布尔,默认关):日期变更(拖拽/键盘/updateTask/updateTasks)或依赖增改后,按 FS/SS/FF/SF 沿依赖图对后继做最小前推(只推迟不提前、保持工期),跳过 disabled 与摘要行,成环安全;派发 oas-reschedulestring—
creatable行内新建(布尔,默认关):开启后行尾出「+」(摘要行加子级、叶子行加同级后继)、双击空白区按落点日期建任务,新建后进入行内重命名;只读/任务级禁用行不出按钮boolean—
dates-readonly禁改期/拉伸(进度仍可拖)boolean—
expanded已展开集合(JSON 数组,受控):属性缺席缺省全展开;显式 [] 全收起;点折叠钮写回string—
first-day-of-week周起始日(0-6);缺省按 locale 推导(week 档对齐用)string—
height组件高度 px(默认 320;接受纯数字或 Npx):映射到自定义属性 --oas-gantt-height。高度挂在内部画布(.gantt)上——宿主自身 height 内联只框定外盒,内部画布高度仍由 height 属性 / --oas-gantt-height 决定(不会被宿主内联 height 拉伸);整体调高请用 height 属性或 --oas-gantt-height。height 属性在场且为合法值(>0 纯数字或 Npx)时组件接管该变量,写入宿主内联并覆盖宿主自己设置的 --oas-gantt-height;空串/空白按未设置处理;非法值不写该变量、仅清除本实例此前写入的值,宿主 token 不受影响;属性移除后组件写入的值归零清除,高度回落 token 缺省 320 或宿主 CSS,宿主原先内联设置的值不恢复;从未设置 height 属性时组件不写该变量,宿主内联或 class 规则设置的 --oas-gantt-height 完全不受影响string320
holidays假日列表(JSON ["YYYY-MM-DD",…]):对应列高亮(优先于周末底色);假日恒为非工作日(与 workdays 是否开启无关),auto-schedule 前推时跳过string—
label-position任务条标签位置:inside 条内 / right 条旁 / left 条左;缺省 none(行名列已承载名称,条旁不再重复渲染);非法值回落 nonestring—
locale本地化(覆盖 config-provider 注入与全局 locale)string—
progress-readonly禁改进度(改期仍可拖)boolean—
range-end宿主托管时间轴终点(ISO 日期 YYYY-MM-DD,含当日):与 range-start 成对使用string—
range-start宿主托管时间轴起点(ISO 日期 YYYY-MM-DD):提供后轴范围不再由数据推导,配合 range-end 支撑窗口化(切片不含完整日期跨度)string—
readonly整图只读(禁改期/禁进度,不渲染拖拽手柄)boolean—
row-height行高 px(默认 36,下限 20)string36
scale时间刻度:hour / day(默认)/ week / month / quarter / year;非法值回落 daystring—
show-baseline基线对比(布尔,默认关):任务带 baseline 时在实际条下渲染基线条(baseline.progress 渲染进度覆盖层),title 标差值(比基线晚/早 N 天或一致)boolean—
show-critical-path关键路径(布尔,默认关):在依赖图与工期上算总时差,时差为 0 的任务加 .critical 高亮(颜色走 --oas-gantt-critical-color);只读展示不改数据string—
show-float显示总浮时/自由浮时(布尔,默认关):仅在依赖图完整时计算,条上显示「总浮时/自由浮时」标签并写入 data-total-float/data-free-float(单位为天);摘要不参与,windowed 模式跳过并 devWarnstring—
show-today今日线(默认开;false 关闭)string—
snap拖拽吸附当前刻度(默认开;false 按像素比例平移并保留时间精度)string—
stripe行斑马纹(布尔,默认关):按绝对行号奇偶给行加底色(虚拟化/窗口化滚动稳定,不随 DOM 顺序跳变);颜色走 --oas-gantt-row-stripe-bg(缺省 --oas-color-bg-hover);选中/周末假日等背景覆盖条纹string—
tasks甘特任务(JSON):[{ id?, name, start, end?, type?, progress?, parent?, children?, dependencies?, color?, disabled?, expanded?, baseline?(start/end?/progress?), deadline?, constraint?(asap/snet/mso/fnlt), constraintDate? }]——扁平 parent 指针为主,嵌套 children 自动拍平;type:"milestone" 显式优先(带 end 也按里程碑渲染,end 忽略),有子任务时恒为摘要;无 end 亦推导为里程碑;start 晚于 end 自动交换GanttTask[][]
totalwindowed 模式下的全量行(任务)数;为 0 或非法时 windowed 不生效(回落本地模式)string—
weekends周末列高亮(默认开;day/hour 档生效;false 关闭)string—
window-startwindowed 模式下切片首行的绝对行号(相对全量)string0
windowed服务端行窗口模式(布尔,默认关):与 total / window-start 配合,宿主只喂可视窗口切片(按绝对行号渲染),期望行区间未被已装载覆盖时派发 oas-window-request 由宿主回填;本地跨全量能力(auto-schedule / 关键路径)在部分数据上会算错,已跳过并 devWarn。非 windowed 行为不变boolean—
workdays工作日周几(JSON [0-6],0=周日…6=周六;opt-in,缺省/空=不限制):auto-schedule 前推结果吸附到下一个工作日(叠加 holidays)string—

Property(JS property;是否写回 attribute 见各行说明) ​

Property说明类型默认值
selection选中任务 id 集合(string[]):el.selection 读(拷贝);el.selection = [...] 写(重渲染选中态 + 派发 oas-selection-change);removeTasks(ids) 批量删除(连同后代)string[]—
tasks甘特任务(GanttTask[]):el.tasks 读(拷贝,嵌套输入已拍平为 parent 指针);el.tasks = [...] 写(同步 tasks 属性 + 重渲染 + 派发 oas-tasks-change)GanttTask[][]

事件 ​

事件说明
oas-dependencies-change连线拖拽建依赖 / 选中删除收口时派发,detail: { taskId, dependencies }(taskId 为依赖变化的后继任务)
oas-expand-change行树折叠/展开时派发,detail:
oas-progress-change拖进度手柄收口时派发,detail:
oas-range-request宿主托管时间范围(range-start/range-end)且可视时间窗接近轴端点时派发,detail: { startMs, endMs, reason }(期望的相邻范围);同一期望范围不重复派发
oas-reparent行拖拽改父子 / 重排收口时派发,detail: { id, parent, index }(parent 为 null 表示根级,index 为同级序号)
oas-reschedule依赖联动排程改动了后继任务时派发(auto-schedule 开启),detail: { ids }(被联动改动的任务 id)
oas-scale-changescale 属性变化时派发,detail: { scale };首次吸收不派发
oas-selection-change多选集合变化(点击 / 键盘 / property 写入)时派发,detail: { ids }(选中的任务 id 数组)
oas-task-add命令式新增任务后派发(addTask / duplicateTask / creatable 行内新建),detail: { id, task }(id 为新任务 id)
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:
oas-window-requestwindowed 模式下期望行窗口未被已装载区间覆盖时派发,detail: { start, end, reason }(半开区间、绝对行号;reason 为 init / scroll / resize / data);同一期望区间不重复派发

插槽 ​

名称说明
template[slot="empty"]空数据态内容(缺省「暂无任务」)
template[slot="row"]行名列自定义模板(每行克隆进 .name;[data-task-name] 自动填任务名;可内含控件以渲染/编辑负责人等自定义字段,行拖拽与选中不会劫持其中控件)
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%, var(--oas-color-bg))
--oas-gantt-bar-height—22px
--oas-gantt-bar-progress-bg—var(--oas-gantt-bar-color, var(--oas-color-primary))
--oas-gantt-baseline-color基线条颜色(默认半透明次要文字色)color-mix(in srgb, var(--oas-color-text-secondary-strong) 55%, transparent)
--oas-gantt-baseline-progress-color—var(--oas-color-text-secondary-strong)
--oas-gantt-conflict-color违约(负总时差)高亮色(默认 --oas-color-danger)var(--oas-color-danger)
--oas-gantt-critical-color关键路径高亮色(默认 --oas-color-danger)var(--oas-color-danger)
--oas-gantt-deadline-color截止日标记颜色(默认 --oas-color-danger)var(--oas-color-danger)
--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-row-stripe-bg—var(--oas-color-bg-hover)
--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)

基于 MIT OR Apache-2.0 双许可发布