跳转到内容
OmniRoute source

OmniRoute — Design System & Visual Identity (中文 (简体))

营销网站(viral.omniroute.online、why.omniroute.online、omniroute.online)和产品仪表板应该看起来像同一个产品。网站已经从仪表板借用了其调色板 — 其 css/tokens.css 甚至写着 “调色板与 OmniRoute 仪表板(src/app/globals.css)保持一致”。因此,两者在颜色层面已经约有 80% 保持一致。仪表板目前缺少的是:

  1. 网站在每个页面中使用的方格纸网格壁纸。
  2. 网站已具备但仪表板缺少的一些共享设计 token(圆角比例、品牌渐变、surface-2、等宽字体)。
  3. 组件级一致性 — 一些仪表板组件使用硬编码的十六进制值/rgba,绕过了主题 token。

本文档包含相关分析和实施计划。


  • 唯一事实来源 = src/app/globals.css。 网站应与仪表板保持同步,绝不能反过来。新 token 必须首先添加到 globals.css。
  • 只用 token,不用字面量。 组件使用语义化 token(bg-surface、text-primary、border-border),绝不直接使用原始 #hex。
  • 低调,而非张扬。 网格是位于内容背后的淡化壁纸 — 它绝不能降低文本对比度,也不能干扰 UI。
  • 感知主题。 所有内容在 .dark(产品的标志性外观)和浅色主题下均可正常使用。
  • 渐进式发布。 先发布网格和 token(低风险、高可见度),然后分批清理组件。

3. 当前状态 — 已经对齐与尚未对齐的部分

Section titled “3. 当前状态 — 已经对齐与尚未对齐的部分”

每种品牌颜色和表面颜色在值层面均已与网站匹配(只有名称不同 — 仪表板使用 --color- 前缀)。已在 src/app/globals.css:30-128 中验证:

概念 网站 token(tokens.css) 仪表板 token(globals.css) 匹配情况
主色 --primary #e54d5e --color-primary #e54d5e ✅
主色悬停态 --primary-hover #c93d4e --color-primary-hover #c93d4e ✅
强调色 --accent #6366f1 --color-accent #6366f1 ✅
强调色 2 --accent-2 #8b5cf6 --color-accent-hover #8b5cf6 ✅(已重命名)
强调色 3 --accent-3 #a855f7 --color-accent-light #a855f7 ✅(已重命名)
成功 / 警告 / 错误 #22c55e / #f59e0b / #ef4444 完全相同 ✅
交通灯 #ff5f56 / #ffbd2e / #27c93f 完全相同 ✅
深色背景 / 表面 / 边框 #0b0e14 / #161b22 / rgba(255,255,255,.08) 完全相同 ✅
浅色背景 / 表面 / 文本 #f9f9fb / #fff / #1a1a2e 完全相同 ✅

结论: 无需进行颜色迁移。视觉形象已经统一;我们是在对其进行_完善_,而不是重新构建。

差异 站点现状 仪表盘现状 操作
网格壁纸 body::before 方格纸效果、--grid-line、--grid-size 32px、--section-alt ✅ 已添加(Phase 1) Part A
圆角尺度 --radius 14px、--radius-sm 9px 已添加 --radius 14px;-sm + 组件重新映射待完成 Part B / Phase 2
品牌渐变 --grad-brand 135deg primary→accent-3 ✅ 已添加令牌(Phase 1);将在 Phase 2 中使用 Part B
嵌套表面 --surface-2 #1c2230 ✅ 已添加(Phase 1) Part B
等宽字体 --font-mono(ui-monospace 字体栈) 待完成(Phase 4,与使用方一并处理) Part B
text-muted(深色) #8b8b9e #a1a1aa(zinc-400) 协调统一 — Part B

3.3 主题机制(确保不破坏任何功能)

