# OneFlow UI > [English README](./README.en.md) [![npm version](https://img.shields.io/npm/v/@oneflowui/ui.svg)](https://www.npmjs.com/package/@oneflowui/ui) [![npm downloads](https://img.shields.io/npm/dm/@oneflowui/ui.svg)](https://www.npmjs.com/package/@oneflowui/ui) [![license](https://img.shields.io/npm/l/@oneflowui/ui.svg)](https://github.com/qixi54/oneui/blob/main/LICENSE) Vue 3 + TypeScript 任务管理视图组件库,75 个组件开箱即用。 **包含**:Table、Kanban、Gantt 甘特图、Gallery、AI Chat、Dashboard 图表、Rich Text Editor、Form Designer、MermaidChart、Toast 等。 --- ## 预览
Kanban 看板 DataTable 数据表格
Kanban DataTable
Gantt 甘特图 Dashboard 仪表盘
Gantt Dashboard
AI Chat 对话组件 DetailLayout 详情页
AI Chat Detail
RichTextEditor 富文本 MermaidChart 图表
Editor Mermaid
--- ## 安装 ```bash # pnpm(推荐) pnpm add @oneflowui/ui # npm npm install @oneflowui/ui # yarn yarn add @oneflowui/ui ``` 安装 peer dependencies(按需): ```bash pnpm add vue pnpm add mermaid # 使用 MermaidChart 时需要 ``` --- ## 快速开始 ### 全局注册 ```ts import { createApp } from 'vue' import App from './App.vue' import OneflowUI from '@oneflowui/ui/plugin' import '@oneflowui/ui/styles' const app = createApp(App) app.use(OneflowUI) app.mount('#app') ``` 如果需要更细粒度的导入边界,可以直接使用稳定子路径入口: ```ts import { useVirtualListStateCache } from '@oneflowui/ui/composables' import type { DataRecord } from '@oneflowui/ui/types' ``` 推荐约定: - 组件与公共能力优先从 `@oneflowui/ui` 根入口导入。 - composables 和纯类型如果希望导入意图更清晰,可分别从 `@oneflowui/ui/composables` 与 `@oneflowui/ui/types` 导入。 - 如果只想注入 token 和主题层,不想顺带注册插件,可改用 `@oneflowui/ui/theme`。 - 样式全量入口仍保留 `@oneflowui/ui/styles`,兼容现有消费方式。 ### 按需引入 ```ts import { KanbanBoard, DataTable, AiMessageList, MermaidChart } from '@oneflowui/ui' import '@oneflowui/ui/styles' ``` 说明:从 `0.5.4` 开始,`plugin` 入口与根入口解耦。全局注册走 `@oneflowui/ui/plugin`,命名导入继续走 `@oneflowui/ui`。 ### 主题层 OneUI 当前默认提供一套中性主题,并允许在不改组件逻辑的前提下切换到上层产品皮肤。 - 默认主题:`neutral` - 可选皮肤:`ops-console` 推荐做法是让组件继续消费统一 token,然后由应用层切换主题,而不是直接覆盖组件内部样式。 ```ts import '@oneflowui/ui/styles' document.documentElement.dataset.ofTheme = 'neutral' // 或 document.documentElement.dataset.ofTheme = 'ops-console' ``` 如果你希望把“样式注入”和“组件插件注册”拆开,推荐改用更明确的主题入口: ```ts import '@oneflowui/ui/theme' ``` 这套结构的目标是: 1. 组件默认保持中性、可复用 2. 业务系统通过主题皮肤注入品牌感或中控台气质 3. 后续可继续扩展更多主题,而不需要修改组件 API ### Token Override / Theme Bridge 如果你的应用已经有自己的设计系统 token,建议保留它们作为真源,再通过 CSS 变量桥接到 OneUI 的 `--of-*` 命名空间。运行时主题文件本身也遵循这个原则:`src/styles/variables.css` 负责默认 `--of-*` 变量面,`src/styles/themes/neutral.css` 和 `src/styles/themes/ops-console.css` 只覆盖语义层。 ```css :root { --app-surface-canvas: #f6f7f9; --app-surface-panel: #ffffff; --app-text-primary: #0f172a; --app-text-secondary: #526071; --app-border-subtle: rgba(15, 23, 42, 0.08); --app-accent-default: #334155; --of-surface-canvas: var(--app-surface-canvas); --of-surface-elevated: var(--app-surface-panel); --of-text-primary: var(--app-text-primary); --of-text-secondary: var(--app-text-secondary); --of-border-subtle: var(--app-border-subtle); --of-accent-default: var(--app-accent-default); } ``` 局部换肤时,优先把 bridge 绑到 wrapper 上,而不是改全局根节点: ```css .ops-preview { --app-surface-canvas: #edf3f8; --app-surface-panel: rgba(255, 255, 255, 0.88); --app-accent-default: #0f4c81; --of-surface-canvas: var(--app-surface-canvas); --of-surface-elevated: var(--app-surface-panel); --of-accent-default: var(--app-accent-default); } ``` 完整 token 参考按 surface / text / border / accent / state / shadow / radius / spacing / z-index 分类收录在 [`docs/CSS-TOKENS.md`](docs/CSS-TOKENS.md)。 ### ThemeScope 包装组件 如果同一页面里需要并存两种视觉语境,优先使用 `ThemeScope`。这个组件会自动给 wrapper 注入 `data-of-theme` 和 `data-of-theme-scope`,业务方不需要手写属性。 ```vue ``` `ThemeScope` 当前支持的主题值与全局主题一致: - `neutral` - `ops-console` 老代码里直接手写的 `data-of-theme-scope` 仍然兼容,但新代码优先使用组件入口。 ### ThemeScope 场景组件 如果你想把“局部主题 + 标题 + 说明 + meta/footer 插槽”一起复用,直接用 `ThemeScopeScene`。它是一个轻量的场景壳层组件,适合企业后台、运营控制台、任务中心这类页面。 ```vue ``` `ThemeScopeScene` 内部继续复用 `ThemeScope` 的 token 作用域,所以它仍然是 non-breaking 的增强,只是把常见业务壳层收成了一个可复用组件。 ### 虚拟列表状态缓存 如果虚拟列表会频繁 remount,但你希望保留 `scrollTop`、`containerHeight` 和 `invalidateVersion`,可以按 key 复用同一份状态。 `createVirtualListState()` 仍然可用,而 `useVirtualListStateCache()` 适合把同一份状态挂在多个 remount 之间。 ```ts import { useVirtualList, useVirtualListStateCache } from '@oneflowui/ui' const virtualListState = useVirtualListStateCache('ai-message-list') const { visibleItems, totalHeight, offsetY } = useVirtualList({ items: messages, itemHeight: 60, containerRef, state: virtualListState, }) ``` ## 发布与验收 如果你需要核对当前可追溯的发布材料,优先看这几份文档: - `0.9.8` 发布阻塞记录:[`docs/plans/2026-05-07-release-0.9.8-proof.md`](docs/plans/2026-05-07-release-0.9.8-proof.md) - `0.9.8` 版本日志:[`docs/CHANGELOG-v0.9.8.md`](docs/CHANGELOG-v0.9.8.md) - Overlay 修复计划:[`docs/plans/2026-03-30-oneui-issues-136-138-remediation-plan.md`](docs/plans/2026-03-30-oneui-issues-136-138-remediation-plan.md) - 预发布验证:[`docs/plans/2026-03-22-oneui-theme-scope-middleware-composer-pre-release-verification.md`](docs/plans/2026-03-22-oneui-theme-scope-middleware-composer-pre-release-verification.md) - 子路径入口治理:[`docs/plans/2026-03-22-oneui-package-entrypoints-verification.md`](docs/plans/2026-03-22-oneui-package-entrypoints-verification.md) 当前 npm 主站已发布版本仍为 `0.9.7`;仓库内下一版 `0.9.8` 的验证与 publish 阻塞信息统一收口在 `docs/plans/2026-05-07-release-0.9.8-proof.md`。 --- ## 页面级方案 当前已经支持直接从包里接入页面级入口: ```ts import { DatabaseView, useDatabaseView } from '@oneflowui/ui' ``` `DatabaseView` 负责统一页面容器,`useDatabaseView` 负责页面状态编排。`dev` app 也已经接入这条链路, 用于证明 `local/provider` 双模式、视图切换、selected record 与 detail workspace 可以在同一页面层里闭环。 当前页面级契约还把 `detailPresentation` 和 `density` 作为明确的对齐方向:桌面端优先右侧 workspace, 移动端保留 sheet fallback;页面密度则统一按 `compact / standard / comfortable` 三档表达。 如果业务页来自通知、看板卡片或列表钻取,建议把 `detail-source` 一并传给 `DatabaseView`,这样 detail slot 就能同时拿到 `source` 和 `presentation` 两个 deep-link hints,而不需要业务侧再重复拼装来源说明。 ```vue ``` ```ts const view = useDatabaseView({ mode: 'provider', schemaSource, dataSource, actions: { onFetch, onRefresh, onUpdateRecord, onCreateRecord, onDeleteRecord, onSaveView, onSchemaChange, }, }) ``` ### 模式 - `local` 模式:外部直接传 `schema + records + view`,页面只负责筛选、排序、切视图和展示状态,不触发远程请求。 - `provider` 模式:外部传入数据获取/刷新能力,页面 shell 只消费 provider 返回的 `schema / records / views`,不绑定具体后端实现。 ### actions 契约 页面级方案只回传动作,不在组件内部写死业务逻辑。常见契约如下: ```ts type DatabaseViewActions = { onFetch?: (params: { viewId: string }) => Promise | void onRefresh?: () => Promise | void onUpdateRecord?: (payload: { tableId: string recordId: string patch: Record record: DataRecord }) => Promise | void onCreateRecord?: (payload: { tableId: string record: DataRecord }) => Promise | void onDeleteRecord?: (payload: { tableId: string recordId: string }) => Promise | void onSaveView?: (viewId: string, payload: Record) => Promise | void onSchemaChange?: (payload: Record) => Promise | void } ``` 如果接入的是 `provider` 模式,建议把 `onFetch` / `onRefresh` 作为必配项;如果接入的是 `local` 模式,则重点只需要保证 `onUpdateRecord`、`onCreateRecord`、`onDeleteRecord` 和 `onSaveView` 这几类页面动作可回传。 其中 `kanban` 视图会在以下场景自动回传这些动作: - 拖拽卡片换列或排序后,按 `record.id` 回传 `onUpdateRecord` - `QuickAddRow` 新建卡片后,回传 `onCreateRecord` - 若上层把某些记录从列集合中移除,可回传 `onDeleteRecord` ### Middleware presets 如果页面想复用 toast、分析埋点或乐观更新逻辑,可以直接组合 `useDatabaseView` 提供的 middleware presets: ```ts import { composeDatabaseViewMiddlewares, createDatabaseViewAnalyticsMiddleware, createDatabaseViewPresetBundle, createDatabaseViewPresetMiddleware, createDatabaseViewOptimisticMiddleware, createDatabaseViewToastMiddleware, useDatabaseView, } from '@oneflowui/ui' const middleware = composeDatabaseViewMiddlewares( createDatabaseViewToastMiddleware({ onSuccess: (message) => toast.success(message), onError: (message) => toast.error(message), }), createDatabaseViewAnalyticsMiddleware({ onEvent: (event) => console.log('[db-view]', event.phase, event.action), }), createDatabaseViewOptimisticMiddleware({ apply: ({ payload }) => updateLocalRecord(payload), revert: ({ payload }) => revertLocalRecord(payload), }), ) const view = useDatabaseView({ tableId: 'tbl-1', actions: { middleware, onCellEdit: saveCellEdit, }, }) ``` 除 `cell-edit` 之外,middleware 现在也会覆盖: - `create-record` - `update-record` - `delete-record` 因此看板里的 quick-add、拖拽换列和删卡这类持久化动作,也会进入同一套 toast / analytics / optimistic 链路。 如果你更想要一个“一键拿到可直接消费的 middleware”的入口,可以优先用官方 preset 工厂: ```ts const presetBundle = createDatabaseViewPresetBundle({ toast: { onSuccess: (message) => toast.success(message), onError: (message) => toast.error(message), }, analytics: { onEvent: (event) => console.log('[db-view]', event.phase, event.action), }, optimistic: { apply: ({ payload }) => updateLocalRecord(payload), revert: ({ payload }) => revertLocalRecord(payload), }, }) const view = useDatabaseView({ tableId: 'tbl-1', actions: { middleware: presetBundle.middleware, onCellEdit: saveCellEdit, }, }) ``` `createDatabaseViewPresetBundle` 会把常用 preset 先组装好,再暴露给业务方按需复用;`createDatabaseViewPresetMiddleware` 则适合直接塞进 `actions.middleware`,用于最小接入,例如: ```ts const middleware = createDatabaseViewPresetMiddleware({ toast: { onSuccess: (message) => toast.success(message), onError: (message) => toast.error(message), }, analytics: { onEvent: (event) => console.log('[db-view]', event.phase, event.action), }, optimistic: { apply: ({ payload }) => updateLocalRecord(payload), revert: ({ payload }) => revertLocalRecord(payload), }, }) ``` ### ThemeScope 场景模板 如果你想把 `ThemeScope` 从“局部 wrapper”升级成“业务场景模板”,可以直接把它当成页面壳层来组织区域结构。这个模板适合企业后台、运营控制台、任务看板这类页面:外层固定视觉语境,内层再放业务卡片、数据表、统计块和侧边说明。 ```vue ``` 仓库里的 `src/dev/examples/database/DatabaseEnterpriseDemo.vue` 就是这一类场景组件的 dev/examples 级参考实现。它展示的是“ThemeScopeScene + DatabaseView + middleware”的组合方式,便于复制到自家项目里改造成真正的企业页。 ### Dev Examples / Enterprise Demo `src/dev/examples/database/DatabaseEnterpriseDemo.vue` 是 dev/examples 级的消费范式,用来展示更完整的企业版页面组合方式。它属于开发示例和文档参考,不是 npm 包对外导出的组件,不会改变 `@oneflowui/ui` 的公开导出面。 仓库同时提供 `src/dev/examples/database/DatabasePresetDemo.vue` 作为更短的 preset bundle 官方示例,重点展示 `createDatabaseViewPresetBundle` / `actions.middleware` 的直接消费方式。 如果你在业务工程里需要类似的页面,建议直接复制示例里的组合思路,再按自己的数据源和动作契约接入,而不是依赖一个额外的生产级导出入口。 ### 组合消费示例 如果你要在同一块业务区域里同时使用主题作用域、数据库动作中间件和虚拟列表状态缓存,可以把三者放进同一个组件壳层。这个写法更接近真实业务页,也最适合作为复制模板。 ```vue ``` 这三个能力可以独立使用,也可以像上面这样组合使用;它们都是非 breaking 增强,不要求业务方修改现有组件 API。 ### Selected record / detail workspace 当前 dev app 已经把“选中记录 -> detail workspace”这条链路接起来了:点击 table / kanban / gallery / timeline 中的条目,会把当前记录送入详情工作区,再由 `DetailLayout`、`PropPanel`、`CommentItem` 这组组件展示主内容、属性和活动记录。 这证明页面级方案已经具备“列表视图 + 选中态 + 详情工作区”的最小闭环,并且可以作为业务页面底座直接接入。 更完整的外部接入约定见 [`docs/DATABASE-VIEW-DETAIL-USAGE.md`](docs/DATABASE-VIEW-DETAIL-USAGE.md)。 ### `detailPresentation` / `density` 页面级方案在语义上继续收敛两个关键契约: - `detailPresentation`:用于描述详情工作区的呈现方式,默认思路是桌面端 `side-panel`、移动端 `sheet`。 - `density`:用于统一页面与表格的视觉密度语义,建议仅使用 `compact`、`standard`、`comfortable` 三档。 这两个契约的目标不是替换现有组件,而是让页面层把右侧工作区、行高密度和默认布局策略收成一致的入口语义。 ### 已支持 / 暂未支持 | 已支持 | 暂未支持 | |---|---| | `local/provider` 两种模式的页面壳层接入 | 真实 provider 数据闭环、权限与持久化策略 | | `normal / loading / empty / error` 四态透传 | 写操作的最终落库与回滚编排 | | `table / kanban / gallery / timeline` 多视图切换 | 可编辑 detail workspace 的最终保存、ACL、schema 管理后台 | | `search / filter / sort / group / save-view / load-view` 工具栏契约 | 远程视图保存、跨端同步与更重的页面编排 | | `schema + records + viewConfig` 数据驱动 | 业务应用侧自定义的 provider 适配层 | | `selected record -> detail workspace` 页面链路 | detail 编辑后的最终提交、乐观更新、冲突处理 | --- ## 组件一览 | 分类 | 组件 | |------|------| | **视图** | DataTable, KanbanBoard, GalleryView, GanttTimeline | | **AI 对话** | AiMessageList, AiMessageBubble, AiSender, AiThinking, AiStreamingCursor | | **仪表盘** | Dashboard, BarChart, PieChart, DoughnutChart, NumberCard | | **编辑器** | RichTextEditor, CodeBlock, ContentBlock | | **详情** | DetailLayout, PropPanel, CommentItem | | **工作区** | WorkspaceShell, WorkspaceDetailActionBar, WorkspaceDetailPreviewBlock, WorkspaceActivityFeed | | **表单** | FormDesigner, 10 种 Field 组件 | | **布局** | AppLayout, Sidebar, Navbar, SplitPane | | **通用** | Modal, Dialog, Toast, Tabs, Breadcrumb, MermaidChart, ContextMenu | --- ## 使用示例 ### KanbanBoard ```vue ``` `KanbanBoard` 现在支持高层 slot forwarding,可直接从 board 层定制列头和卡片内容: ```vue ``` 注意:当启用 `card-title / card-meta / card-tags` 这类自定义 card slot 时,`KanbanColumn` 会自动关闭虚拟滚动,避免卡片高度变化导致布局错位。 ### AI 聊天面板 ```vue ``` ### GanttTimeline ```vue ``` ### MermaidChart ```vue ``` ### DataTable ```vue ``` ### Toast 通知 ```ts import { useToast } from '@oneflowui/ui' const toast = useToast() toast.success('保存成功') toast.error('操作失败') ``` --- ## 本地开发 ```bash # 克隆仓库 git clone https://github.com/qixi54/oneui.git cd oneui # 安装依赖 pnpm install # 启动开发环境(端口 5174) pnpm dev # 类型检查 pnpm type-check # 运行测试 pnpm test # 构建 pnpm build ``` --- ## License MIT