refactor: complete shared ui cleanup baseline

This commit is contained in:
Haitao Pan 2026-03-30 16:47:22 +08:00
parent 8ab1c09891
commit 831303fa46
11 changed files with 101 additions and 732 deletions

View File

@ -1,494 +1,90 @@
# XWorkmate 设置页与 Assistant 三栏 UI 组件梳理
# XWorkmate UI 组件盘点与清理基线
## 目标
结合本次两张截图,对应梳理
基于当前截图批次,收口以下主链路的 UI 组件归属与清理候选
1. 截图 AAssistant 三栏工作区中的“设置焦点卡片 + 会话区 + 右侧任务文件栏”
2. 截图 B完整“设置”页
3. 这些 UI 在 Desktop / Web / Mobile 三端的代码归属与复用关系
1. Assistant 三栏工作区
2. 设置页
3. 账号页
4. `SKILLS 目录授权`
本文档只记录当前实际代码状态,不再保留已完成清理前的旧副本描述。
---
## 截图归因
## 在用的组件
### 截图 AAssistant 三栏工作区
这张图对应的是桌面端 Assistant 主工作区,不是完整设置页。
代码链路是:
- `lib/app/app_shell_desktop.dart`
Desktop 壳层负责把当前路由切到 `WorkspaceDestination.assistant`
- `lib/app/workspace_page_registry.dart`
把 Assistant 路由映射到 `AssistantPage`
- `lib/features/assistant/assistant_page_main.dart`
负责三栏布局骨架:
- 左侧:`AssistantUnifiedSidePaneInternal`
- 中间:主会话工作区
- 右侧:任务文件/预览栏
- `lib/widgets/assistant_focus_panel_core.dart`
左侧“关注入口”卡片容器
- `lib/widgets/assistant_focus_panel_previews.dart`
其中“设置”卡片内部内容来自 `SettingsFocusPreviewInternal`
- `lib/widgets/settings_focus_quick_actions.dart`
语言切换、主题切换两个快捷按钮
- `lib/features/assistant/assistant_page_state_closure.dart`
中间消息区、输入区、右侧产物栏拼装逻辑
- `lib/widgets/assistant_artifact_sidebar.dart`
右侧“当前任务工作路径 / 全部文件 / 预览 / 暂无文件”侧栏
### 截图 B完整设置页
这张图对应的是桌面端完整设置页。
代码链路是:
- `lib/app/app_shell_desktop.dart`
壳层负责把当前路由切到 `WorkspaceDestination.settings`
- `lib/app/workspace_page_registry.dart`
把设置路由映射到 `SettingsPage`
- `lib/features/settings/settings_page_core.dart`
整个设置页主容器,负责:
- Breadcrumb / 标题 / 搜索框
- 顶部保存入口
- Tab 区域
- 各 section 内容装配
- `lib/features/settings/settings_page_sections.dart`
负责:
- `buildGlobalApplyBarInternal`:“设置提交流程 / 保存并生效”
- `buildGeneralInternal``Application`、`账号访问` 等卡片
- `lib/features/settings/settings_page_widgets.dart`
负责通用字段原子组件:
- `SwitchRowInternal`
- `EditableFieldInternal`
- `InfoRowInternal`
- `lib/widgets/section_tabs.dart`
“通用 / 工作区 / 集成 / 外观 / 诊断 / 关于” tab 条
- `lib/widgets/top_bar.dart`
页面顶部 breadcrumb、标题、副标题、搜索框区域
---
## UI 组件矩阵
| UI Name | code path | Desktop | Web | Mobile |
| 名称 | 路径 | Desktop | Web | Mobile |
| --- | --- | --- | --- | --- |
| Desktop App Shell | `lib/app/app_shell_desktop.dart` | Yes | No | No |
| Web App Shell | `lib/app/app_shell_web.dart` | No | Yes | No |
| App Shell Desktop | `lib/app/app_shell_desktop.dart` | Yes | No | No |
| App Shell Web | `lib/app/app_shell_web.dart` | No | Yes | No |
| Mobile Shell | `lib/features/mobile/mobile_shell_core.dart` | No | No | Yes |
| Mobile Workspace Launcher | `lib/features/mobile/mobile_shell_workspace.dart` | No | No | Yes |
| Assistant Page | `lib/features/assistant/assistant_page_main.dart` | Yes | No | Yes |
| Assistant 主工作区拼装 `buildMainWorkspaceInternal` | `lib/features/assistant/assistant_page_state_closure.dart` | Yes | No | Yes |
| Assistant 右侧产物栏拼装 `buildWorkspaceWithArtifactsInternal` | `lib/features/assistant/assistant_page_state_closure.dart` | Yes | No | Yes |
| Assistant 统一左侧板 `AssistantUnifiedSidePaneInternal` | `lib/features/assistant/assistant_page_main.dart` | Yes | No | No |
| Assistant 关注入口面板 `AssistantFocusPanel` | `lib/widgets/assistant_focus_panel_core.dart` | Yes | No | No |
| 设置焦点预览 `SettingsFocusPreviewInternal` | `lib/widgets/assistant_focus_panel_previews.dart` | Yes | No | No |
| 设置快捷操作 `SettingsFocusQuickActions` | `lib/widgets/settings_focus_quick_actions.dart` | Yes | Yes | No |
| 任务文件侧栏 `AssistantArtifactSidebar` | `lib/widgets/assistant_artifact_sidebar.dart` | Yes | Yes | No |
| Desktop / Web 通用内容卡片壳 `DesktopWorkspaceScaffold` | `lib/widgets/desktop_workspace_scaffold.dart` | Yes | Yes | No |
| 完整设置页 `SettingsPage` | `lib/features/settings/settings_page_core.dart` | Yes | No | Yes |
| 设置页顶部栏 `TopBar` | `lib/widgets/top_bar.dart` | Yes | Yes | Yes |
| 设置提交流程条 `buildGlobalApplyBarInternal` | `lib/features/settings/settings_page_sections.dart` | Yes | No | Yes |
| 设置页通用卡片 `buildGeneralInternal` | `lib/features/settings/settings_page_sections.dart` | Yes | No | Yes |
| 设置表单原子 `SwitchRowInternal / EditableFieldInternal` | `lib/features/settings/settings_page_widgets.dart` | Yes | No | Yes |
| 设置页标签条 `SectionTabs` | `lib/widgets/section_tabs.dart` | Yes | Yes | Yes |
| Web Assistant Page | `lib/web/web_assistant_page_core.dart` | No | Yes | No |
| Web Assistant 顶部 chrome | `lib/web/web_assistant_page_chrome.dart` | No | Yes | No |
| Web Assistant 会话工作区 | `lib/web/web_assistant_page_workspace.dart` | No | Yes | No |
| Web 关注入口面板 `WebAssistantFocusPanel` | `lib/web/web_focus_panel_core.dart` | No | Yes | No |
| Web 设置页 `WebSettingsPage` | `lib/web/web_settings_page_core.dart` | No | Yes | No |
| Web 设置页 section 装配 | `lib/web/web_settings_page_sections.dart` | No | Yes | No |
| Mobile 工作区入口 `MobileWorkspaceLauncherInternal` | `lib/features/mobile/mobile_shell_workspace.dart` | No | No | Yes |
| Assistant 主工作区拼装 | `lib/features/assistant/assistant_page_state_closure.dart` | Yes | No | Yes |
| Assistant 左侧关注面板 | `lib/widgets/assistant_focus_panel_core.dart` | Yes | No | No |
| Assistant 设置预览 | `lib/widgets/assistant_focus_panel_previews.dart` | Yes | No | No |
| Assistant 设置快捷操作 | `lib/widgets/settings_focus_quick_actions.dart` | Yes | Yes | No |
| 右侧任务文件栏 | `lib/widgets/assistant_artifact_sidebar.dart` | Yes | Yes | No |
| Desktop / Web 通用壳层 | `lib/widgets/desktop_workspace_scaffold.dart` | Yes | Yes | No |
| Settings Page | `lib/features/settings/settings_page_core.dart` | Yes | No | Yes |
| Settings Page sections | `lib/features/settings/settings_page_sections.dart` | Yes | No | Yes |
| Settings Page widgets | `lib/features/settings/settings_page_widgets.dart` | Yes | No | Yes |
| Gateway settings | `lib/features/settings/settings_page_gateway.dart` | Yes | No | Yes |
| Gateway connection settings | `lib/features/settings/settings_page_gateway_connection.dart` | Yes | No | Yes |
| Web Settings Page | `lib/web/web_settings_page_core.dart` | No | Yes | No |
| Web Settings sections | `lib/web/web_settings_page_sections.dart` | No | Yes | No |
| Web Settings gateway | `lib/web/web_settings_page_gateway.dart` | No | Yes | No |
| Web Settings support | `lib/web/web_settings_page_support.dart` | No | Yes | No |
| Account Page | `lib/features/account/account_page.dart` | Yes | No | Yes |
| Section Tabs | `lib/widgets/section_tabs.dart` | Yes | Yes | Yes |
| Top Bar | `lib/widgets/top_bar.dart` | Yes | Yes | Yes |
| Surface Card | `lib/widgets/surface_card.dart` | Yes | Yes | Yes |
| Skill Directory Authorization Card | `lib/features/settings/skill_directory_authorization_card.dart` | Yes | No | Yes |
| Settings Shell wrapper | `lib/widgets/settings_page_shell.dart` | Yes | Yes | Yes |
---
## 截图 A 对应的关键组件名字
## 可以删除的 UI 组件
### 左侧窄图标列
| 名称 | 路径 | 原因 |
| --- | --- | --- |
| 旧 Web Assistant 页面分层 | `lib/web/web_assistant_page_*` 中重复的局部壳层 | 只有在 Web Assistant 进一步向共享页面收口时才继续删。 |
| 旧设置页 Web 分层 | `lib/web/web_settings_page_*` 中重复的局部壳层 | 只有在 Web 设置页完全收口到共享 `SettingsPage` 后才建议删。 |
桌面截图 A 左边最窄的图标列,对应:
说明:
- `AssistantSideTabRailInternal`
- `AssistantSideTabButtonInternal`
- `web_focus_panel_core.dart`
- `web_focus_panel_previews.dart`
- `web_focus_panel_support.dart`
代码文件:
- `lib/features/assistant/assistant_page_main.dart`
它不是全局设置页导航,而是 Assistant 工作区内部的“任务 / 导航 / 关注入口”侧板。
### 左侧“设置”卡片
左侧大卡片不是完整设置页,而是 Assistant 中的一个“关注入口工作台卡片”:
- 卡片容器:`AssistantFocusWorkbenchInternal`
- 设置摘要内容:`SettingsFocusPreviewInternal`
- 顶部快捷按钮:`SettingsFocusQuickActions`
对应文件:
- `lib/widgets/assistant_focus_panel_core.dart`
- `lib/widgets/assistant_focus_panel_previews.dart`
- `lib/widgets/settings_focus_quick_actions.dart`
截图里出现的这些文案都直接来自 `SettingsFocusPreviewInternal`
- `设置`
- `语言`
- `主题`
- `执行目标`
- `权限`
### 中间会话区
中间对话工作区对应:
- 页面骨架:`AssistantPage`
- 主体拼装:`buildMainWorkspaceInternal`
对应文件:
- `lib/features/assistant/assistant_page_main.dart`
- `lib/features/assistant/assistant_page_state_closure.dart`
这一块负责:
- 顶部会话流
- 消息气泡
- 底部输入区
- 附件 / 技能 / 提交按钮
### 右侧任务文件栏
右侧栏对应:
- `AssistantArtifactSidebar`
对应文件:
- `lib/widgets/assistant_artifact_sidebar.dart`
截图里的这些元素都在这个组件中:
- `当前任务工作路径`
- `全部文件`
- `预览`
- `暂无文件`
这三份旧 Web Focus Panel 副本已经不再存在,不再列入候选池。
---
## 截图 B 对应的关键组件名字
## 当前清理状态
### 设置页整体
### 第一批:已完成
完整页面组件名:
- Web Focus Panel 共享化已收口到 `lib/widgets/assistant_focus_panel*.dart`
- Web Assistant 不再通过单独的 `web_focus_panel.dart` 兼容壳间接引用共享组件
- `SettingsPage`
### 第二批:已完成公共壳层收口
对应文件
Desktop 与 Web 设置页当前已共用:
- `lib/features/settings/settings_page_core.dart`
- `SettingsPageBodyShell`
- `SettingsGlobalApplyCard`
- `buildOrderedSettingsSections`
它负责:
剩余差异集中在 controller、gateway 细节和 Web 专属 persistence 逻辑,不属于“已完成共享化的重复实现”。
- 顶部 breadcrumb
- 标题 `设置`
- 副标题
- 搜索框 `搜索设置`
- 页面 section 排布
### 第三批:本轮完成
### 顶部“设置提交流程”
- `IosMobileShell` 兼容壳删除后,以 `MobileShell` 作为唯一正式入口
组件来源:
### 第四批:持续维护
- `buildGlobalApplyBarInternal`
对应文件:
- `lib/features/settings/settings_page_sections.dart`
截图里的:
- `设置提交流程`
- `当前没有待提交更改。`
- `保存并生效`
都来自这里。
### Tab 区域
组件名:
- `SectionTabs`
对应文件:
- `lib/widgets/section_tabs.dart`
截图里的:
- `通用`
- `工作区`
- `集成`
- `外观`
- `诊断`
- `关于`
都由这个组件承载。
### Application 与账号访问卡片
组件来源:
- `buildGeneralInternal`
- 原子行组件:`SwitchRowInternal`
- 输入组件:`EditableFieldInternal`
对应文件:
- `lib/features/settings/settings_page_sections.dart`
- `lib/features/settings/settings_page_widgets.dart`
截图里这些内容都在这部分:
- `Application`
- `启用工作台外壳`
- `开机启动`
- `显示 Dock 图标`
- `账号本地模式`
- `账号访问`
- `账号服务地址`
- `账号用户名`
- `工作区名称`
---
## 跨端设计结论
### 1. Desktop 与 Web 共用“视觉原子”,但页面容器分裂
以下组件明显是跨端复用的:
- `DesktopWorkspaceScaffold`
- `SurfaceCard`
- `TopBar`
- `SectionTabs`
- `SettingsFocusQuickActions`
- `AssistantArtifactSidebar`
但 Desktop 与 Web 的页面级容器并没有统一:
- Desktop 设置页:`SettingsPage`
- Web 设置页:`WebSettingsPage`
- Desktop Assistant`AssistantPage`
- Web Assistant`WebAssistantPage`
这意味着视觉语言接近,但页面编排逻辑仍然是双实现。
### 2. Mobile 不是截图同构,而是能力映射
Mobile 当前不是截图 A / B 的直接缩放版,而是“能力对应、布局重组”:
- Assistant 与设置功能仍然存在
- 但入口通过 `MobileShell``MobileWorkspaceLauncherInternal` 组织
- 不存在截图 A 这种桌面三栏结构
- 设置页在 Mobile 继续复用 `SettingsPage`
所以从设计维护角度看:
- `SettingsPage` 是 Desktop / Mobile 的共享设置容器
- `WebSettingsPage` 是 Web 独立实现
- `AssistantArtifactSidebar` 是 Desktop / Web 共享产物侧栏
- “设置焦点卡片”只存在于 Desktop / Web 的 Assistant 焦点面板体系里,不属于 Mobile
### 3. 如果后续要统一三端设计,优先收敛这三层
建议优先把以下三层当作设计系统主干:
1. 页面骨架层:`DesktopWorkspaceScaffold` / `TopBar`
2. section 层:`SectionTabs` / `SurfaceCard`
3. 领域卡片层:设置卡、焦点卡、产物栏
其中最值得继续收敛的重复实现是:
- `SettingsPage` vs `WebSettingsPage`
- `AssistantFocusPanel` vs `WebAssistantFocusPanel`
- `assistant_focus_panel_previews.dart` vs `web_focus_panel_previews.dart`
---
## 建议的后续文档演进
如果后续继续补 UI 文档,建议按下面三个文件拆:
1. `assistant-layout-spec.md`
只描述 Assistant 三栏布局、会话区、产物栏
2. `settings-page-spec.md`
只描述设置页 section、字段、交互状态
3. `cross-platform-ui-parity.md`
专门记录 Desktop / Web / Mobile 的同构与差异
---
## 可合并 / 可清理分析
在保持三栏布局骨架不变的前提下,当前最值得处理的不是页面骨架,而是页面骨架内部已经重复的“焦点卡片层”和“预览内容层”。
### A. 第一优先级:可直接合并复用
#### 1. Focus Panel Core
- Desktop: `lib/widgets/assistant_focus_panel_core.dart`
- Web: `lib/web/web_focus_panel_core.dart`
这两份文件当前为同构重复实现。
判断依据:
- 文件长度完全一致,均为 `347`
- 代码 diff 主要只剩:
- `app_controller.dart` vs `app_controller_web.dart`
- 相对 import 路径差异
- widget 命名前缀 `Assistant*` vs `WebAssistant*`
合并建议:
- 保留 `lib/widgets/assistant_focus_panel*.dart` 作为唯一实现
- Web 端直接复用共享 widget
- 删除 Web 侧同构副本,或先退化为兼容导出薄壳
#### 2. Focus Panel Previews
- Desktop: `lib/widgets/assistant_focus_panel_previews.dart`
- Web: `lib/web/web_focus_panel_previews.dart`
这两份文件当前也为同构重复实现。
判断依据:
- 文件长度完全一致,均为 `636`
- diff 也只剩 controller import 和路径差异
- `SettingsFocusPreviewInternal`、`LanguageFocusPreviewInternal`、`ThemeFocusPreviewInternal` 等实现一致
合并建议:
- 收敛到 `lib/widgets/assistant_focus_panel_previews.dart`
- Web Assistant 通过共享导出的 `AssistantFocusPanel` 直接复用
#### 3. Focus Panel Support
- Desktop: `lib/widgets/assistant_focus_panel_support.dart`
- Web: `lib/web/web_focus_panel_support.dart`
这两份 support 文件同样是同构副本,可和 core / previews 一起收口。
### B. 第二优先级:可抽公共层,但不建议整页硬合并
#### 1. Settings Page Core
- Desktop: `lib/features/settings/settings_page_core.dart`
- Web: `lib/web/web_settings_page_core.dart`
不建议直接合成一个页面类。
原因:
- Desktop settings 还承载 `SettingsDetailPage` drill-down、`initialDetail`、`navigationContext`
- Web settings 重点维护浏览器会话持久化、Local/Remote Gateway、External ACP
- 二者状态模型明显不对称
建议做法:
- 抽共享壳层和 section 编排逻辑
- 保留 Desktop / Web 两个 page container
#### 2. Settings Page Sections
- Desktop: `lib/features/settings/settings_page_sections.dart`
- Web: `lib/web/web_settings_page_sections.dart`
这里适合抽:
- `buildGlobalApplyBarInternal`
- overview tab 排布
- section 级 SurfaceCard 组织方式
但不适合一步到位强合并所有业务 section。
### C. 可标记清理
#### 1. Web Focus Panel 重复文件
以下文件可以标记为第一批清理对象:
- `lib/web/web_focus_panel_core.dart`
- `lib/web/web_focus_panel_previews.dart`
- `lib/web/web_focus_panel_support.dart`
清理前提:
- Web Assistant 全部切回共享 `lib/widgets/assistant_focus_panel.dart`
- 相关测试与 import 路径同步调整
#### 2. 已废弃 iOS 壳别名
- `lib/features/mobile/ios_mobile_shell.dart`
该文件已标注:
- `@Deprecated('Use MobileShell instead.')`
功能上只是直接转发到 `MobileShell`,可以标记为后续兼容清理对象。
#### 3. 不在这两张图主链路中的 settings detail 旁路
以下内容不属于截图 B 的 overview 主链路,建议后续拆出:
- `buildDetailContentInternal`
- `buildDetailIntroInternal`
- `SettingsDetailPage.*`
对应文件:
- `lib/features/settings/settings_page_sections.dart`
这些应独立成 detail flow 文件,而不是继续和 overview 同居在一个大文件里。
#### 4. settings 目录中的大面积冗余 import
当前以下文件头部都带有较重的 `unused_import` / 互相引用信号:
- `lib/features/settings/settings_page_core.dart`
- `lib/features/settings/settings_page_sections.dart`
- `lib/features/settings/settings_page_widgets.dart`
- `lib/features/settings/settings_page_gateway_connection.dart`
- `lib/features/settings/settings_page_gateway_llm.dart`
- `lib/features/settings/settings_page_multi_agent.dart`
- `lib/features/settings/settings_page_presentation.dart`
- `lib/features/settings/settings_page_device.dart`
这些不是“立即删除”对象,但可以明确标记为依赖清理范围。
### D. 本轮推荐执行顺序
在不动三栏布局骨架前提下,推荐按这个顺序执行:
1. 合并 Desktop / Web 的 Focus Panel Core / Previews / Support
2. 抽 Settings 页的共享 section 壳层
3. 拆 Settings detail flow避免与 overview 混杂
4. 清理 deprecated mobile 壳与 settings 冗余 imports
### E. 当前基线测试记录
本轮开始前的最小基线如下:
- `flutter test test/widgets/assistant_focus_panel_suite.dart`
- 结果:通过
- `flutter test --platform chrome test/web/web_ui_browser_test.dart`
- 结果:失败
- 当前已知失败点:测试找不到 “集成” tab
因此后续重构验证需要区分:
- 共享 Focus Panel 的 widget 层回归
- Web 端已有基线失败,不能误判为本轮新引入问题
- 文档和测试应只引用当前仍存在的 UI 文件
- 不再记录已经删除的旧 Web Focus Panel 副本路径

