Scheduler
scheduler在月、周、日和资源视图里排事件,可拖拽建单改期
用法
受控用法
events / view / date 全部受控,由消费者持有 state;onEventsChange 回吐整组新 events(照 Kanban 受控范式)。
6/1 – 6/7
周一6/1
周二6/2
周三6/3
周四6/4
周五6/5
周六6/6
周日6/7
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
复诊 · 陈先生
初诊 · 刘女士
09:00–10:00 · 外科
换药 · 赵先生
儿科疫苗
术后随访
11:00–12:00
停诊 · 学术会议
13:00–17:00
tsx
const [events, setEvents] = useState(INITIAL);
const [view, setView] = useState<SchedulerView>("week");
const [date, setDate] = useState(monday);
<Scheduler
events={events}
view={view}
date={date}
resources={resources}
onViewChange={setView}
onDateChange={setDate}
onEventsChange={setEvents}
/>资源视图
view='resource' 时横轴为 resources(医生/诊室)、纵轴为时间;需传 resources。
2026 年 6 月 1 日
李医生内科
王医生外科
张医生儿科
09:00
10:00
11:00
12:00
13:00
14:00
15:00
16:00
17:00
18:00
19:00
20:00
复诊 · 陈先生
换药 · 赵先生
初诊 · 刘女士
09:00–10:00 · 外科
tsx
<Scheduler
events={events}
view="resource"
date={date}
resources={resources}
onEventsChange={setEvents}
/>月总览
view='month' 给出整月概览,点某天经 onDateChange + onViewChange 下钻到日视图。
2026 年 6 月
周一
周二
周三
周四
周五
周六
周日
tsx
<Scheduler
events={events}
view="month"
date={date}
onDateChange={setDate}
onViewChange={setView}
/>自定义时间范围
dayStartHour / dayEndHour 收窄时间轴,hourHeight 调每小时像素高。
2026 年 6 月 1 日
6月1日周一
10:00
11:00
12:00
13:00
复诊 · 陈先生
初诊 · 刘女士
09:00–10:00 · 外科
换药 · 赵先生
tsx
<Scheduler
events={events}
view="day"
date={date}
dayStartHour={9}
dayEndHour={13}
hourHeight={72}
/>何时用
需要可交互的「事件日历/排班台」时用——预约、诊室排班、资源时间线,支持拖空白建预约、拖事件改期、拖下缘改时长。只读展示项目工序排期用 Gantt(不可拖拽);纯月历选日期用 Calendar/DatePicker。Scheduler 是带时间轴网格 + 拖拽编辑的旗舰排班件。
导入
ts
import { Scheduler, dateOf, dayColumns, eventRect, hourLines, layoutColumns, minutesOfDay, minutesToISO, monthMatrix, resourceColumns, snap, startOfWeekISO, weekColumns, yToMinutes } from "@hulianui/ui"Props
| 名称 | 类型 | 默认 | 说明 |
|---|---|---|---|
| events* | SchedulerEvent[] | - | 受控事件数组。{id, title, start, end, resourceId?, tone?, subtitle?};start/end 为 ISO datetime(含时分,本地时区) |
| view* | "month" | "week" | "day" | "resource" | - | 受控视图 |
| date* | string | - | 受控焦点日(ISO),决定哪周/哪天/哪月 |
| now | string | Date | 挂载后取浏览器时钟 | 「今天 / 此刻」的判定基准。渲染期不读系统时钟,所以首帧没有今天高亮与当前时刻线,挂载后补上(#181)。传了它就完全由你决定:截图回归要可复现、或「今天」该按服务端业务时钟而非用户本机时钟时用 |
| resources | SchedulerResource[] | - | resource 视图必填。{id, title, subtitle?} |
| dayStartHour | number | 8 | 时间轴起始小时 |
| dayEndHour | number | 20 | 时间轴结束小时 |
| slotMinutes | number | 30 | 吸附粒度(分钟) |
| hourHeight | number | 56 | 每小时像素高 |
| toolbar | boolean | true | 内置头部工具条(标题 + 前/今/后 + Segmented 视图) |
| className | string | - | 外层类名(须有确定高度,组件填满时间轴可滚) |
SchedulerEvent.tone:"primary" \| "success" \| "warning" \| "danger" \| "neutral",默认 primary(仅用已定义语义 token)。
Events
| 事件 | 类型 | 说明 |
|---|---|---|
| onViewChange | (v: SchedulerView) => void | 视图切换(内置 toolbar Segmented) |
| onDateChange | (iso: string) => void | 焦点日切换(前/今/后、点月视图某天) |
| onEventsChange | (events: SchedulerEvent[]) => void | 拖移/拖改时长提交:回吐整组新 events(照 Kanban 受控范式) |
| onSlotDragCreate | (slot: SchedulerSlot) => void | 空白竖拖创建(拖出一段时间) |
| onSlotClick | (slot: SchedulerSlot) => void | 点空白格(无拖动)创建 |
| onEventClick | (event: SchedulerEvent) => void | 点事件块 |
Slots
| 插槽 | 类型 | 说明 |
|---|---|---|
| renderEvent | (event: SchedulerEvent) => ReactNode | 渲染函数:自定义事件块内容(外框/定位/拖拽手柄由组件负责) |
禁忌 / 坑
- 渲染期不读系统时钟:SSR / 静态导出下服务端那次渲染发生在构建时刻、客户端首次渲染发生在访问时刻,两者跨天就算出不同的「今天」→ hydration 失败(React #418)。本组件因此把「此刻」推迟到挂载后,首帧没有今天高亮与当前时刻线。抄示例时别把
dayjs()写回模块顶层或渲染体里 ——useMemo(fn, [])也救不了,它只保证一次渲染树内稳定。要确定性就传now。 - 全受控:events/view/date 由消费者持有,拖拽不会自动改 state——必须接
onEventsChange回吐整组并 setState,否则拖完弹回原位(照 Kanban 范式)。 - 外层须给确定高度(如
h-[520px]+className="h-full"),时间轴靠容器高度填满后才内部滚动;不给高度会塌缩。 - tone 只接受 5 个语义枚举,刻意避开未定义色的静默回退;要任意配色走
renderEvent。 - start/end 是含时分的 ISO datetime(本地时区解释),区别于 Gantt 的纯日期闭区间。
- 内置工具条、星期、日期标题和「更多」文案读取
ConfigProvider的locale.components.scheduler。zhCN/enUS已内置;旧版自定义 locale 未提供该可选字段时继续回退中文,不影响现有消费者。
相关
Table · Book3D · ProTable · PricingTable · JsonViewer · EditableTable