# 界面重构与多用户认证 —— 设计提案(2026-09-30) 状态:**accepted(方向 + R2 范围)**——2026-09-30 用户裁定采用**方案 A 任务中心**;同日裁定认证阶段 2 改为**管理员发放制**:无自助注册,账号仅管理员(或 CLI 引导)创建并设定初始密码,创建后与重置后的首次登录均强制改密(§5.1 邮箱+自助注册方案作废)。R1 已实施:Dev 仓 `feature/task-sidebar-r1`(Core +pinned/archived、Backend 迁移 v9 与任务列表 API、Frontend TaskSidebar)。R2 已实施:Dev 仓 `feature/auth-admin-accounts`(Backend 迁移 v10 auth_accounts:users 密码/must_change/is_admin + sessions 表;`/api/auth/login|logout|password`、`/api/admin/users*`;argon2id;登录失败退避;中间件接受 Bearer 密钥或会话 cookie 且豁免静态与登录入口;CLI `user create|reset-password|list`;Frontend 登录页双 tab、强制改密门、用户管理弹层。验证:store/e2e 测试 + 无头全流程走查)。R4 已实施:`feature/visual-refresh-r4`(令牌 v2 + 线性图标集 + 全组件重造型)。**UI 能力平台已实施(2026-09-30 用户裁定:头像/卡片/设置页为系统基本能力,插件直接复用)**:`feature/ui-capability-platform`——Core 增 `avatar` 词表(UINode/UIAvatarSpec 含叠放组);@ui 入 Icon/Avatar(名字派色/语义色/状态点/叠放)/primitives(Btn/Input/Chip/EmptyState/SettingRow)/SettingsShell(侧导航设置外壳);UIRenderer 补齐 D28 七词表(progress/compare/tree/table/steps/tabs/timeline——此前仅类型声明、卡片内被静默丢弃);前端消费(消息头像列、设置中心上外壳、管理弹层头像);react 类型单副本钉扎(tsconfig paths,修 make frontend 双 @types/react 名义冲突)。owner:weichen。 前置:[界面交互底座](2026-09-30-ui-inbox-command-workspace.md)(D25–D33)、[双档存储、多租户与规模化](2026-09-30-dual-tier-storage-and-multitenancy.md)(D17–D24)。 配套 demo:`ui-redesign-demos/`(index.html 为入口,本地浏览器直接打开)。 --- ## 1. 背景与问题 用户对现有界面的判定(2026-09-30):**界面与交互设计不够好**。具体事实(对照 v0.1.0 截图与 `modules/frontend/src/components/ProjectNav.tsx`): 1. **创建入口分裂且错位**:新建项目在左上角 `nav-header` 的 ✚,新会话在左下角 `nav-footer` 的「+ 新会话」。两个高频动作一个在最上一个在最下,且都是小图标/文字按钮,无主次。 2. **项目树导航繁琐**:`ProjectNav` 只渲染 `currentProjectId` 的会话(`open && p.id === currentProjectId`),切项目才能看会话;项目折叠态与会话列表耦合,浏览成本高。 3. **无用户与租户界面**:系统定位是多用户、多租户(D17 已落 `users`/`api_keys` 表),但界面只有一个密钥输入登录门(`App.tsx LoginGate`),没有账户、身份、成员、租户切换的任何表面。 4. 视觉密度与专业度不足:emoji 图标(✚ ☰ ⚙ 📦 🤖)、无统一设计令牌,观感偏离"办公工作台"。 ## 2. ZCode 桌面端研究结论 研究对象:`github.com/zai-org/ZCode`(Apache-2.0,Electron 桌面 + Web + CLI/TUI 三形态)。证据为仓库源码与 `DESIGN.md`(以下文件路径均在该仓)。 ### 2.1 布局范式(`packages/ui/src/app-shell/WorkspaceShellLayout.tsx`) - 四区:**左侧栏(任务列表)+ 中栏会话 + 底部终端 + 右侧 Side Pane**(浏览器/子代理会话/工作流运行/工件,Tab 化)。 - 尺寸用 CSS 变量驱动(`--workspace-sidebar-width` 等),拖拽中只写变量不进 React state;宽度持久化 localStorage。 - 自动收起策略:窗口变窄(去抖 300ms)时若会话列 < 480px 收 Side Pane、< 360px 收侧栏;**只在窗口 resize 时触发**,避免把用户手动打开的面板又关回去。 - 侧栏隐藏时由 `DesktopTopOverlay` 浮出 New Task,保证创建入口永不丢失。 ### 2.2 侧栏组织(`packages/ui/src/WorkspaceSidebar.tsx` 等) - **顶部动作区**:第一颗按钮就是 **New Task**(带快捷键),随后是 Command Center 搜索(⌘K)、Automations、插件商店。创建入口在视觉与逻辑的**第一位**,不在角落。 - **任务列表四种组织模式**:`grouped`(自定义分组)/ `workspace`(按项目)/ `timeline`(按时间线)/ `archived`,pill 切换 + 过滤菜单(排序、归档)。项目是任务的**组织维度**,不是必须展开导航的树。 - **置顶区全局置顶**(`WorkspacePinnedTasksSection`:归档态也保持置顶区可见)。 - 任务行支持拖拽排序、分组展开态持久化、右键菜单(`TaskListItemContextMenu`)。 - **Footer = 账户区**:主题/语言、设置、用量与套餐徽章、**登录/登出与用户信息**(`WorkspaceSidebarFooter`)。 - 收起后变 52px 图标轨道(`WorkspaceSidebarCollapsedRail`)。 ### 2.3 会话头与中栏(`WorkspaceHeaderSections/`) - 中栏会话头:上下文路径(项目/目录)+ 最近活动时间 + 动作区;**无全局顶栏**(与我方 D26 一致)。 ### 2.4 设计系统(`DESIGN.md`) - 定位:"calm, dense, operational rather than decorative";桌面优先。 - 硬规则:统一 `text-ui-*` 字号阶(默认 14px);语义色只用于真实语义态;**所有等待确认类交互(提问/权限/计划批准)统一绿色确认**;圆角按嵌套层级递减(外 12 → 内 10/8/6);4px 间距基;高度克制(先靠背景对比与描边,不堆阴影)。 - 键盘优先:可聚焦、可见焦点、快捷键全程可触达(新建任务、⌘K、侧栏拖拽支持方向键步进 16px)。 ### 2.5 认证表面 - `login/LoginApiKeyForm.tsx`:API 密钥表单;`onboarding/`:首跑引导;OAuth 相关在 `root/` 与 `packages/web/src/auth/`。 ### 2.6 对本系统的可迁移结论 | ZCode 实践 | 迁移判据 | |---|---| | New Task 置顶 + 快捷键 + 隐藏侧栏时浮出 | 直接采纳:解决"创建入口分裂"这一首要痛点 | | 项目/时间线/分组/归档是列表的**视图模式** | 直接采纳:项目从"树"降为"组织维度",浏览免切项目 | | 侧栏 Footer 承载账户/租户/用量 | 直接采纳:多租户身份常驻但低噪声 | | 底部终端 + Side Pane Tab | 远期:我们的代理/工件已有 ⌘1–9 弹层(D25/R4),不重复建面 | | CSS 变量驱动分隔条、自动收起策略 | 实现层采纳(现有 divider 逻辑升级) | | 绿色统一确认 | 与 InlineConfirmCard 语义合并考虑 | ## 3. 设计原则(继承 + 新增) 继承界面五原则(D25–D33 提案 §1.2:中栏做空、消息是事件流卡片是状态对象、弹层是加速器、待办不沉没、确认留痕)与 D26(无全局顶栏)。新增: - **P6 单一主创建入口**:创建动作只有一个主按钮(新建任务=会话),其余创建(项目等)收进它的次级菜单或组织区的显式 +。位置固定在侧栏顶部第一位,快捷键 ⌘N。 - **P7 身份常驻**:用户(头像/名/租户/角色)常驻侧栏 Footer;一切跨租户资源不可见性由服务端保证(D18 不变)。 - **P8 组织即视图**:项目/时间线/归档是任务列表的切换视图,不改变数据模型(`conversations.project_id` 不变),切换是本端偏好。 ## 4. 三个方案 demo:`ui-redesign-demos/demo-a-task-centric.html` / `demo-b-activity-rail.html` / `demo-c-project-portal.html`(含明暗主题切换;方案 A 含完整交互演示)。 ### 方案 A:任务中心(ZCode 同构)——**推荐** ``` ┌────────────────────┬──────────────────────────────┬─────────────────┐ │ Agent-System │ [项目徽章] 会话标题 ⋯ │ 收件箱 2 │ │ [+ 新建任务 ⌘N ▾] │ 状态 · 模型 · 更新于 3 分钟前 │ [待办][全部] │ │ [🔍 搜索 ⌘K] ├──────────────────────────────┤ ⚠ 发布前确认 │ │ 组织 [项目|时间线] ⋯│ │ ▷ 记忆库索引 68% │ │ 📌 置顶 │ 消息流 + 内联确认卡 │ ✓ 周报已生成 │ │ ▾ 研发体系文档 (4) │ │ − 已确认(折叠) │ │ • 任务… ├──────────────────────────────┤─────────────────│ │ ▸ 真实模型测试 (2) │ [附件] 输入框… [发送] │ 代理 2 · 工件 5 │ │ 👤 weichen · 个人 │ │ │ │ 租户 ⚙ 🌓 │ │ │ └────────────────────┴──────────────────────────────┴─────────────────┘ ``` - **新建任务**(主按钮,split menu):默认在"当前项目上下文"建会话;▾ 展开新建项目/新建任务于指定项目/导入。解决入口分裂:一个位置、有主次、带快捷键。 - **组织切换**:按项目(分组可折叠,组头 hover 出「在此项目新建」)/ 按时间线(今天/昨天/本周)。置顶区恒在顶部;过滤菜单含归档视图与排序。 - 任务行:状态点(运行中/待我确认/空闲/已完成)+ 相对时间 + 所属项目徽章(时间线模式)。 - **Footer 账户区**:用户 chip(点头像弹账户菜单:信息/切换租户/API 密钥/退出)+ 设置 + 主题。 - 中栏头沿用 D26:项目徽章 + 会话标题 + 状态;右栏纯收件箱(D25 不变),底部快捷链接进 ⌘1–9 弹层。 - **优点**:创建/浏览/身份三大痛点一次解决;与 ZCode(以及 Linear/ChatGPT 侧栏)这类已验证范式同构;纯前端改造,不动数据模型。 - **代价**:需重写 `ProjectNav`(约一个组件的量)+ 新增账户菜单;左栏语义从"项目树"变为"任务列表",用户有一周适应期。 ### 方案 B:活动栏 + 上下文列表(VS Code 式) ``` ┌──┬─────────────────┬──────────────────────┬─────────────┐ │▣ │ 研发体系文档 ▾ │ 会话(同 A 中栏) │ 收件箱 │ │+│ [+ 新会话] │ │ │ │🔍│ ── 会话列表 │ │ │ │📭│ • … │ │ │ │🤖│ │ │ │ │📦│ │ │ │ │⚙ │ │ │ │ │👤│ │ │ │ └──┴─────────────────┴──────────────────────┴─────────────┘ ``` - 最左 48px 图标轨切换领域(任务/收件箱/代理/工件/设置/账户),第二栏随活动渲染列表。 - **优点**:导航可无限扩展(插件域友好);账户/设置有恒定图标位。 - **代价**:**创建仍是二级动作**(先选项目再新建),痛点 1 只部分解决;多一列常驻(1280px 屏占 6%);与 D25"代理/工件走弹层"重复建面。判定:适合域数量 ≥ 6 时再启用。 ### 方案 C:项目门户(Notion/Linear 式) ``` ┌──────────────┬────────────────────────────────┐ │ [+ 新项目] │ 研发体系文档 12 会话 · 3 运行│ │ ▸ 文档智能体 │ ┌─────┐┌─────┐┐─────┐ │ │ ▸ 记忆库建设 │ │会话卡││会话卡││ + 新│ │ │ ▸ 模型测试 │ └─────┘└─────┘└─────┘ │ │ 👤 weichen │ 点会话卡 → 进入对话视图 │ └──────────────┴────────────────────────────────┘ ``` - 项目是页面:首页是会话卡片网格 + 统计 + 项目内新建(入口在上下文中,最贴任务)。 - **优点**:项目级总览最好;新建会话离上下文最近。 - **代价**:对话-first 被破坏(打开高频会话多一跳);卡片网格信息密度低;与"中栏做空"张力最大。判定:适合项目数少(<10)且以交付物为中心的用法。 ### 对比与推荐 | 维度 | A 任务中心 | B 活动栏 | C 项目门户 | |---|---|---|---| | 解决创建入口分裂 | **完全** | 部分 | 部分(上下文内) | | 跨项目浏览 | **优(视图切换)** | 中 | 中 | | 身份/租户常驻 | **Footer 账户区** | 图标位 | Footer | | 与既有决策兼容(D25/D26/D31) | **完全** | 需调 D25 | 张力大 | | 改造量 | 中(左栏+账户菜单) | 大 | 大(含视图路由) | | 扩展性(未来插件域) | 中 | **优** | 中 | **推荐 A**,并以 A 的 Footer 账户区 + 账户菜单吸收 B 的"账户恒定入口"优点。B 的活动栏留作域数量增长后的演进项(远期不否决)。 ## 5. 多用户与多租户设计(认证阶段 2) demo:`ui-redesign-demos/demo-auth.html`(登录/注册/账户与租户三屏)。 ### 5.1 身份模型演进(延续 D17 编号段,新决策从 D34 起,本文只提案) - **阶段 1(现状,保留)**:API key(`ask_`)即身份,user 即租户 owner,嵌入式档默认关闭认证。 - **阶段 2(本设计)**: - `users` 增 `email`、`password_hash`(argon2id)、`status`;`organizations`(租户)与 `memberships`(user × org × role: owner/admin/member)分离——**user 不再天然等于租户**,一个用户可属多租户。 - 登录:邮箱 + 密码 → 服务端会话(`sessions` 表,HttpOnly+SameSite=Lax cookie,滑动过期);**API key 保留**为程序化访问凭证,挂到 user,权限同其成员角色。 - 阶段 1 过换路径:每个既有 owner user 自动建同名个人租户并设 owner;API key 归属不变。 - **SSE 认证升级**:会话 cookie 使 EventSource 同源自动携带,**移除 `?key=` URL 传钥**(消除 D17 §3 记录的日志泄露权衡);API key 客户端仍可用 header。 ### 5.2 界面表面 | 表面 | 内容 | |---|---| | 登录页 | 品牌 + 双 tab(访问密钥 / 邮箱密码)+ 注册入口;错误内联;宽屏右侧产品信息面板 | | 注册页 | 姓名/邮箱/密码/组织名(即建租户,成为 owner) | | 账户菜单(侧栏 Footer) | 头像、显示名、邮箱;当前租户 + 角色徽章;**切换租户**(多租户成员);API 密钥管理;偏好(主题/语言);退出 | | 成员管理(设置内) | 成员表(邮箱/角色/状态)、邀请(邮件链接或邀请码)、角色变更;仅 owner/admin 可见 | | 项目可见性(远期) | 项目级成员范围(默认租户内全员);跨租户访问仍一律 NotFound(D18) | ### 5.3 服务端边界(不变项) - 权威在执行端(baseline 硬边界 4):角色检查在服务端每路由执行,UI 只做可见性降级。 - 密码哈希 argon2id、会话 cookie HttpOnly;不引入第三方 OAuth(远期)。 - 限流沿用 D24 租户固定窗口;登录路由加 IP 级失败退避。 ## 6. 落地路线(裁定方向后另立实施提案,此处仅示意切分) | 期 | 内容 | 验收要点 | |---|---|---| | R1 | 左栏重构(方案 A 任务列表 + 新建任务 + 组织视图 + 置顶/归档)+ 设计令牌接入(modules/ui tokens.css) | 创建入口唯一性走查;对话完备性剧本不回退 | | R2 | 登录页 + 阶段 2 认证(orgs/memberships/sessions)+ 侧栏 Footer 账户区 + 迁移 | auth_e2e 扩容;`?key=` 移除后 SSE 全链路 | | R3 | 成员管理与邀请、租户切换、API 密钥管理页 | 角色负例(member 越权 NotFound) | | R4 | 视觉系统全面收敛(字号阶/语义色/圆角嵌套/绿色统一确认) | 明暗主题截图对比 + 密度走查 | ## 7. Demo 清单 | 文件 | 内容 | 交互 | |---|---|---| | `index.html` | 方案总览与链接、对比表 | — | | `demo-a-task-centric.html` | 方案 A 全应用 | 组织切换、新建菜单、账户菜单、收起轨道、主题、收件箱筛选 | | `demo-b-activity-rail.html` | 方案 B | 活动切换、二级列表 | | `demo-c-project-portal.html` | 方案 C | 项目切换、进入会话 | | `demo-auth.html` | 登录/注册/账户与租户 | 双 tab 登录、注册表单校验、账户菜单、成员管理 | demo 为静态设计稿(无后端),数据为演示数据;视觉规格(色板/字号/圆角)即 R4 设计令牌的目标值来源。 ## 8. 边界与不做 - 本提案不含实施;实施前须用户裁定方案(默认 A)与认证阶段 2 范围。 - 不做计费/套餐(Footer 用量区留位即可)、不做 SSO/OAuth、不做项目级 ACL(远期,见 5.2)。 - 中栏与右栏结构不在本次重构范围(D25/D26 已定且未被推翻);底部终端面板不做(我们非终端工作台)。 ## 9. 交付补记(2026-09-30 下午:消息顺序保真 + 工件文件管理) 用户验收 UI 能力平台后反馈四项,本轮修复(任务 feature/chat-order-artifact-files): 1. **消息顺序保真(新设计约定:渲染顺序 = 落库顺序)**。后端 llm.go 按时间交错落库 parts (text → tool_call → tool_result → artifact_ref → 下一轮 text…),前端曾按 `p.process` 布尔二分重排(过程全前置),工具调用脱离真实位置。修复:`groupParts` 只把"连续的"过程 部件就地聚成折叠块,内容部件原位保留;live 流式改为 `LiveState.parts` 按事件到达序维护 (artifact.created 即时上 chip)。该约定写入 UI 层默认要求:任何 parts 分组展示不得改变原始顺序。 2. **下载通道**。后端 `artifactContent` 始终回 `Content-Disposition`(默认 inline, `?download=1` → attachment,RFC 5987 filename* 支持中文名)+ Office/PDF 扩展名 MIME 表; 前端 chip / 工件面板行 / DocViewer 三处都有下载动作。 3. **工件面板 = 工作区文件管理**(浏览/显示/下载/回看/删除):搜索 + kind 过滤 + 上传 + 行内 预览/下载/删除(二次确认);DocViewer 重构为单层 OverlayHost(pdf 内嵌 iframe、 csv/json 等宽、二进制信息卡 + 下载 CTA);收件箱结果卡经 docBridge 可直接打开工件。 4. **设置界面级联修复**。SettingsShell 根元素同挂宿主 `.modal`,被后加载的宿主样式以同 特异性覆盖(column/860px)压坏左右布局——改为 `.modal.ui-settings-shell` 复合选择器 (0,2,0)免疫加载顺序;设置行统一 @ui SettingRow,保存按钮进固定 actions 底栏。 教训入库:**@ui 组件挂宿主通用类时,外壳样式必须用复合选择器高于宿主单类**。 验证:ui 37 + frontend 20 vitest 全绿;backend go test ./... 全绿(含 disposition/MIME 新测); Playwright 头链 12/12(mock 后端 + SQLite 直插交错 parts 探针消息): DOM 序 [text→process-collapse→text→artifact-chip]、设置外壳 computed flex-direction=row 且 侧栏/主区并排、?download=1 → attachment+RFC5987 文件名、面板工具栏/过滤/上传/行内下载。 docx 在线预览为非目标(下载为主);工作区文件即 artifacts(不新增 fs 工具/目录)。