View File

@ -1,146 +1,26 @@
# Focus Panel Dedupe Implementation Plan
# Focus Panel Dedupe Implementation Status
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
## 状态
**Goal:** 在保持 Assistant 三栏布局骨架不变的前提下,收敛 Desktop / Web 重复的 Focus Panel 实现,建立共享前端组件单一来源
已完成
**Architecture:** 保留 `lib/widgets/assistant_focus_panel*.dart` 作为唯一实现Web 端改为直接复用共享 widgets不再维护同构副本。先处理 Focus Panel Core / Previews / Support再调整 Web Assistant 侧的 import 和引用,最后更新测试与文档。
## 当前事实
**Tech Stack:** Flutter, Dart, conditional export `app_controller.dart`, widget tests, browser tests
- 共享实现唯一来源为:
- `lib/widgets/assistant_focus_panel.dart`
- `lib/widgets/assistant_focus_panel_core.dart`
- `lib/widgets/assistant_focus_panel_previews.dart`
- `lib/widgets/assistant_focus_panel_support.dart`
- Web 侧旧的 `web_focus_panel_core.dart`、`web_focus_panel_previews.dart`、`web_focus_panel_support.dart` 已不再存在。
- 本轮进一步移除了 `lib/web/web_focus_panel.dart` 这一层兼容导出Web Assistant 侧不再保留旧入口。
---
## 验收关注点
### Task 1: 记录当前实施上下文
- `test/widgets/assistant_focus_panel_suite.dart`
- `test/web/web_ui_browser_test.dart`
- Web Assistant 页面不再引用旧 Focus Panel 文件路径
**Files:**
- Modify: `docs/planning/2026-03-29-settings-assistant-ui-component-matrix.md`
- Create: `docs/plans/2026-03-29-focus-panel-dedupe-implementation-plan.md`
## Residual Risks
**Step 1: 追加“可合并 / 可清理分析”**
把本轮结论写入组件矩阵文档:
- 可直接合并Focus Panel Core / Previews / Support
- 可抽公共层Settings Page Core / Sections
- 可标记清理Web Focus Panel 副本、deprecated iOS shell、settings detail 旁路
**Step 2: 记录基线测试**
记录:
- `flutter test test/widgets/assistant_focus_panel_suite.dart` 通过
- `flutter test --platform chrome test/web/web_ui_browser_test.dart` 当前基线失败,失败点为找不到 “集成” tab
### Task 2: 建立共享 Focus Panel 单一实现
**Files:**
- Modify: `lib/widgets/assistant_focus_panel.dart`
- Modify: `lib/widgets/assistant_focus_panel_core.dart`
- Modify: `lib/widgets/assistant_focus_panel_previews.dart`
- Modify: `lib/widgets/assistant_focus_panel_support.dart`
- Modify: `lib/web/web_assistant_page_core.dart`
- Modify: `lib/web/web_assistant_page_chrome.dart`
- Modify: `lib/web/web_assistant_page_workspace.dart`
- Modify: `lib/web/web_assistant_page_helpers.dart`
**Step 1: 让 Web 侧直接依赖共享入口**
把 Web Assistant 页面中对 `web_focus_panel.dart` 的依赖改成共享 `../widgets/assistant_focus_panel.dart`
**Step 2: 去掉 Web 专属 Focus Panel 类型耦合**
`WebAssistantFocusPanel` 的使用点替换为 `AssistantFocusPanel`
**Step 3: 确认共享组件继续使用条件导出的 controller**
共享 Focus Panel 通过 `../app/app_controller.dart` 获取平台适配后的 `AppController`,不再区分 Desktop/Web 文件树。
### Task 3: 退役 Web Focus Panel 副本
**Files:**
- Delete: `lib/web/web_focus_panel_core.dart`
- Delete: `lib/web/web_focus_panel_previews.dart`
- Delete: `lib/web/web_focus_panel_support.dart`
- Modify: `lib/web/web_focus_panel.dart`
**Step 1: 保留一个薄入口或直接删入口**
推荐做法:
- `lib/web/web_focus_panel.dart` 变成一行导出共享 widget 的兼容入口
```dart
export '../widgets/assistant_focus_panel.dart';
```
**Step 2: 删除三份重复副本**
删除:
- `web_focus_panel_core.dart`
- `web_focus_panel_previews.dart`
- `web_focus_panel_support.dart`
### Task 4: 更新测试与守护规则
**Files:**
- Modify: `test/widgets/assistant_focus_panel_suite.dart`
- Verify: `test/web/web_ui_browser_test.dart`
**Step 1: 更新文件存在性 / 行数守护**
将原来对 Web 重复文件的守护改成对共享实现的守护,避免测试继续依赖已删除文件路径。
**Step 2: 跑 widget 测试**
Run:
```bash
flutter test test/widgets/assistant_focus_panel_suite.dart
```
Expected:
- PASS
**Step 3: 跑 browser 测试并记录结果**
Run:
```bash
flutter test --platform chrome test/web/web_ui_browser_test.dart
```
Expected:
- 如果仍失败,需要确认是否仍是既有 “集成” tab 失败
- 如果失败点变化,说明本轮重构影响了 Web 链路,需要回退排查
### Task 5: 回归与提交
**Files:**
- Verify only
**Step 1: 检查 git diff**
确认本轮只涉及:
- 文档
- Focus Panel 共享化
- 测试更新
**Step 2: 记录 residual risks**
记录:
- `SettingsPage` / `WebSettingsPage` 尚未统一
- `settings detail flow` 仍在 Desktop overview 体系里
- `ios_mobile_shell.dart` 仍未清理
**Step 3: 提交**
建议提交信息:
```bash
git commit -m "refactor: dedupe assistant focus panel across desktop and web"
```
- `SettingsPage` / `WebSettingsPage` 仍然是双容器实现,但公共壳层已共享
- Web Assistant 页面内部仍保留自己的页面分层,后续可继续评估是否值得继续收口

