# UI_SPEC.md —— 设计令牌与组件规格 > 版本 1.0 | 作者 PM | 本文件由 PM 独占写入,所有开发/测试 agent **只读** > > 唯一权威来源:`/Users/jerry/haiguji/plantai-agent-ui-design/plantai-agent-ui-prototype.html`(1380 行)及其规范性文档 `DESIGN.md`。 > **实现以本文件的令牌值为准,以 DESIGN.md 的规则为约束。两者冲突时以 DESIGN.md 的规则优先,但像素值以本文件为准。** > 前端实现时必须逐字复刻本文件列出的 CSS,不得自行"美化"。 --- ## 1. 设计令牌(`ui/src/styles/tokens.css`) ### 1.1 深色主题(默认)`[data-theme="dark"]` ```css --pa-canvas: #0A0A10; --pa-surface-1: #111119; --pa-surface-2: #161622; --pa-surface-3: #1C1C2A; --pa-raised: #202031; --pa-hairline: #23232F; --pa-hairline-strong: #33334A; --pa-ink: #F2F3F8; --pa-ink-muted: #A9ADC4; --pa-ink-subtle: #6B6F8B; --pa-code-bg: #0D0D16; --pa-user-bubble: linear-gradient(135deg, #2A2A3E, #1C1C2A); --pa-user-bubble-border: #33334A; --pa-glow-opacity: 1; --pa-aurora-opacity: 1; --pa-grid-dot: rgba(255,255,255,.035); --pa-scrim: rgba(10,10,16,.6); ``` ### 1.2 浅色主题 `[data-theme="light"]` ```css --pa-canvas: #F6F8FC; --pa-surface-1: #FFFFFF; --pa-surface-2: #F0F3FA; --pa-surface-3: #E9EDF7; --pa-raised: #FFFFFF; --pa-hairline: #E2E7F2; --pa-hairline-strong: #C9D2E8; --pa-ink: #16182A; --pa-ink-muted: #4C5268; --pa-ink-subtle: #9AA1B8; --pa-code-bg: #F1F4FB; --pa-user-bubble: linear-gradient(135deg, #E8ECFF, #F4FBFF); --pa-user-bubble-border: #C9D2E8; --pa-glow-opacity: .35; --pa-aurora-opacity: .08; --pa-grid-dot: rgba(22,24,42,.05); --pa-scrim: rgba(246,248,252,.6); ``` ### 1.3 双主题公共 ```css /* 品牌 */ --pa-g-from: #5E6AD2; --pa-g-to: #00D4FF; --pa-aux: #A78BFA; --pa-gradient: linear-gradient(135deg, var(--pa-g-from), var(--pa-g-to)); /* 语义色(只表状态,双主题通用) */ --pa-success: #2ED3A0; --pa-warning: #F5B85C; --pa-error: #FF5C7A; --pa-info: #5E9BFF; /* 相位五色(只用于流水线卡/相位徽章/底栏状态点) */ --pa-t-planning: #C0A8DD; --pa-t-execution: #9FBBE0; --pa-t-knowledge: #9FC9A2; --pa-t-validation: #DFA88F; --pa-t-done: #C08532; /* 字体 */ --pa-font-ui: 'SF Pro Display','SF Pro Text','PingFang SC','Helvetica Neue','Microsoft YaHei','Noto Sans SC',system-ui,sans-serif; --pa-font-mono: 'SF Mono',Menlo,'JetBrains Mono',Consolas,'Liberation Mono',monospace; /* 圆角 */ --pa-r-xs: 4px; --pa-r-sm: 6px; --pa-r-md: 8px; --pa-r-lg: 12px; --pa-r-xl: 16px; --pa-r-pill: 9999px; /* 缓动 */ --pa-ease: cubic-bezier(.4,0,.2,1); --pa-ease-out: cubic-bezier(.16,1,.3,1); --pa-ease-spring: cubic-bezier(.34,1.56,.64,1); /* 壳层尺寸 */ --topbar-h: 48px; --statusbar-h: 28px; ``` ### 1.4 硬编码值(token 之外的合法常量) | 用途 | 值 | |---|---| | 热图 8 级色板 | `#0D0D16, #1E2A5E, #2B4AA8, #3B5FD0, #5E6AD2, #00A3E8, #00D4FF, #8DF0FF`(本项目图谱热力用途) | | 按钮白字 | `#fff` | | 辉光预设 | logo 点 `0 0 10px rgba(0,212,255,.7), 0 0 22px rgba(94,106,210,.5)`;按钮悬停 `0 0 24px rgba(0,212,255,.4)`;焦点输入 `0 0 14px~22px rgba(0,212,255,.16~.18)`;建议卡悬停 `0 0 18px rgba(0,212,255,.15)` | | 徽章 tint 底 | running `rgba(245,184,92,.12)`、done `rgba(46,211,160,.12)`、error `rgba(255,92,122,.12)` | | 相位色 tint | 工具图标 chip 底 `color-mix(in srgb, var(--pa-g-from) 16%, transparent)`,字色 `--pa-g-to` | ### 1.5 设计规则(DESIGN.md 约束,违反即缺陷) 1. **渐变克制**:渐变只允许出现在——Logo 文字、主按钮、活动会话高亮边、进度条填充、运行状态点、极光背景、焦点描边、表头下划线、chip/pill 激活态。正文与数据**永远是纯 ink 色**。 2. **层级靠表面阶梯 + 发丝线,不靠阴影**:静态卡片 1px `--pa-hairline` 描边;**glow 只属于状态类元素**(运行脉冲、悬停主按钮、焦点输入),静态卡片禁止发光。 3. **语义色只表状态**(成功/运行/失败),**相位色只表步骤归属**,两者互不混用。 4. **mono 只用于代码、终端、文件路径、数字与参数**;叙述性文字一律 font-ui。 5. **动效有目的**:动 = 状态。无装饰性漂浮弹跳。 6. **禁外链**:无 Google Fonts、无 CDN(DESIGN.md 硬性禁令,实验室可能离线)。 7. 状态表达三重编码:颜色 + 图标 + 文字。 --- ## 2. 动画规格(`ui/src/styles/animations.css`) | 动画 | 时长/缓动 | 用途 | 关键帧要点 | |---|---|---|---| | `pulse` | 2s infinite | running 状态点/徽章 | box-shadow `0 0 0 0 rgba(0,212,255,.5)` → `0 0 0 8px rgba(0,212,255,0)` → 0 | | `shimmer` | 1.8s infinite | 运行中卡片扫光、流式进度线 | `background-size:200%`,`background-position` 200%→-200% | | `blink` | 1s step-end infinite | 流式光标 | `50% { opacity: 0 }` | | `spin` | 1s linear infinite | running 相位 spinner | `rotate(360deg)` | | `sweep` | 2.4s infinite | 进度条高光带 | 同 shimmer 方向 | | `fade-slide` | .2s `--pa-ease-out` | tab 切换、工具卡展开体 | translateY(6px)→0 + opacity | | `msg-in` | .3s `--pa-ease-out` | 新消息入场 | translateY(8px)→0 + opacity | | `aurora-drift` | 16s ease-in-out infinite alternate | 背景光斑 | translate(-40px,30px) scale(1.08),blob.b 延迟 -8s | | 面板折叠 | .3s `--pa-ease-out` | 左右栏 grid-template-columns | — | | 主题图标 | .4s | 切换 rotate 180° | — | | hover lift | 200ms | 按钮 -1px、建议卡 -2px | — | **降级**:`@media (prefers-reduced-motion: reduce)` 下 `*` 全部 `animation:none; transition:none`。状态仍由静态符号(✓/●/◌/实心/空心)表达。 --- ## 3. 三栏外壳(Desktop ≥1280px) ``` grid: columns 260px minmax(0,1fr) 380px rows var(--topbar-h) minmax(0,1fr) var(--statusbar-h) areas "top top top" "side chat bench" "status status status" ``` - `.side-collapsed` → columns `64px minmax(0,1fr) 380px` - `.bench-collapsed` → columns `260px minmax(0,1fr) 28px` - body `overflow:hidden`,滚动在各栏内部 - `.aurora-bg` 固定层 z-index:0,pointer-events:none,两个光斑 560/620px + blur(120px) + 48px 点阵(顶部渐隐 mask) - 顶栏 `.top-bar`:`color-mix(in srgb, var(--pa-canvas) 88%, transparent)` + `backdrop-filter: blur(14px)` + 底部 hairline - 中栏 `.chat-inner` max-width 760px 居中,padding `28px 28px 12px` - 作曲器 `.composer-wrap` padding `4px 28px 14px`,`.composer` max-width 760px ### 折叠把手 - 左栏折叠把手:26×26px 圆角按钮,悬浮在左栏底部(bottom 40px),hairline 描边,chevron 左指;展开后图标方向反转 - 右栏折叠把手条:28px 宽竖条,内嵌 chevron;折叠时 chevron rotate 180° --- ## 4. 组件规格(每个组件精确的 CSS 关键值) ### 4.1 顶栏与徽章 | 组件 | 规格 | |---|---| | `.logo-dot` | 9px 圆点,渐变底,双辉光 | | `.logo-text` | 15px/700/ls .2px,`linear-gradient(90deg, from, to)` + `background-clip:text` | | `.icon-btn` | 30×30px r-md,ink-muted → hover ink + surface-2 | | `.top-title` | 居中,13.5px/600,ellipsis | | `.badge` | pill(r-pill,padding 2px 10px),11px/500/ls .5px,6px dot + 文字;四态见 PRD §2.1,`.running` 的 dot 带 pulse | ### 4.2 会话列表 | 组件 | 规格 | |---|---| | `.new-task-btn` | 40px 高,r-md,渐变底,白字 14px/600;hover 辉光 + -1px lift | | `.search-box` | 34px 高,surface-2 + hairline;focus-within 渐变描边(double-bg 技巧)+ `0 0 14px rgba(0,212,255,.18)` | | `.group-label` | 11px/500/ls .6px,ink-subtle,padding `10px 6px 5px` | | `.session-item` | padding 8px 10px,r-md,透明边;hover surface-2;active 时 左 2px 渐变条(`left:-10px`)+ `color-mix(g-to 8%)` 底 + `22%` 描边 | | `.status-dot` | 8px;running=`--pa-g-to`+pulse,done=success,error=error,idle=空心 1.5px ink-subtle | | 标题 | 13px/500 ellipsis;meta 11px ink-subtle ellipsis | ### 4.3 对话区 | 组件 | 规格 | |---|---| | `.empty-state` | 顶部 9vh;hero-dot 46px r-14 渐变底 ✧,双辉光;h1 28px/600/ls-.4px,ink→ink-muted 渐变字;副标题 14px ink-muted | | `.suggest-card` | 3 列 grid gap 12px;padding 15px,r-lg;hover -2px lift + 渐变描边 + 青色辉光;icon 16px、name 13.5px/600、desc 12px | | `.msg.user .bubble` | 右对齐 max-width 70%,user-bubble 渐变 + border,r-lg,padding 10px 15px,14px | | `.msg.assistant` | 无底色;padding-left 14px;左缘 2px 透明竖线 hover 变渐变 | | `.msg-head` | 24px 渐变头像 r-8 白 ✦ + 名字 12.5px/600 + 时间 11.5px ink-subtle | | `.md-table` | surface-1 + hairline,r-md;thead th 12px/600 surface-3 底 + **2px 渐变下边框**(`border-image: var(--pa-gradient) 1`);数据格 13px,**表头非「说明」的列 mono 12.5px** | | `.code-block` | code-bg + hairline r-md,mono 12.5px lh 1.7,pre-wrap,色 ink-muted | | `.stream-cursor` | 8×15px 青色块,blink 1s;`.shimmer-line` 3px 高 surface-3 轨道 + 青色扫光 | ### 4.4 流水线卡(`pipeline-card`,RAG 域改为「检索流水线」五相位) | 元素 | 规格 | |---|---| | 卡体 | surface-1 + hairline,r-lg,padding 14px 16px,margin 14px 0 | | 头部 | 「⚙ 检索流水线」12.5px/600/ls .3px + 整体语义色徽章 | | 步骤 | 每步 padding 7px 0,gap 10px;步骤间左侧 2px hairline 连接线(left 7px) | | 状态点 | 16px 圆,done=`--pa-t-done` 底白 ✓;running=对应相位色底 ● + pulse;waiting=surface-3 底 + 1.5px hairline-strong 边 ◌ | | 相位名 | 13px,宽 84px 固定 | | 描述 | 12px ink-muted,ellipsis | | 状态文字 | 12px/600;done 金、running 相位色 + 11px spin 环、waiting ink-subtle 400 | 注意:原型的 running 点颜色是执行蓝;RAG 版按 PRD FR-CHAT-009 的相位色表——**当前相位的点与字用该相位的 `--pa-t-*` 色**。 ### 4.5 阶段卡(原型 `tool-card` 的 RAG 化,见 PRD FR-RETRIEVAL) | 元素 | 规格 | |---|---| | 卡体 | surface-1 + hairline,r-lg,overflow hidden;running 时叠加 shimmer 扫光层(`rgba(0,212,255,.05)` 斜扫) | | 头部 | padding 10px 14px;图标 chip 22px r-7(g-from 16% tint 底,g-to 字色);名称 13.5px/600 ellipsis;状态徽章;mono 耗时 11.5px;chevron 展开 rotate 90° | | 展开体 | 顶部 hairline 分隔,padding 11px 14px 13px,fade-slide 入场;`tb-label` 11px/ls .5px;`tb-params` mono 12.5px 青色 code-bg r-sm;`tb-result` 13px 数值 mono success;`tb-log` mono 11.5px lh1.8 code-bg,max-height 130px 滚动,`.log-ok` success / `.log-run` 青色 | ### 4.6 作曲器 | 元素 | 规格 | |---|---| | `.composer` | r-xl surface-1 + hairline,padding 12px;focus-within 渐变描边 + `0 0 22px rgba(0,212,255,.16)` | | `.mode-pill` | r-pill,padding 4px 12px,12px/500;默认 hairline + ink-muted;`.on` 渐变底白字 + `0 0 12px rgba(0,212,255,.3)` | | textarea | 透明无边框 14px/1.6,min-height 46px,max-height 160px 内滚;placeholder ink-subtle | | `.send-btn` | r-md,padding 7px 18px,渐变底白字 13px/600;hover 辉光 + -1px;disabled opacity .45 无辉光 | ### 4.7 右工作台 | 组件 | 规格 | |---|---| | `.bench-tabs` | padding 10px 14px 0,底部 hairline;tab 13px/500 ink-muted,`.on` 13px/600 ink + **底部 2px 渐变下划线**(fade-slide 入场) | | `.bench-body` | padding 14px,滚动;`.tab-pane` fade-slide | | `.chip` | r-pill padding 3px 11px,11.5px;`.on` 实心 `#5E6AD2` 底白字 | | `.file-tree`(来源列表沿用) | mono 12.5px;条目 padding 6px 8px r-sm;hover surface-2 并显示 `.ft-dl`(opacity 0→1);目录名 g-to 色 600 | | `.prog-item` | 名称 13px/600 + mono 百分比(100% 转 success);轨道 6px r-3 surface-3;填充渐变 + `sweep`;`.full` 纯 success 停扫光 | | `.preview-block` | surface-1 + hairline r-lg padding 12px;标题 12px/600 | ### 4.8 底部状态栏 28px 高,surface-1 + 顶部 hairline,padding 0 14px,11.5px ink-subtle。 左:4 个 `.agent-dot-item`(7px 点 + 名):默认 surface-3 底 + 1.5px hairline-strong 边;`.running` = 相位色 + pulse;`.done` = success;`.error` = error。**RAG 版四个点名为:规划 / 检索 / 证据 / 生成**(对应 PRD FR-CHAT-009 前四相位;完成相位不进底栏)。 右:`PlantAI RAG v0.1` + mono QA 版本 + mono 会话数。 --- ## 5. 四档响应式(`ui/src/styles/responsive.css`,覆盖 §3) | 档位 | 规则 | 具体行为 | |---|---|---| | Desktop ≥1280px | 无覆盖 | 完整三栏,见 §3 | | Laptop 1024–1279px | `@media (max-width: 1279px) and (min-width: 1024px)` | 左栏强制 `side-collapsed`(64px 轨);右栏列宽 340px | | Tablet 768–1023px | `@media (max-width: 1023px) and (min-width: 768px)` | 单栏:`.app-shell` columns `minmax(0,1fr)`;左栏变**左抽屉**(fixed,260px 宽,translateX 滑入 + scrim);右栏变**右抽屉**;顶栏出现汉堡按钮与工作台按钮(工作台按钮带来源数角标);底栏保留 | | Mobile <768px | `@media (max-width: 767px)` | 顶栏 = 汉堡 + 标题 + 工作台按钮;工作台为**全屏覆盖层**(顶部 tab 条);底栏隐藏;顶栏显示一枚聚合状态点;aurora 光斑 `--pa-aurora-opacity: 0` | 移动端专项(全部实现,见 PRD §12.2):安全区 `env(safe-area-inset-*)`;textarea 16px 字号;`@media (hover: hover)` 包裹全部悬停态;<768px 交互目标 min-height 44px;`100dvh` + `100vh` 回退;`visualViewport` 键盘适配;`md-table` 横向滚动容器 + 边缘渐隐;图谱节点上限 30。 抽屉组件(B1 负责):`.drawer-scrim`(fixed inset 0,`--pa-scrim`,fade-in)+ `.drawer`(fixed,宽 300px max,transform 滑入 300ms `--pa-ease-out`)。Esc 或点击 scrim 关闭。焦点进入抽屉时锁定 Tab 焦点在抽屉内,关闭后归还。 --- ## 6. 主题初始化顺序(防止闪白) `index.html` 中 `` 硬编码;`main.js` 中在 `createApp` **之前**同步执行: ```js const t = localStorage.getItem('pa-theme'); if (t === 'light' || t === 'dark') document.documentElement.dataset.theme = t; ``` 此后才挂载应用。theme store 仅管理运行时切换。 --- ## 7. 组件类名复用约定 B2/B3 组件必须复用 B1 在 `styles/base.css` 与原型中定义的类名,**不得另起炉灶**:`app-shell`、`top-bar`、`logo`、`badge`、`session-panel`、`session-item`、`status-dot`、`chat-panel`、`msg`、`bubble`、`msg-head`、`agent-avatar`、`md-table`、`code-block`、`pipeline-card`、`p-step`、`tool-card`、`stream-wrap`、`stream-text`、`stream-cursor`、`shimmer-line`、`composer`、`mode-pill`、`send-btn`、`bench-panel`、`bench-tabs`、`bench-tab`、`chip`、`ft-item`、`prog-item`、`prog-track`、`prog-fill`、`preview-block`、`status-bar`、`agent-dot-item`、`drawer`、`drawer-scrim`。 --- ## 8. 生信流程编排组件规格(FR-BIO,BioFlow) 通用纪律:全部使用现有 `--pa-*` 令牌;新类名集中声明(§8.7);前端逐字复刻本节 CSS 关键值,不得自行美化;深浅主题由令牌自动适配。 ### 8.1 路径选择卡(`flow-path-card`) | 元素 | 规格 | |---|---| | 卡体 | surface-1 + hairline,r-lg,padding 14px 16px,margin 14px 0 | | 标题 | 「🧬 分析路径选择」12.5px/600/ls .3px | | 候选路径行 | 每行 padding 8px 10px,r-md,hover surface-3;行内阶段序列 12px ink-muted,首阶段加粗 ink | | 选中态 | 行 border 1.5px `--pa-g-from` + 背景 `color-mix(in srgb, var(--pa-g-from) 8%, transparent)` | | 确认按钮 | 「确认此路径」`--pa-gradient` 底白字 12.5px/600,r-md padding 7px 14px;无选中时禁用(opacity .45) | ### 8.2 参数表单卡(`flow-form-card`) | 元素 | 规格 | |---|---| | 卡体 | 同 8.1 | | 标题 | 「⚙ XXXX 步骤 · 可调整参数」12.5px/600/ls .3px | | 字段行 | label 12px ink-muted 宽 96px 固定;input surface-1 + hairline,r-sm,padding 6px 10px,focus border `--pa-g-from` | | 来源标注 | 每字段下方 11px ink-subtle(如「默认值来源:阶段契约文档」) | | 继续按钮 | 「继续」`--pa-gradient` 白字 12.5px/600,r-md padding 7px 16px | | 自动连续开关 | 「自动连续执行」12px ink-muted + 现有 switch 样式(`mode-pill` 同款开关) | ### 8.3 文件引导卡(`flow-file-card`) | 元素 | 规格 | |---|---| | 卡体 | 同 8.1 | | 拖放区 | border 2px dashed `--pa-hairline-strong`,r-lg,padding 24px,居中提示 12px ink-subtle | | 拖入态 | border-color `color-mix(in srgb, var(--pa-g-from) 45%, transparent)` + 背景 `color-mix(in srgb, var(--pa-g-from) 8%, transparent)` | | 进度条 | 复用 `prog-track`/`prog-fill`(track surface-2 r-pill 高 4px;fill `--pa-gradient`),旁注百分比 11px mono | | 路径输入行 | input 同 8.2 + 「登记路径」pane-btn 同款 12px | ### 8.4 阶段进度卡(`bioflow-progress-card`) 结构/状态点/连接线/相位色**复用 §4.4 pipeline-card 全部令牌**(done=`--pa-t-done` 底白 ✓、running=相位色底 ● + pulse、waiting=surface-3 底 ◌);新增两态与附加区: | 元素 | 规格 | |---|---| | failed 态 | `--pa-error` 底 ✕,状态文字 error 色 12px/600 | | skipped 态 | `--pa-ink-subtle` 底 ◌,状态文字 ink-subtle | | 日志尾区 | 仅 running/failed 阶段展开:`--pa-code-bg` 底,mono 11px,padding 8px 10px,max-height 96px 滚动,随 SSE 追加 | | 三选一按钮 | 仅 failed:重跑/跳过/改参数重跑,pane-btn 同款 12px,gap 8px | | 折叠 | 阶段 >10 自动分组折叠(组头 12px/600 + 展开箭头),默认展开运行中所在组 | ### 8.5 存档提示卡(`flow-archive-card`) | 元素 | 规格 | |---|---| | 卡体 | 同 8.1 | | 文案 | 「本次生信任务已完成,是否存档?可按你的要求命名并描述」12.5px | | 输入 | 名称输入行同 8.2 input | | 按钮 | 「存档」`--pa-gradient` 12.5px/600;「放弃」pane-btn 同款 12px | ### 8.6 面板(`biojobs-pane` / `bioarchive-pane`) | 元素 | 规格 | |---|---| | 面板容器 | 复用 bench 面板容器(§4.7),TAB 走现有 `bench-tab` | | 列表项 | 复用 `session-item` 形态:标题 13px + 状态徽章(同 §4.2) | | 阶段 DAG | 纵向 2px hairline 连接线(同 §4.4 连接线令牌),节点 8px 圆点按阶段状态取色 | | manifest/日志 | 复用 `code-block`(mono 12px,code-bg,滚动) | | 操作按钮 | pane-btn 同款(重跑/删除/复用发起) | ### 8.7 生信类名复用约定(在 §7 清单上追加) `flow-path-card`、`flow-form-card`、`flow-file-card`、`bioflow-progress-card`、`flow-archive-card`、`biojobs-pane`、`bioarchive-pane`。其余(按钮/输入/进度条/徽章/面板容器)一律复用 §7 既有类名,不得另起炉灶。