Section titled “3.3 主题机制(确保不破坏任何功能)”
  • Tailwind v4,CSS 优先(无 tailwind.config.*)。令牌在 :root/.dark 中定义,并通过 @theme inline 暴露给工具类(globals.css:130-179)。
  • 通过 <html> 上的 .dark 类启用深色模式(globals.css:22 中的 @custom-variant dark),由自定义 Zustand store(src/store/themeStore.ts)切换,默认主题 = system(src/shared/constants/appConfig.ts:11)。站点改用 html[data-theme="light"]——两种机制不同,但彼此不会相交(来源相互独立),因此不存在冲突。我们保留仪表盘的 .dark 机制。
  • 支持运行时覆盖主色(themeStore.ts:85-97,预设位于 COLOR_THEMES)——用户可以替换 --color-primary。任何引用 --color-primary 的新令牌(渐变等)都会自动继承这些覆盖。✅
  • Tailwind v4 保留的圆角名称:--radius-sm/md/lg/... 是 rounded-* 工具类的底层变量。重新定义它们会追溯性地改变所有现有的 rounded-*(例如,rounded-sm 在 12 个文件中使用)。因此,小圆角值和组件重新映射有意推迟到 Phase 2,届时会与使用方一起修改。

4. A 部分 — 方格纸网格背景(核心诉求)— 已实现(阶段 1)

Section titled “4. A 部分 — 方格纸网格背景(核心诉求)— 已实现(阶段 1)”

来自网站(_mono_repo/omnirouteSite/css/base.css)的完整实现方案:一个固定、覆盖整个视口的伪元素,绘制两个 1px 线性渐变,并以 z-index:-1 位于所有内容之后。

body::before {
content: "";
position: fixed;
inset: 0;
z-index: -1;
pointer-events: none;
background-image:
linear-gradient(to right, var(--grid-line) 1px, transparent 1px),
linear-gradient(to bottom, var(--grid-line) 1px, transparent 1px);
background-size: var(--grid-size) var(--grid-size);
}

**为什么即使 body 设置了不透明的 background-color,这种方式仍然有效:**带有 z-index:-1 的 ::before 会绘制在元素自身背景的_上方_,但位于其正常文档流内容的_下方_。因此,--color-bg 作为基础填充色,网格叠加在其上,而应用内容则渲染在网格上方。