View File

@ -1,121 +1,35 @@
# Settings Section Shell Implementation Plan
# Settings Section Shell Implementation Status
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
## 状态
**Goal:** Extract a shared Settings page shell so Desktop and Web reuse the same top-level layout, ordered section composition, and global apply bar behavior without changing the three-column workspace skeleton.
已完成公共壳层收口。
**Architecture:** Introduce a small shared shell widget layer under `lib/widgets/` that owns the common settings-page frame and ordered section assembly. Keep Desktop and Web-specific controllers, gateway sub-tabs, and section content builders in their existing feature modules.
## 当前共享层
**Tech Stack:** Flutter, Dart, existing `TopBar`/`SurfaceCard` widgets, Desktop/Web app controllers.
Desktop 与 Web 设置页当前共用以下结构层:
---
- `lib/widgets/settings_page_shell.dart`
- `SettingsPageBodyShell`
- `SettingsGlobalApplyCard`
- `buildOrderedSettingsSections`
### Task 1: Add a shared settings page shell module
这意味着两端已经统一:
**Files:**
- Create: `lib/widgets/settings_page_shell.dart`
- 顶部 `TopBar` 承载方式
- 全局 apply bar 结构
- overview section 的排序装配方式
**Step 1: Add a shared apply-bar widget**
## 当前仍保留的平台差异
- Implement a widget that renders:
- title `设置提交流程 / Settings Submission`
- resolved draft/apply status copy
- `settings-global-apply-button`
- Pass behavior through parameters instead of depending on a specific controller type.
- Desktop`lib/features/settings/settings_page_core.dart`
- 持有 detail flow、navigation context、gateway profile hints
- Web`lib/web/web_settings_page_core.dart`
- 持有浏览器 persistence、Web gateway 子页和 Web 专属 copy
**Step 2: Add a shared page body shell**
## 结论
- Implement a widget that renders:
- `TopBar`
- optional shared apply bar
- page body children
- Keep paddings configurable so Desktop and Web can preserve their current spacing.
第二批不再需要重复执行“抽共享壳层”本身。后续如继续清理,应只处理:
**Step 3: Add a shared ordered-section helper**
- Implement a helper that:
- takes `availableTabs`, `currentTab`
- asks a callback for each tabs content
- interleaves `SizedBox(height: 24)` between non-empty sections
### Task 2: Move Desktop Settings page onto the shared shell
**Files:**
- Modify: `lib/features/settings/settings_page_core.dart`
- Modify: `lib/features/settings/settings_page_sections.dart`
**Step 1: Replace duplicated page frame markup**
- Swap the current top-level `SingleChildScrollView -> Column -> TopBar -> apply bar -> body` block to the shared shell widget.
**Step 2: Replace duplicated ordered overview assembly**
- Route overview ordering through the shared helper instead of local inline assembly.
**Step 3: Keep detail-mode behavior unchanged**
- Ensure the existing desktop-only detail flow still owns:
- breadcrumbs
- back button
- detail intro cards
- gateway navigation hints
### Task 3: Move Web Settings page onto the shared shell
**Files:**
- Modify: `lib/web/web_settings_page_core.dart`
- Modify: `lib/web/web_settings_page_sections.dart`
**Step 1: Reuse the shared page frame**
- Keep `DesktopWorkspaceScaffold` in Web.
- Replace the inner duplicated page body with the shared shell widget.
**Step 2: Reuse the ordered-section helper where still needed**
- Keep Web tab availability constraints intact.
- Use the same helper for any ordered overview logic that remains.
**Step 3: Preserve Web-specific gateway behavior**
- Keep:
- web search field key
- browser persistence copy
- ACP-specific apply-bar gating
### Task 4: Verify the refactor
**Files:**
- Modify as needed: `test/features/settings_page_suite.dart`
- Modify as needed: `test/web/web_ui_browser_test.dart`
**Step 1: Run static analysis**
Run:
```bash
flutter analyze lib/widgets/settings_page_shell.dart lib/features/settings/settings_page_core.dart lib/features/settings/settings_page_sections.dart lib/web/web_settings_page_core.dart lib/web/web_settings_page_sections.dart test/features/settings_page_suite.dart test/web/web_ui_browser_test.dart
```
**Step 2: Run targeted Desktop settings tests**
Run:
```bash
flutter test test/features/settings_page_suite.dart
```
**Step 3: Run targeted Web browser regression**
Run:
```bash
flutter test --platform chrome test/web/web_ui_browser_test.dart
```
**Step 4: Record residual risk**
- Note whether any remaining Desktop/Web duplication still lives in:
- gateway sub-tab section builders
- detail-only desktop flows
- web-only persistence cards
- Web / Desktop 剩余的业务 section 重复
- 已无价值的旧路径引用
- 测试和文档守护的一致性

