agent-Specialization/doc/frontend/component_plan.md

11 KiB
Raw Permalink Blame History

前端组件化梳理与规划

背景与现状

  • static/index.html 将所有界面(配额通知、对话侧栏、文件/待办/子智能体面板、聊天区、输入区、聚焦文件、个性化抽屉、上下文菜单等)堆在一个根模板里,通过 v-if/v-for 直接绑定根实例的数据,缺乏可复用组件边界和样式隔离。static/index.html:35-1094
  • static/app.js 中单个 createApp 承担了连接管理、消息流、文件树、资源监控、使用额度、工具控制、上传、个性化设置、彩蛋等所有状态/方法,数据段跨越 150+ 行,方法 200+ 个,总体约 4.4k 行,导致维护和测试困难。static/app.js:186-4362
  • 现有代码依赖 Vue CDN全局变量ICONSTOOL_CATEGORY_ICON_MAPwindow.requestSocketToken 等)直接注入;没有构建步骤,也就无法按模块拆分或使用 TypeScript/ESM。

Phase 1脚手架 + 入口切换)已落地,过程总结见 doc/frontend/phase1_setup.md Phase 2对话侧栏 + 文件面板)已上线,详见 doc/frontend/phase2_sidebar.md。 以下规划作为 Phase 3+ 的拆分依据。

目标与约束

  1. 拆分出语义明确的组件,使每个功能模块有独立的模板/逻辑/样式,降低互相影响。
  2. 引入现代化构建链路Vite + Vue 3 SFC保留当前 API/UI 行为、Socket.IO 逻辑与安全脚本(security.js、彩蛋脚本)。
  3. 建立状态分层,区分“跨组件共享状态”“本地 UI 状态”“请求数据”,以 Pinia/composable 管理。
  4. 支持渐进式迁移:新旧模板可短期共存,确保每阶段都能运行并回归关键流程(登录→聊天→终端→上传→用量面板)。

