- git mv 保留历史:ui/(Vue3+Vite)、sdk/(BFF 中间层)
- 路径语义修正:db_path/figures_cache 改相对 sdk/(BFF cwd),
历史库 sdk/backend/data 迁移至 sdk/data/(会话/图片缓存无损)
- 引用修复 ~15 处:config.py、deploy/*.sh、vitest/playwright 配置、
单测导入路径、docs、README、gitignore、.env.example
- 骨架:agent/{qa,methodology,legacy-rag,vendor}、knowledge/manifest.yaml、
tooling/{compile,kb,crypto,assemble,audit,tools,scripts} + README
- 门禁验证:sdk pytest 125 通过、ui vitest 158 通过、
生产 BFF 脚本重启四上游全绿 + 静态托管 + 会话库无损
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
15 KiB
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"]
--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"]
--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 双主题公共
/* 品牌 */
--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 约束,违反即缺陷)
- 渐变克制:渐变只允许出现在——Logo 文字、主按钮、活动会话高亮边、进度条填充、运行状态点、极光背景、焦点描边、表头下划线、chip/pill 激活态。正文与数据永远是纯 ink 色。
- 层级靠表面阶梯 + 发丝线,不靠阴影:静态卡片 1px
--pa-hairline描边;glow 只属于状态类元素(运行脉冲、悬停主按钮、焦点输入),静态卡片禁止发光。 - 语义色只表状态(成功/运行/失败),相位色只表步骤归属,两者互不混用。
- mono 只用于代码、终端、文件路径、数字与参数;叙述性文字一律 font-ui。
- 动效有目的:动 = 状态。无装饰性漂浮弹跳。
- 禁外链:无 Google Fonts、无 CDN(DESIGN.md 硬性禁令,实验室可能离线)。
- 状态表达三重编码:颜色 + 图标 + 文字。
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→ columns64px minmax(0,1fr) 380px.bench-collapsed→ columns260px 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-innermax-width 760px 居中,padding28px 28px 12px - 作曲器
.composer-wrappadding4px 28px 14px,.composermax-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 中 <html data-theme="dark"> 硬编码;main.js 中在 createApp 之前同步执行:
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。