src/app/landing/page.tsx:16-26 已经在单个页面中实现了相同的网格——但使用的是红色线条(#E54D5E,不透明度 0.06),网格尺寸为 50px,并带有动态光球。因此,这种模式已经在产品中得到验证;本项工作会将其提升为全局、主题感知的壁纸。

4.3 新增的令牌(位于 globals.css)

Section titled “4.3 新增的令牌(位于 globals.css)”
:root {
/* 浅色主题——相较网站使用的 0.045,提高了网格不透明度,从而确保壁纸
在内容密集的仪表板中确实可见(卡片和界面框架覆盖了视口的大部分区域) */
--grid-line: rgba(0, 0, 0, 0.07);
--grid-size: 32px;
--section-alt: rgba(0, 0, 0, 0.022);
}
.dark {
/* 深色主题——出于相同原因,从 0.035 调高 */
--grid-line: rgba(255, 255, 255, 0.06);
--section-alt: rgba(255, 255, 255, 0.018);
}

该网格天然是全局的(它会一次性覆盖面板、auth/login、错误页面——即所有路由)。面板中恰好有一个元素遮住了它:

  • src/shared/components/layouts/DashboardLayout.tsx——最外层包装器绘制了不透明的 bg-bg。其下方的所有元素本来就已经是透明的(<main>、滚动容器、内部的 max-w-7xl),因此移除 bg-bg 后,body 网格便可透过内容区域显示出来(body 的 --color-bg 仍作为基础填充色)。

    <div className="flex h-dvh min-h-0 w-full overflow-hidden bg-bg">
    <div className="flex h-dvh min-h-0 w-full overflow-hidden">

4.5 界面框架交互(侧边栏 / 顶栏)

Section titled “4.5 界面框架交互(侧边栏 / 顶栏)”
  • Header(Header.tsx:207,bg-bg)和 Sidebar(Sidebar.tsx:430,bg-sidebar)保持不透明 → 网格仅显示在内容区域中,并由纯色界面框架包围。默认效果克制沉稳,与网站将界面框架和画布分隔开的方式一致(决策 D3 = 纯色)。

这些页面直接渲染在 &lt;body&gt; 下(没有面板界面框架),因此全局网格应自动显示在它们后面。**阶段 5 — 已完成:**这些独立的全屏包装器实际上是不透明的(min-h-screen … bg-bg,其中 bg-bg 与 &lt;body&gt; 使用相同的纯色填充),这会遮住所有非仪表板页面上的网格,而不只是登录页面。现在它们全部改为透明,以便显示共享壁纸:login、forgot-password、callback、maintenance、offline、status、terms、privacy、onboarding 和 ErrorPageScaffold(覆盖 400/401)。这完成了 D4(从仅限登录页面扩展到所有独立页面)。由 tests/unit/design-grid-background.test.ts 提供保障。

landing/page.tsx 保留其更丰富的动态背景(光球 + 暗角)——这是其专属的营销展示效果(决策 D5 = 保持不变)。


阶段 1 添加惰性的、无冲突的标识 Token(--surface-2/--color-surface-2、--grad-brand、--radius)。阶段 2 将圆角尺度接入 Tailwind 并重新指向组件;阶段 4 添加 --font-mono 及其使用方。

Token 原因 阶段
--radius / --radius-sm 使用统一的圆角尺度(14/9),而不是临时混用 6/8/12 1(值)/ 2(接入 + 重新指向)
--grad-brand 用于主要 CTA 的品牌渐变(红→紫),与站点保持一致 1(Token)/ 2(Button)
--surface-2 嵌套面板 / 表头 / 内嵌行 1
--font-mono 代码块、终端、ID、端点 4
--text-muted 协调 在站点↔面板之间选择一个值(推荐 #a1a1aa) 2

D2(text-muted):站点为 #8b8b9e,仪表板为 #a1a1aa。建议保留仪表板的 #a1a1aa,并更新_站点_以保持一致。这属于外观调整。


6. C 部分 — 组件标准化(阶段 2–4)

Section titled “6. C 部分 — 组件标准化(阶段 2–4)”

自定义组件(不使用 shadcn/Radix)、Tailwind v4,语义化 Token 大部分已采用(195 个文件导入共享桶文件)。工作重点是移除绕过机制。组件目录:src/shared/components/。

# 项目 文件 问题 → 目标 阶段
C1 圆角对齐 Button.tsx:14-18、Card.tsx:39、Modal.tsx、Input.tsx、Select.tsx 混用 6/8/12px → --radius/--radius-sm(14/9) 2
C2 按钮渐变 + accent 变体 Button.tsx:5-12 主要按钮是纯红→红;改为与 --grad-brand 对齐;添加缺失的 accent 变体。约 195 个导入方——可见度最高 2
C3 表格 DataTable.tsx:122-176、logTableStyles.ts、globals.css:405-414 100% 使用内联硬编码 rgba + 不存在的变量;迁移到 Token,并淘汰不一致的样式 3
C4 集中管理状态颜色 flow/edgeStyles.ts、TokenHealthBadge.tsx、DegradationBadge.tsx、ProviderCascadeNode.tsx、Badge.tsx + 5 个辅助模块 同一十六进制颜色有 6+ 份副本 → 基于 --color-success/warning/error 的单一模块 3
C5 卡片边框 Card.tsx:39 border-white/5 → 品牌色 /8 2
C6 协调焦点环 ✅ 已完成 globals.css 中的 --focus-ring(强调色)与表单控件的 ring-primary/30 统一为强调色(紫色),以匹配全局焦点环,并与红色错误环明确区分;错误状态仍为红色 4
C7 添加 Checkbox + Textarea 带有内联 accentColor:#6366f1 的原始 &lt;input&gt;/&lt;textarea&gt; Token 驱动的基础组件 4
C8 清理硬编码十六进制颜色 ConsoleLogViewer.tsx:240、ComboLiveStudio.tsx:306、Modal 圆点、约 14 个图表文件 字面值 → Token 4
C9 cn() → clsx + tailwind-merge src/shared/utils/cn.ts 冲突类会叠加;C1 覆盖需要此项 2

已符合品牌规范(由 Token 驱动,仅需调整圆角):Badge、Toggle、SegmentedControl、Input、Select。


  • 阶段 1 — 网格 + 品牌标识令牌(本 PR)。 globals.css 网格 + --surface-2/--grad-brand/--radius 令牌;body::before 壁纸;移除 bg-bg 阻碍项;静态防护测试。风险低,可通过一个提交回滚。
  • 阶段 2 — 基础组件(C1、C2、C5)— 已在本 PR 中完成。 通过 @theme 添加语义化圆角工具类 rounded-card (14px) / rounded-control (9px)(使用自定义名称,因此默认的 rounded-sm/md/lg/xl 保持不变——不会引发波及 400 个文件的大规模修改);Card/Modal → 14px,Button/Input/Select → 9px;Button 主按钮 → --grad-brand(红色→紫色)+ 新增 accent 变体;Card 边框 → border-border 令牌 (0.08)。已推迟: cn()→tailwind-merge (C9) 需要新增依赖;临时性的 rounded-lg 全面清理(326 个文件)维持原状,因为基础组件已覆盖大部分界面。
  • 阶段 3 — 状态颜色 + 表格(C3、C4)— 已在本 PR 中完成。 ✅ C4(src/shared/constants/statusColors.ts — 以 STATUS_HEX 作为单一来源;flow/edgeStyles.ts + TokenHealthBadge 已改为引用它,表现一致/十六进制值相同)。✅ --font-mono 令牌。✅ C3 (DataTable) — 使用一组 --table-* 令牌(--table-header-bg/-row-zebra/-row-hover/-cell-border/-row-selected)替换了所有内联 rgba,以及无效的 var(--bg-table-header) / var(--text-secondary) 回退值;其深色模式值与旧的硬编码 rgba 完全相同(深色模式逐字节一致),而浅色模式值修复了此前始终呈现深色的问题。表头边框 → --color-border,次要文本 → --color-text-muted。合并前需要进行一次视觉检查。(未触及:logTableStyles.ts 和旧版 Ant .ant-table 规则——这些将单独处理,优先级较低。)
  • 阶段 4 — 清理(C6、C7、C9 已完成;C8 待完成)。 ✅ C9 cn() → twMerge(clsx(...))(已将 clsx + tailwind-merge 添加为依赖)——调用方的 className 现在会正确地_替换_基础组件中冲突的类,而不是将它们叠加。✅ C7 新增 Checkbox + Textarea 基础组件(由令牌驱动,并从桶文件导出;属于增量添加——后续可逐步采用,以替换 32 个原生复选框 / 41 个原生文本区域)。✅ C6 焦点环协调——表单控件(Input/Select/Textarea/Toggle/Checkbox)现在聚焦时使用**强调色(紫色)**焦点环,以匹配全局 --focus-ring,并避免与红色错误环冲突;红色错误状态保持不变。⏳ C8 十六进制颜色清理并非盲目的查找/替换——已确认以下问题项是_有意如此_且必须保留:ConsoleLogViewer.tsx:240(始终为深色的终端)、TokenHealthBadge 弹出框、ReactFlow SVG 描边。仅迁移确实需要感知主题的十六进制颜色。

每个阶段:npm run lint + npm run typecheck:core + 一次视觉检查。


  • D1 — Button 主按钮: 保持红色→红色,还是切换为红色→紫色 --grad-brand?建议:红色→紫色(阶段 2)。
  • **D2 — 网格线颜色:**中性色(站点风格)——已选定——而非品牌红色。尺寸为 32px(根据负责人的反馈,相较原始的 46px 缩小约 30%——46px 的网格单元在仪表盘布局中显得过大)。
  • D3 — 界面框架鲜艳度: 侧边栏/页眉使用纯色——已选定。
  • D4 — 认证/登录网格: ✅ 已完成(阶段 5)——已从每个独立的全屏包装器中移除不透明的 bg-bg(而不只是登录页),因此所有屏幕上都能显示网格。参见 §4.6。
  • D5 — 落地页: 保持动画启动画面不变。已选定。
  • D6 — 全产品统一使用 14/9 圆角: 建议:是(阶段 2)。
  • D7 — 阶段 1 优先发布: 已选定。
  • D8 — 布局宽度(阶段 5): 仪表盘内容外壳此前限制为 max-w-7xl (1280px),导致其在大型显示器上居中显示,两侧留有较宽的空白边距。✅ 已完成——已提升为流式 max-w-[3840px](真正的 4K):内容现在会随视口扩展至约 4K,仅在超过该宽度后居中(DashboardLayout.tsx)。有意保持较窄的页面仍按设计维持窄幅(ProviderOnboardingWizard max-w-5xl,Rtk/CavemanContextPageClient max-w-6xl)。
  • D9 — 不透明数据表格(阶段 6): 仪表盘内容区域现已透明(因此网格壁纸可以透出,阶段 5),但若数据表格的容器不是不透明表面,网格就会透过其透明偶数行 / 低透明度斑马纹显示出来。✅ 已完成——现在所有不在卡片内的表格都会绘制 bg-surface(对于 <DataTable> 基础组件,则在其滚动容器上设置 background: var(--color-surface))。已修复:DataTable(基础组件)、ProxyLogger/RequestLoggerV2(其 <Card> 的 bg-black/5 dark:bg-black/20 色调通过 tailwind-merge 覆盖了 Card 的 bg-surface → 约 95% 透明)、BatchListTab/FilesListTab/CacheEntriesTab/ReasoningCacheTab/cache page/FreePoolTab/ModelMappingTable/HeaderTable,以及缓存视图中的两个 CSS 网格“表格”(bg-surface/35 → bg-surface)。经验证,已位于 <Card>/Modal 内的表格是不透明的,因此有意保持不变(在这些位置添加 bg-surface 只是无实际作用的冗余操作)。网格本身无需更改——仪表盘的 body::before 与站点逐字节一致(--grid-size: 32px);运行实例中出现的任何“更大网格”都是 #4143 之前的陈旧构建,而非代码问题。由 tests/unit/design-grid-background.test.ts 提供防护(阶段 6 区块)。

  • 不更改调色板 — 现有颜色已匹配;我们只补充缺失的令牌。产品不会出现重新着色的风险。
  • 不更改主题引擎 — 保留 .dark + Zustand store。
  • 圆角调整(阶段 2)影响范围广 — 会涉及每个卡片/按钮/输入框;合并前需目视检查内容繁多的界面(表格、模态框)。
  • **表格(C3)**包含最多的硬编码样式,回归风险范围也最大 — 应放在独立的 PR 中处理。

区域 路径
仪表板令牌 src/app/globals.css(:root、.dark、@theme inline、body、body::before)
主题 store src/store/themeStore.ts、src/shared/components/ThemeProvider.tsx、src/shared/constants/appConfig.ts:9-11
面板外壳(在此解除网格阻塞) src/shared/components/layouts/DashboardLayout.tsx
框架 UI src/shared/components/Header.tsx:207、src/shared/components/Sidebar.tsx:430
网格先例 src/app/landing/page.tsx:16-26
基础组件 src/shared/components/{Button,Card,Input,Select,Badge,Modal,Toggle,SegmentedControl,Loading,Tooltip,DataTable}.tsx
状态颜色来源 flow/edgeStyles.ts、TokenHealthBadge.tsx、DegradationBadge.tsx、logTableStyles.ts
cn 工具 src/shared/utils/cn.ts
阶段 1 防护测试 tests/unit/design-grid-background.test.ts
站点参考 _mono_repo/omnirouteSite/css/tokens.css、css/base.css

OmniRoute 源码 (a58000c7685f)

HagiCode

HagiCode 是一套智能体编码工作台:结构化工作流、多 Agent 并行执行与 Hero Dungeon 视图,把想法变成真正交付的软件。

让想法更快变成好用的软件,让智能编码更聪明、更高效,也更有趣。

HagiCode 浅色主题主界面截图
  • Smart结构化工作流将意图转化为从想法到交付的可执行路径。
  • Efficient多 Agent 工作流让调研、实现与审阅并行推进。
  • FunHero Dungeon 让长时间编码协作更直观、更有参与感。
访问 HagiCode