View File

@ -1,16 +0,0 @@
import 'package:flutter/material.dart';
import '../../app/app_controller.dart';
import 'mobile_shell.dart';
@Deprecated('Use MobileShell instead.')
class IosMobileShell extends StatelessWidget {
const IosMobileShell({super.key, required this.controller});
final AppController controller;
@override
Widget build(BuildContext context) {
return MobileShell(controller: controller);
}
}

View File

@ -14,7 +14,6 @@ import '../widgets/assistant_artifact_sidebar.dart';
import '../widgets/desktop_workspace_scaffold.dart';
import '../widgets/pane_resize_handle.dart';
import '../widgets/surface_card.dart';
import 'web_focus_panel.dart';
import 'web_assistant_page_core.dart';
import 'web_assistant_page_workspace.dart';
import 'web_assistant_page_helpers.dart';

View File

@ -14,7 +14,6 @@ import '../widgets/assistant_artifact_sidebar.dart';
import '../widgets/desktop_workspace_scaffold.dart';
import '../widgets/pane_resize_handle.dart';
import '../widgets/surface_card.dart';
import 'web_focus_panel.dart';
import 'web_assistant_page_chrome.dart';
import 'web_assistant_page_workspace.dart';
import 'web_assistant_page_helpers.dart';

View File

@ -15,7 +15,6 @@ import '../widgets/assistant_artifact_sidebar.dart';
import '../widgets/desktop_workspace_scaffold.dart';
import '../widgets/pane_resize_handle.dart';
import '../widgets/surface_card.dart';
import 'web_focus_panel.dart';
import 'web_assistant_page_core.dart';
import 'web_assistant_page_chrome.dart';
import 'web_assistant_page_workspace.dart';

View File

@ -14,7 +14,6 @@ import '../widgets/assistant_artifact_sidebar.dart';
import '../widgets/desktop_workspace_scaffold.dart';
import '../widgets/pane_resize_handle.dart';
import '../widgets/surface_card.dart';
import 'web_focus_panel.dart';
import 'web_assistant_page_core.dart';
import 'web_assistant_page_chrome.dart';
import 'web_assistant_page_helpers.dart';

View File

@ -1 +0,0 @@
export '../widgets/assistant_focus_panel.dart';

View File

@ -1,5 +1,5 @@
import '../../test_suite_stub.dart'
if (dart.library.io) 'ios_mobile_shell_suite.dart'
if (dart.library.io) 'mobile_shell_suite.dart'
as suite;
void main() {