Files
hermes-desktop/docs/phases/phase_007.md
T
toor 01d9e301fc
Build / build (push) Canceled after 0s
Playwright / browser (push) Canceled after 0s
initialize Electron desktop app and remove unused files
2026-10-25 01:09:01 +08:00

13 KiB
Raw Blame History

Phase 007 — Arco 迁移:其余 20 视图批量

项 值
目标 全仓无 naive-ui;无第二 UI 库
前置 Phase 006 通过
产出 grep -r "naive-ui" packages/client/src 零命中
参考 docs/03-施工蓝图.md §8.2

0. 批次划分原则

按耦合度分批,不按页面重要性。每批独立提交、独立验收,任何一批都能停下来过夜。

Phase 006 已经把最难的(流式 / 虚拟滚动 / 审批)趟平了,所以下面每批都是体力活。


1. 批次一览

批次 范围 特征 风险
7a Settings / Profiles / Models / Logs 纯表单 + 表格 低
7b Skills / Plugins / McpManager / Memory 卡片列表 + 抽屉 低
7c Files / Terminal 大量 DOM + xterm 中
7d Usage / Performance / SkillsUsage / Journey 图表 / 图谱 + 数据表格 中
7e Kanban / Jobs / Workflow / Devices 拖拽 + 复杂交互 中高
7f Channels / GroupChat / GlobalAgent IM 频道 + 群聊 中高
7g History / VersionPreview 历史会话 低

7f 排在 7e 之后:群聊也是流式页,虽然比主聊天简单,但仍有 SSE + 增量渲染,靠近 006 的经验更划算。


2. 每批的标准动作(7a 走一遍,之后照抄)

2.1 开工前

cd /Users/jack/source/MyProject/js/hermes-ui
# 看这批有多少 naive 引用
grep -rc "naive-ui" <本批文件列表>

2.2 改法顺序

  1. 先建/补 docs/arco-mapping.md —— 本批遇到的 Naive 组件若表里没有,先补进去
  2. Provider 层先换(NMessageProvider → useMessage() composable)
  3. 容器 → 布局(NLayout → a-layout)
  4. 表单 → 控件(NForm → a-form,逐个 NFormItem)
  5. 表格 / 列表(NDataTable → a-table,差异最大)
  6. 交互层(NModal NDrawer NPopconfirm)
  7. 删除所有未用的 naive import(这一步最容易漏,编译器会兜底)

2.3 收尾

grep -rn "naive-ui" <本批文件>     # 期望零命中
npm run build
npm run test
npm run test:e2e
git commit -m "feat(ui): migrate <batch> views to Arco Design Vue"

2.4 每批完成定义(四条全满足)

  • 本批文件 grep -c naive-ui 归零
  • npm run test 通过
  • e2e 对应用例通过
  • 明暗双主题人工过一遍

3. 批次内容

3.1 批次 7a — 纯表单与表格(先做这批打样)