构建与目录规划

  1. 构建工具:采用 Vite支持 Vue 3、热更新、自动代码分割后续易拓展 TypeScript/测试。
  2. 目录建议(均位于 static/ 下):
    • src/main.ts:入口,挂载 App.vue、注入 Pinia、注册全局指令/组件。
    • src/App.vue:根壳组件,只负责大布局与全局 overlay 容器。
    • src/components/:按功能域组织(如 chat/, sidebar/, panels/, overlays/, common/)。
    • src/stores/Pinia storeuseConnectionStore, useConversationStore, useResourceStore, useFileStore, useUiStore, usePersonalizationStore)。
    • src/composables/WebSocket 管理、消息流解析、Toast/Confirm service、复制代码块等工具。
    • src/assets/:静态 SVG/样式;继续复用 style.css,逐步拆为 src/styles/
    • src/utils/request.ts:封装带 CSRF 的 fetch。
  3. 构建输出Vite 输出到 static/dist/Flask 模板改为加载 dist/assets/*.js|css;保留 CDN 版本作为 fallback直到迁移完成。

组件树(建议)

AppShell
├─ GlobalToastsquota + toast 队列)
├─ ConfirmDialog
├─ EasterEggOverlay + ContextMenu + CopyCodeHandler
├─ ConversationSidebar
├─ WorkspaceLayout
│  ├─ LeftPanel
│  │  ├─ StatusHeader
│  │  ├─ PanelSwitcher
│  │  └─ PanelContent
│  │      ├─ FileTreePanel含 FileNode
│  │      ├─ TodoPanel
│  │      └─ SubAgentPanel
│  ├─ ChatArea
│  │  ├─ TokenDrawer
│  │  ├─ MessageList
│  │  │  ├─ MessageItemUser/Assistant/System
│  │  │  └─ ToolAction / ThinkingBlock / MarkdownBlock
│  │  ├─ ScrollLockToggle
│  │  └─ InputComposer
│  │      ├─ QuickMenu
│  │      │  ├─ ToolToggleMenu
│  │      │  └─ SettingsMenu
│  │      └─ AttachmentButton / ModeSwitch
│  └─ RightFocusPanel
└─ PersonalizationDrawer

说明:

  • ConversationSidebar 负责搜索/分页/对话操作,接收 conversations, currentConversationId、触发 loadConversation/delete/duplicatestatic/index.html:91-204
  • LeftPanel 根据 panelMode 动态渲染文件树(fileTree, expandedFolders)、待办(todoList)、子智能体(subAgents)。static/index.html:217-368
  • ChatArea 内部组件拆分消息渲染、Token/资源卡片、输入框及快捷菜单。static/index.html:374-820
  • RightFocusPanel 只观察 focusedFiles,提供 tabs 和 downloadFile 操作。static/index.html:906-958
  • PersonalizationDrawer 独立组件管理表单、拖拽排序与保存逻辑。static/index.html:959-1094
  • Toasts/Confirm/ContextMenu/EasterEgg 形成 overlays/ 组件,避免根实例直接绑定。

状态域与 Store 设计

Store/Composable 职责 关键数据来源
useConnectionStore 维护 Socket.IO 实例、连接状态、stop 请求、服务器状态快照;统一事件监听与销毁。 initSocket 逻辑 static/app.js:711-1103
useConversationStore 对话列表、当前对话、消息流、工具状态、压缩/清空等命令;暴露 actionload/create/delete/duplicate/send/compress loadConversationsListloadConversationfetchAndDisplayHistory、消息 handlers static/app.js:1904-3336
useResourceStore Token 统计、容器状态、网络/存储、配额轮询;提供格式化工具。 loadInitialDataupdateContainerStatuspollContainerStatsfetchUsageQuota static/app.js:1595-1870
useFileStore 文件树、聚焦文件、右键菜单、下载逻辑。 updateFileTreedownloadFile/Folder static/app.js:615-707static/index.html:906-958
useTaskStore 待办列表、子智能体轮询。 fetchSubAgents, fetchTodoList static/app.js:2885-2938
useUploadStore 上传状态、toast 更新、复用安全扫描提示。 uploadSelectedFile static/app.js:2940-3108
usePersonalizationStore 个人页表单、保存/启停逻辑。 openPersonalPage~savePersonalization static/app.js:2496-2669
useUiStore 侧栏折叠、面板宽度、QuickMenu/ToolMenu/Settings、toast 队列、confirm/overlay。 data 中的 UI 字段 static/app.js:224-360 + pushToast/confirmAction static/app.js:4200-4334

Store 之间通过 action 通信,如 conversationStore 发出 loadConversation 后通知 resourceStore 更新 tokenuiStore 暴露 toast/confirm 服务供其他 store/组件调用。

事件与数据流

  1. WebSocketio('/') 监听 quota/token/status/conversation/message/easter-egg 等事件(static/app.js:769-1103),将原本直接修改 data 的逻辑迁移到 store action例如 conversationStore.handleAiMessageStartresourceStore.handleQuotaUpdate)。
  2. REST APIloadInitialData 涵盖 /api/files, /api/focused, /api/status, /api/conversations/current, /api/usage 等;应抽象为 apiClient,集中处理 CSRF/错误提示。
  3. 定时轮询:容器 0.5s、存储 5s、子智能体 5s、配额 10s可在 store 内封装 start/stop以路由或可见性驱动
  4. 命令通道socket.emit('send_command', {...})run_commandstop_task 等保持不变,只是从组件调用 store action。

迁移路线(建议)

  1. Phase 0 基础设施
    • 初始化 Vite + Vue 3 + Pinia + ESLint + Prettier。
    • 配置构建输出与 Flask 静态路径,写入 README 使用说明。
  2. Phase 1 壳 + Overlay
    • 实现 AppShell、toast/confirm/context-menu/personalization overlay保持旧版聊天区域引用旧模板通过 mount#app 下混用。
    • 验证登录、对话加载、toast/confirm 是否正常。
  3. Phase 2 侧栏组件
    • 拆 ConversationSidebar、LeftPanel含 FileTree/Todo/SubAgent
    • 引入 useConversationStoreuseFileStoreuseTaskStore
    • 测试对话搜索/切换、文件树展开/右键、待办/子智能体展示。
  4. Phase 3 ChatArea
    • 拆 TokenDrawer、MessageList、InputComposer、QuickMenu、ToolMenu。
    • 落地 WebSocket/消息 store复用现有渲染逻辑Markdown、思考块、工具卡片
    • 回归消息流、工具调用、停止按钮、上传/设置/模式切换。
  5. Phase 4 RightPanel & Personalization
    • 拆聚焦文件与个人页组件,接入 usePersonalizationStore
    • 完成 CSS 抽取,移除旧版 static/app.js/index.html,保留必要 polyfill。

每个阶段都保持 main.py/web_server.py 无需改动,仅替换静态入口文件即可。

测试与验证

阶段 核心验证 自动化建议
Phase 0 npm run dev/build 正常Flask 引用 dist;加载页可看到“正在连接服务器”。 添加 npm run lintnpm run typecheck(若启用 TS
Phase 1 Toast/Confirm/上下文菜单、彩蛋覆盖层可交互;连接断开/重连提示正常。 编写 Vitest 针对 toast store 的单测。
Phase 2 对话 CRUD、文件树右键下载、待办/子智能体轮询无误;侧栏拖拽宽度保持。 Playwright 脚本:创建/切换/删除对话,校验 API 调用。
Phase 3 消息流畅、工具卡片渲染、上传扫描提示、快捷菜单/设置工作。 录制 socket mock用 Jest/Vitest 验证消息 reducer。
Phase 4 聚焦文件显示、个人化表单保存;整体构建包大小可控。 e2e提交 personalization再刷新确保状态加载。

风险与应对

  1. WebSocket 事件错杀:拆分过程中如未正确解绑监听,会重复触发。→ 在 useConnectionStore 中集中注册/清理,配合 onBeforeUnmount
  2. CSS 回归.sidebar, .chat-container 等现有样式都位于 style.css,迁移时注意命名冲突,可引入 postcss-nesting + CSS Modules逐步拆分。
  3. Build/Runtime 混用:迁移初期若需要旧版 app.js 支撑未拆组件,可通过 Vite 的 define 暴露全局函数,与 Flask 模板条件加载。
  4. 依赖外链Prism/KaTeX/Marked、Socket.IO 目前从 CDN 引入。组件化后建议使用 npm 依赖,统一由 Vite 打包,避免版本漂移。

下一步

Phase 3进行中聊天区实时化 + 输入/工具 + Token 面板

  1. 连接与消息流(已完成)useConnectionStore + useChatStore + ChatArea,加载历史、实时流式输出、发送/停止。
  2. 工具卡片与 Quick Menu(当前待做)
    • 抽象 useToolStore 管理工具分类、状态、开关(迁移 toolSettings)。
    • 组件化 Quick Menu上传、工具开关、设置接入 Pinia store。
    • 渲染工具执行卡片(命令输出、文件操作等),替换 legacy DOM 结构。
  3. Token/Quota/资源面板
    • 新建 useResourceStore 轮询 /api/container-status/api/project-storage/api/usage,替换 token drawer。
    • 组件化 TokenDrawer,展示 Token/Quota/CPU/内存/网络/存储卡片。
  4. Toast/Confirm/Context
    • 搬迁 pushToast/confirmAction/contextMenu/EasterEgg overlay形成 useUiStore + GlobalToasts/ConfirmDialog 组件。

完成 Phase 3 后,再进入 Phase 4聚焦面板、个性化抽屉、样式统一等。