20 KiB
20 KiB
Legacy UI 规格说明(static/old_version_backup/前端备份)
目的:彻底记录旧版前端(
static/old_version_backup/前端备份/index.html + app.js + style.css)的 UI 结构、状态域、交互与 API,用于后续 Phase 3+ 全量重构时精准还原体验。下文所有字段/方法名称均沿用备份代码,方便对照实现。
全局运行环境
- 依赖加载:直接在
index.html通过 CDN/本地脚本注入 Vue 3(Vue.createApp)、Socket.IO 客户端、Marked、Prism、KaTeX,以及/static/security.js与彩蛋脚本 (/static/easter-eggs/*.js)。window.requestSocketToken、window.ensureCsrfToken来自后端脚本。 - 样式体系:单一
style.css使用大量 CSS 变量(--claude-*)打造“Claude 风”视觉;含左/右侧边栏、对话区、输入区、Toast、面板等所有样式。另挂载彩蛋专用 CSS(flood.css/snake.css)。 - 入口 DOM:整个应用被包裹在
<div id="app">中,通过 Vue 模板语法渲染;根节点同时承载 Toast/Confirm/Overlay/ContextMenu。 - 脚手架行为:页面加载时会执行
bootstrapApp()→ 确保 Vue/Socket.IO 存在 →createApp,并在window.load后挂载。Viewport 逻辑通过updateViewportHeightVar挂在window.visualViewport事件,CSS 使用--app-viewport控制高度。
状态域(app.js → data())
| 状态分组 | 关键字段 | 说明/用途 | 建议 Pinia Store |
|---|---|---|---|
| 连接 & 系统 | isConnected, socket, projectPath, agentVersion, thinkingMode, stopRequested |
管理 Socket.IO 生命周期、后端模式、思考/快速切换、Stop 指令等 | useConnectionStore / useSystemStore |
| 对话 & 消息 | messages, currentConversationId, currentConversationTitle, currentMessageIndex, streamingMessage, expandedBlocks, thinkingScrollLocks, autoScrollEnabled, userScrolling |
聊天历史、流式状态、思考块折叠、滚动锁、当前对话元信息 | useConversationStore + useChatStore |
| 面板布局 | sidebarCollapsed, leftWidth, rightWidth, rightCollapsed, isResizing, resizingPanel, panelMode, panelMenuOpen |
控制三个侧栏宽度/折叠及 Panel 切换 | useUiStore |
| 资源与统计 | tokenPanelCollapsed, currentContextTokens, currentConversationTokens, usageQuota, usageQuotaTimer, projectStorage, containerStatus, containerNetRate |
Token/Quota/容器与存储统计,含轮询定时器 | useResourceStore |
| Toast/Confirm/Quota | quotaToast, toastQueue, nextToastId, confirmDialog, pendingConfirmResolver |
全局通知与确认框 | useUiStore |
| 文件/待办/子智能体 | fileTree, expandedFolders, focusedFiles, todoList, subAgents, subAgentPollTimer |
侧栏三合一内容、聚焦文件、子智能体轮询 | useFileStore / useTaskStore / useSubAgentStore |
| 工具/快捷菜单 | toolMenuOpen, settingsOpen, quickMenuOpen, toolSettings, toolSettingsLoading, preparingTools, activeTools, toolActionIndex, toolStacks |
工具禁用菜单、Quick Menu、流式工具卡片状态 | useToolStore |
| 输入与上传 | inputMessage, inputLineCount, inputIsMultiline, inputIsFocused, uploading |
输入框动态高度、上传反馈 | useChatStore / useUploadStore |
| 个性化 | personalPageVisible, personalizationLoading, personalForm, tonePresets, newConsideration, personalizationStatus/Error 等 |
个人空间表单、拖拽排序、开关提示 | usePersonalizationStore |
| 其它 | contextMenu, easterEgg, icons, toolCategoryIcons, onDocumentClick/onWindowScroll/onKeydownListener |
文件树右键、彩蛋生命周期、全局事件清理 | useUiStore |
注意:
toolActionIndex在data()中被声明两次,后者覆盖前者;重构时可合并为单一 Map。
API & Socket 交互速览
- REST 拉取:
/api/files,/api/focused,/api/status,/api/todo-list,/api/sub_agents,/api/tool-settings,/api/usage,/api/project-storage,/api/container-status,/api/conversations,/api/conversations/<id>/load|messages|tokens|compress,/api/conversations/current,/api/upload,/api/download/file|folder,/api/personalization,/api/thinking-mode,/api/logout,/api/focus相关(通过工具块触发),/api/terminals(via 终端页面)。部分接口混用 GET/POST/PUT。 - Socket 通道:
ai_message_start|end,thinking_start|chunk|end,text_start|chunk|end,tool_preparing|status|start|result,tool_settings_updated,append_payload,modify_payload,system_message,quota_update|notice|exceeded,token_update,todo_updated, 子智能体/聚焦更新等。发送事件包括send_message,send_command,stop_task。 - 轮询:容器指标每 500ms,项目存储 5s,额度 60s,子智能体 5s(仅在 tab 打开时),Tool 设置按需拉取。
布局与模块
1. 对话历史侧边栏(.conversation-sidebar)
- 收起状态:仅露出三个纵向按钮(展开、开新对话、个人页面)。点击任意按钮会展开或进入个人页面。
- 展开后结构:
conversation-header:左侧“新建对话”主按钮、右侧“折叠”箭头;另有快捷按钮(加号、折叠/展开)。conversation-search:输入框绑定searchQuery,@input防抖 300ms 触发searchConversations(当前实现仅回退到全列表,保留 TODO)。conversation-list:显示加载态/空态/列表;条目包含标题、更新时间、消息/工具数量、删除/复制按钮(调用/api/conversations/<id>/delete|duplicate,逻辑位于methods);点击条目触发loadConversation。列表底部加载更多控制分页 (limit=20offset 递增)。conversation-personal-entry:打开“个人空间”。
- 路由策略:
bootstrapRoute根据window.location.pathname自动加载conv_<id>,history.pushState在切换对话后更新 URL,popstate监听需重载历史。
2. 三合一左侧面板(.left-sidebar)
- 状态卡:展示 Logo(
iconStyle('bot'))、agentVersion,thinkingMode标签(brain/zap图标切换),右侧连接状态圆点(connection-dot)。 - 面板卡:
- 顶部
panel-menu透视panelMode(files/todo/subAgents)。sidebar-view-toggle打开菜单,点击按钮selectPanelMode()并可cyclePanelMode()。 - 文件树(默认):递归组件
<file-node>,使用expandedFolders记住展开;右键触发contextMenu(下载文件/目录 ZIP)。点击文件节点 currently 仅选中 highlight(无 open 行为)。 - 待办:
todoList含instruction,tasks。任务展示标题、执行人与状态标记。 - 子智能体:
subAgents卡片显示agent_id,status,summary,last_tool;点击调用openSubAgent()生成 URL 并window.open。
- 顶部
- 拖拽手柄:
.resize-handle左侧@mousedown="startResize('left', $event)"控制leftWidth(350~600px)。
3. 聊天区域(.chat-container)
3.1 Token/Quota/资源抽屉(.token-drawer)
- 在
currentConversationId存在时显示,tokenPanelCollapsed控制折叠。 - 内容:
Token 统计:currentContextTokens,currentConversationTokens。性能统计:容器状态 pill + CPU/内存 + 宿主机占位提示。额度统计:显示常规模型/思考/搜索剩余额、自动格式化 reset 时间。资源统计:网络速率(containerNetRate)+ 项目存储用量(projectStorage)。
- 抽屉状态可通过 Quick Menu → 设置 → “用量统计”切换。
3.2 消息时间线(.chat-messages)
- 数据结构:
messages数组,元素为{ role: 'user'|'assistant'|'system', content, actions[] }。 - 渲染块:
- 用户消息:头像 + 气泡、背景框。
- 助手消息:每个
action渲染成折叠块(thinking/text/tool/append_payload/modify_payload/system)。thinking:带“正在思考”标题,自动滚动/折叠/锁定;thinkingScrollLocks确保块滚至底部,结束后 1s 自动折叠改名为“思考过程”。text:Markdown 渲染 +marked+Prism+KaTeX,支持copy code(copyCodeBlock()通过data-code-id/data-code属性工作)。tool:卡片包含工具名、图标(TOOL_ICON_MAP),参数快照/状态消息/结果(JSON、plain text、命令输出pre),流式时加 loading 条;action.tool.awaiting_content控制“等待正文”占位。工具status颜色区分preparing/running/completed/error。append_payload/modify_payload:专门显示文件路径、强制标志、成功/失败行数。system:用于role=system文本,折叠块system-message。
- 特殊处理:
renderHistoryMessages()会解析<think>块、自定义 metadata(append_payload,modify_payload),并避免 LLm 输出的<<<APPEND/<<<MODIFY>>>内容直接进入 UI。 - 滚动策略:
messagesArea的 scroll 事件更新userScrolling/autoScrollEnabled,scroll-lock-toggle按钮切换锁定;思考块单独监听scroll以保持 pinned 行为。
3.3 输入区(.compact-input-area)
- 结构:
stadium-shell包含隐藏<input type="file">、左侧+按钮、textarea、右侧发送/停止按钮。textarea支持Ctrl+Enter发送、根据内容自动扩高(最多 6 行,autoResizeInput计算 line-height)。 +按钮弹出quick-menu(点击外部关闭):上传文件→ 触发隐藏文件输入 →/api/upload→ Toast 队列显示进度、完成、失败;完成后刷新文件树。工具禁用→ 二级菜单罗列toolSettings(按分类 toggles, icon 由TOOL_CATEGORY_ICON_MAP指定)。禁用/启用通过 POST/api/tool-settings并即时刷新。思考/快速模式→ 切换thinkingMode(调用/api/thinking-mode)。设置二级菜单:实时终端→openRealtimeTerminal()新开/terminal。聚焦面板→ 切换右侧rightCollapsed。用量统计→ 切换 Token Drawer。压缩对话→ POST/api/conversations/<id>/compress,需确认框、compressing状态。
- 发送按钮:若
streamingMessage为真则显示 STOP 图标,点击调用stopTask(Socketstop_task)。发送前检查额度(isQuotaExceeded+quotaToast)。命令以/开头时走send_command。
4. 右侧聚焦面板(.right-sidebar)
- 默认折叠(
rightCollapsed = true),通过 Quick Menu → 设置或拖拽手柄展开。 - 内容:顶部标题 + “聚焦文件 (x/3)” 计数;
focusedFiles为{ path: { size, content } }。 - 每个 tab 展示文件名、大小(KB, 1 decimal)、
<pre><code>语法高亮(getLanguageClass基于拓展名)。无文件时显示“暂无聚焦文件”。
5. 个人空间(.personal-page-overlay)
- 从左侧最下方“个人页面”按钮或 Sidebar collapsed 图标进入,覆盖全屏(透明蒙层 + Card)。支持鼠标/触摸长按关闭(
handleOverlayPress*)。 - 表单字段:启用开关(即时 POST
/api/personalization,personalizationToggleUpdating防抖)、自称、称呼、职业、语气、Considerations 列表(拖拽排序 + 新增输入 + 预设语气 chips)。保存按钮提交/api/personalization(POST JSON)。 - 顶部按钮:退出登录(POST
/logout)与返回工作区。
6. 全局 Overlay/服务
- Quota Toast:置顶横幅
quota-toast显示额度提醒;showQuotaToast()控制。 - Toast Stack:
toastQueue通过<transition-group>渲染,支持自动消失/手动关闭。 - Confirm Dialog:
confirmDialog+handleConfirm用于危险操作。 - 上下文菜单:
contextMenu仅针对文件树节点(下载文件/文件夹)。 - Easter Egg Overlay:
easterEgg.active控制<div class="easter-egg-overlay">,Tooltrigger_easter_egg结果由handleEasterEggPayload->EasterEggRegistry播放,支持自动清理。
消息/工具渲染细节
- 助手消息结构:
ensureAssistantMessage()保证messages末尾存在role: 'assistant'且actions: [],之后所有流式事件都向该actionspush。 - 流式顺序:
ai_message_start新增消息 →thinking_start/chunk/end→text_start/chunk/end→ 多个工具事件(preparing/status/start/result/append_payload/modify_payload/system_message) →ai_message_end(重置currentMessageIndex,streamingMessage,stopRequested)。 - Tool Action:
action.tool包含id/name/status/statusDetail/result/arguments/argumentSnapshot/argumentLabel/message/executionId/awaiting_content。registerToolAction& Maps 用于后续 socket事件匹配。 - Append/Modify Payload:用于
append_to_file/modify_file工具响应,展示 path、强制写入 flag、影响行数/块数。 - System Block:
appendSystemAction插入“系统消息” collapsible。 - LaTeX:
renderLatexInRealtime()在text_chunk/text_end之后执行renderMathInElement。
文件/待办/聚焦/子智能体逻辑
- 文件树:
updateFileTree()将/api/files返回的嵌套结构转换为 nodes({ type: 'folder'|'file', name, path, children, annotation });右键@contextmenu记录 node 与鼠标位置,点击菜单按钮调用/api/download/file|folder。 - 聚焦文件:
/api/focused返回 { path -> { size, content } },显示/下载/滚动 purely 只读。工具focus_file/unfocus_file事件会触发focusedFiles刷新(applyStatusSnapshot/socket)。 - 待办:
/api/todo-list->this.todoList = { tasks: [], instruction };todo_updatedsocket 事件使 UI 立即同步。 - 子智能体:
/api/sub_agents+ 5s 轮询;openSubAgent构建 URL,优先window.SUB_AGENT_BASE_URL。状态 pill 颜色由 classagent.status控制。
Token/资源/Quota 面板行为
- token_update socket:仅处理当前对话 ID,一次更新
currentConversationTokens+currentContextTokens+usageQuota+quotaToast。 - 工具完成数:
updateCurrentContextTokens()在 Tool 完成/消息发送后延迟调用/api/conversations/<id>/tokens。 - 容器指标:
pollContainerStats()(未在片段展示)调用/api/container-status,updateContainerStatus()根据stats.timestamp/rx_bytes/tx_bytes计算containerNetRate(字节差 / 时间差)。 - 项目存储:
pollProjectStorage()->/api/project-storage,usage_percent/limit_label直接展示。 - 额度:
/api/usage->normalizeUsageQuota()-> Quick Menu, Toast, Token Drawer 共享;quota_notice/exceededsocket 触发顶部通知 + 立刻刷新额度。
快捷交互流程
- 加载流程:
mounted→bootstrapRoute()(解析 URL) →initSocket()(分配 token, 监听事件)→initScrollListener()→setTimeout(loadInitialData, 500)(并发加载文件树/聚焦/待办/状态/工具设置/对话 tokens)→start*Polling()。 - 发送消息:输入→
sendMessage()检查 quota → push 用户消息 →socket.emit('send_message', { message, conversation_id })→scrollToBottom→ 1s 后刷新 token。 - 停止任务:
streamingMessage+ Stop 按钮 →socket.emit('stop_task')。ai_message_end或text_end事件最终stopRequested = false。 - 上传:Quick Menu “上传文件” →
<input type=file>→/api/upload(FormData)→ Toast 过渡 +refreshFileTree()→ 出错时匹配错误文案(安全审核/禁用类型)。 - 对话切换:侧栏点击 →
/api/conversations/<id>/load(PUT)→resetAllStates()→fetchAndDisplayHistory()+fetchConversationTokenStatistics()+updateCurrentContextTokens()→history.pushState()。 - 个性化:打开个人空间 →
/api/personalizationGET → 表单编辑/拖拽/预设 → 保存 POST → 成功/失败提示;启用/停用走单独 API。 - 工具禁用:Quick Menu → Tool submenu → POST
/api/tool-settings→ UI 更新 +tool_settings_updatedsocket 兜底。 - 压缩对话:Quick Menu → 设置 →
handleCompressConversationClick()→ Confirm → POST/api/conversations/<id>/compress→ 新 ID 赋值 + 继续加载。
样式与布局要点
- 定位:
.main-container高度锁定var(--app-viewport),避免移动端地址栏影响;bodyoverflow: hidden,聊天区域内部overflow-y: auto。 - 配色:大量
var(--claude-*)变量 + 玻璃态背景(backdrop-filter)。按钮/输入/面板 radius 取值 12~24px。 - 动效:多处
transition(quick-menu,submenu-slide,personal-page-fade,quota-toast-fade、mode-icon等);Thinking → Collapse, Scroll lock UI 2 态 SVG。 - 拖拽:Considerations 列表使用
draggable + dragstart/dragover/drop;侧栏手柄cursor: col-resize。 - Icon 渲染:统一使用 CSS mask(
.icon)+iconStyle('--icon-src')设定路径。
重构建议(旧 → 新 Store/组件映射)
| 模块 | 旧 DOM/方法 | 目标组件 | 相关 Store/Composable |
|---|---|---|---|
| 对话历史侧栏 | conversation-sidebar + loadConversationsList/loadConversation/duplicate/delete |
ConversationSidebar.vue |
useConversationStore |
| Logo/状态卡 + Panel 切换 | .sidebar-status + .sidebar-panel-card |
LeftPanel.vue + StatusHeader.vue + PanelSwitcher.vue |
useSystemStore, useFileStore, useTaskStore, useSubAgentStore |
| 文件树节点 | <file-node> 组件 |
FileTreePanel.vue |
useFileStore |
| Token/Quota Drawer | .token-drawer + startContainerStatsPolling 等 |
TokenDrawer.vue + ResourceStats.vue |
useResourceStore |
| 聊天消息 | .chat-messages + messages/actions 渲染 |
ChatArea.vue + MessageList.vue + MessageItem.vue + ActionCard 子组件 |
useChatStore, useToolStore |
| 输入区/Quick Menu | .compact-input-area + quick-menu |
InputComposer.vue + QuickMenu.vue + ToolToggleMenu.vue + SettingsMenu.vue |
useChatStore, useToolStore, useUploadStore |
| 聚焦面板 | .right-sidebar |
RightFocusPanel.vue |
useFocusStore |
| 个人空间 | .personal-page-overlay |
PersonalizationDrawer.vue |
usePersonalizationStore |
| Toast/Confirm/ContextMenu | quota-toast, .toast-stack, .confirm-overlay, .context-menu |
ToastStack.vue + ConfirmDialog.vue + ContextMenu.vue |
useUiStore |
| 彩蛋 | .easter-egg-overlay + handleEasterEggPayload |
EasterEggOverlay.vue + composable |
useUiStore |
关键注意事项
- 完全还原:Phase 标签已失效,重构时应以本文 + 备份代码为唯一真值;任何现存 Vite 代码若偏离需求可直接推翻。
- 流式同步:Tool/思考/文本事件严格依赖顺序、状态映射与
action.id,必须在组件化后保持同等粒度,避免“危房式”拼接。 - 多重状态同步:Token 面板、Quota Toast、Quick Menu 与资源轮询之间互相引用(如工具完成后更新 Token),实现时应通过跨 store action 协调。
- 可访问性:旧版所有按钮均提供
title/aria-label,复制按钮状态 2s 自动恢复;滚动锁按钮使用svgicon 反馈;保留这些交互细节。 - 安全脚本:
/static/security.js、window.ensureCsrfToken、window.requestSocketToken、EasterEggRegistry等全局依赖需要在新构建链路中继续注入或以 shim 方式提供。
后续编码时,请以此文档 +
static/old_version_backup/前端备份中的 HTML/CSS/JS 为参考基准,确保界面结构、逻辑流与交互表现与旧版完全一致,再逐步拆分到 Vue 组件与 Pinia store。