views/hermes/SettingsView.vue
views/hermes/ProfilesView.vue
views/hermes/ModelsView.vue
views/hermes/LogsView.vue
components/hermes/settings/**            # 约 20 个组件,含 voice/ 子目录
components/hermes/profiles/**            # 6 个
components/hermes/models/**              # 约 12 个,含各种 OAuth 登录弹窗
components/hermes/settings/SettingRow.vue
components/layout/ModelSelector.vue
components/layout/ProfileSelector.vue
components/layout/LanguageSwitch.vue
components/layout/ThemeSwitch.vue

本批特有难点:

  • NForm 的校验规则 API 与 a-form 不同,需写适配
    naive: [{ required: true, message: '...' }]
    arco:  [{ required: true, message: '...' }]  # 规则对象基本一致
          但 field 绑定方式与 error 展示位置不同
    
  • 各 OAuth 登录弹窗(AnthropicLoginModal CodexLoginModal CopilotLoginModal GeminiLoginModal NousLoginModal XaiOAuthLoginModal)—— 每个都是独立 Modal,改完逐个点
  • SettingRow.vue 是所有设置项的骨架容器,先改它

完成后必须过:

tests/client/default-credential-prompt.test.ts
tests/client/copilot-login-modal.test.ts
tests/client/platform-card.test.ts
tests/client/profile-card-config-edit.test.ts
tests/client/provider-card-built-in-action.test.ts
tests/client/provider-base-url.test.ts
tests/client/display-settings.test.ts
tests/client/gateway-auto-start-settings.test.ts
tests/client/compression-settings 相关

3.2 批次 7b — 卡片列表与抽屉

views/hermes/SkillsView.vue
views/hermes/PluginsView.vue
views/hermes/McpManagerView.vue
views/hermes/MemoryView.vue
components/hermes/skills/**             # 7 个
components/hermes/mcp/McpServerCard.vue
components/hermes/common/RouteLinkItem.vue
components/hermes/settings/MemorySettings.vue
components/hermes/settings/CompressionSettings.vue

本批特有难点:

  • SkillList / SkillDetail / SkillImportModal / SkillExternalDirsModal 有复杂表单与文件树
  • PendingWriteApprovals.vue 有审批交互(与 Phase 006 的审批同源)

完成后必须过:

tests/client/skills-view.test.ts
tests/client/skill-list.test.ts
tests/client/skill-detail-edit.test.ts
tests/client/plugins-view.test.ts
tests/client/pending-write-approvals.test.ts
tests/client/route-link-item.test.ts

3.3 批次 7c — 文件与终端(别把 Arco 塞进来)

views/hermes/FilesView.vue
views/hermes/TerminalView.vue
components/hermes/files/**               # 9 个
components/hermes/chat/TerminalPanel.vue   # 若 7a/7b 未改
composables/useDefaultWorkspace.ts
utils/file-path.ts
utils/hermes/kanban-assignees.ts

**本批特有难点(本批最特殊):

  • 文件树 FileTree.vue / FileList.vue / FileBreadcrumb.vue 是手写 DOM 结构 + CSS,不要换成 Arco 的 a-tree——会丢掉自定义的文件类型图标、右键菜单、拖拽。
  • xterm.js 终端是独立 DOM 树,外面套任何 Arco 布局都可能引入尺寸问题。终端容器用固定 flex + 原生 CSS。
  • FileContextMenu.vue / FilePreview.vue / FileEditor.vue / FileToolbar.vue 涉及上传、预览、编辑
  • 右键菜单:a-trigger 的 trigger="contextmenu"

完成后必须过:

tests/e2e/terminal.spec.ts
tests/client/file-tree-profile-scope.test.ts
tests/client/file-list-layout.test.ts
tests/client/file-context-menu.test.ts
tests/client/folder-picker-windows-drives.test.ts
tests/client/files-view-profile-config-route.test.ts
tests/client/file-path.test.ts

3.4 批次 7d — 图表与数据密度

views/hermes/UsageView.vue
views/hermes/PerformanceView.vue
views/hermes/SkillsUsageView.vue
views/hermes/JourneyView.vue
components/hermes/usage/**              # StatCards DailyTrend ModelBreakdown AgentBreakdown
api/hermes/journey.ts
stores/hermes/usage.ts

本批特有难点:

  • 这是 ArkScope 装饰层的第二个合法落点:Journey 图谱的背景层可以用装饰位面。但数据线、节点、文字仍必须原生渲染,装饰只能垫在最底。
  • 图表组件(若有 echarts / 自绘 SVG)不要动,只换外围容器
  • NDataTable → a-table 在这里是重灾区(数据密度高、列多、有合计行)
  • 表格横向滚动 + 固定列

完成后必须过:

tests/client/usage-components-cache-visuals.test.ts
tests/client/usage-view-period.test.ts
tests/client/usage-store.test.ts
tests/client/skills-usage-view.test.ts

3.5 批次 7e — 拖拽与复杂交互

views/hermes/KanbanView.vue
views/hermes/JobsView.vue
views/hermes/WorkflowView.vue
views/hermes/DevicesView.vue
components/hermes/kanban/**              # 4 个
components/hermes/jobs/**                # 4 个
components/hermes/workflow/**            # 3 个
stores/hermes/kanban.ts
stores/hermes/jobs.ts
utils/hermes/workflow-skills.ts

本批特有难点:

  • 拖拽(Kanban 列间拖卡片)是手写 drag 事件,换成 Arco 布局后要重新验证 drop zone 的坐标计算。这是本批最大风险。
  • WorkflowAgentNode.vue 画的是节点图,坐标计算与容器尺寸耦合
  • JobRunHistory 有时间线

完成后必须过:

tests/client/kanban-view.test.ts
tests/client/kanban-task-card.test.ts
tests/client/kanban-task-drawer.test.ts
tests/client/kanban-create-form.test.ts
tests/client/kanban-store.test.ts
tests/client/kanban-api.test.ts
tests/client/jobs.test.ts
tests/client/job-form-modal.test.ts
tests/client/workflow-skills.test.ts
tests/client/workflow-socket.test.ts

3.6 批次 7f — IM 频道与群聊

views/hermes/ChannelsView.vue
views/hermes/GroupChatView.vue
views/hermes/GlobalAgentView.vue
components/hermes/group-chat/**          # GroupChatPanel GroupMessageList GroupMessageItem GroupChatInput CreateRoomForm
stores/hermes/group-chat.ts
api/hermes/group-chat.ts
api/hermes/global-agent.ts

本批特有难点:

  • GroupMessageList / GroupMessageItem 也是流式增量渲染,Phase 006 的规则同样适用:气泡内禁用 Arco 组件
  • 多 agent 路由的可视化(谁在响应)
  • 会话设置抽屉

完成后必须过:

tests/client/group-chat-store-baseline.test.ts
tests/client/group-chat-store-streaming.test.ts
tests/client/group-chat-store-workspace.test.ts
tests/client/group-chat-view-settings.test.ts
tests/client/group-chat-workspace-diff.test.ts
tests/client/group-chat-input-mentions.test.ts
tests/client/group-chat-mention-options.test.ts
tests/client/group-chat-panel-workspace-source.test.ts
tests/client/group-message-list-scroll.test.ts
tests/client/group-message-item-highlight.test.ts
tests/e2e/group-chat-room-deeplink.spec.ts

3.7 批次 7g — 历史与版本预览(收尾)

views/hermes/HistoryView.vue
views/hermes/VersionPreviewView.vue
stores/hermes/app.ts
data/changelog.ts                        # Phase 002 已清空

本批特有难点:

  • VersionPreviewView 若 changelog 已清空,要么给空态,要么隐藏入口

完成后必须过:

tests/e2e/history-session-deeplink.spec.ts
tests/client/chat-view-tab-title.test.ts

4. 收尾(全批次完成后)

4.1 删依赖

package.json 删:

"naive-ui": "...",
"@css-render/vue3-ssr": "...",   // naive 的 peer,若直接依赖
"vdirs": "..."                     // 若直接依赖

先用 grep -rn "vdirs\|@css-render" packages/client/src 确认是否真用到。

4.2 改构建配置

vite.config.ts:

// manualChunks
if (id.includes('naive-ui') || id.includes('vueuc')) return 'ui-vendor'
// 改为
if (id.includes('@arco-design')) return 'ui-vendor'

// optimizeDeps.include
// 删掉 'naive-ui', 'vueuc', '@css-render/vue3-ssr'
// 加上 '@arco-design/web-vue'

4.3 恢复 prepare script

Phase 001 摘掉的 "prepare": "[ -d dist ] || npm run build" 恢复。

4.4 重写 style-system.test.ts

旧版断言的是 Naive 的 theme key。改为断言 Arco token:

// packages/client/src/styles/arco-theme.ts 导出的令牌完整性
// colorPrimary / colorBgLayout / colorBgContainer / borderRadius / fontFamily / fontFamilyMono 存在
// 浅色与深色两套值都定义了

4.5 新增 no-naive-ui.test.ts(防回流,最强保障)

// 递归扫 packages/client/src
// 任何文件出现 "from 'naive-ui'" 或 "from \"naive-ui\"" 即 fail
// 同时断言 package.json 的 dependencies 里无 naive-ui

4.6 更新 AGENTS.md 前端规则

- 使用 Arco Design Vue。新增控件优先从 @arco-design/web-vue/es/icon 取图标。
- 禁止引入第二个 UI 库。
- 消息气泡内部不用 Arco 组件(流式性能)。
- 装饰层一律 pointer-events: none。

4.7 更新 DEVELOPMENT.md 的依赖说明

删掉任何 naive 相关表述。


5. 验收

cd /Users/jack/source/MyProject/js/hermes-ui

# 全仓零命中
grep -rn "naive-ui\|vueuc\|@css-render" packages/client/src/
grep -n "naive-ui" package.json package-lock.json
# 期望:零命中

# 只 Arco 一个 UI 库
grep -nE "\"(naive-ui|element-plus|ant-design-vue|primevue|@arco-design/web-vue)\"" package.json

npm ci --ignore-scripts
npm run build
npm run test:coverage
npm run test:e2e

手工

  • 全部 24 个视图(20 个 + 登录 + 缺依赖引导)逐个点过
  • 明暗双主题各过一遍
  • Kanban 拖拽正常
  • 文件树正常
  • 终端正常
  • 图表正常
  • 窄屏 / 移动端布局正常

6. 风险

# 风险 缓解
P7-1 工作量超预期,7a-7g 拖太久 每批独立可停;先做 7a 定模式,再批量
P7-2 批量改中顺手重构业务逻辑,污染 diff 硬规则:只换渲染层。发现逻辑 bug 单独记 issue,不在本次改
P7-3 Kanban 拖拽坐标在 Arco 布局下算错 7e 单独安排时间手测,不与其他批混做
P7-4 忘记某文件的 naive import no-naive-ui.test.ts 卡住(§4.5)
P7-5 a-table 替换后大数据量卡顿 7d 加虚拟滚动(a-table-virtual),先测 1000 行
P7-6 依赖删了但 lock 没同步,npm ci 失败 删依赖后 rm package-lock.json && npm install --package-lock-only
P7-7 7f 群聊流式性能退化 复用 Phase 006 的气泡禁 Arco 规则

7. 完成标志

项目功能完整 + 界面全量 Arco + 无第二 UI 库。进入 Phase 008。