Files
one_divine_lot/docs/04-迭代记录/09-Tab设置统一管理/迭代复盘.md
T
kyugao f1e7e785a1 docs(迭代09/10): Tab 设置统一管理 + UI 主题适配 全量文档
迭代09 (R-011 Tab 设置统一管理):
- 需求 R-011 (定稿 Q1-Q5) + 需求池索引
- 计划 PLAN-010 + 迭代09 四件套 (目标/技术方案/验收/复盘)
- 约束: 产品约束-009 / UI约束-003 / 技术约束-014
- UI约束-002 修订: 通用设置→Tab 设置

迭代10 (R-012 UI 适配 DSH 主题):
- 需求 R-012 (定稿: 暂定跟随系统) + 需求池索引
- 计划 PLAN-011 + 迭代10 四件套
- 约束: UI约束-004 (主题适配约定)
2026-09-02 14:01:08 +08:00

42 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 迭代复盘:09-Tab 设置统一管理(内置 + 策略分组,显示/隐藏 + 拖动排序)
> 复盘日期:2026-09-02 | 迭代状态:**已完成(老师确认)**
> 关联需求:R-011(Tab 设置:统一管理所有 tab,已定稿 Q1-Q5)
> 关联计划:PLAN-010(计划-Tab设置统一管理)
## 结果
迭代 09 达成:设置页「通用设置」升级为「Tab 设置」,成为所有会话 tab(系统内置 + 策略分组)**唯一的顺序与显隐入口**:两类 tab 混排一张表,每行 = 拖动手柄(原生 HTML5 DnD)+ 名称(内置带「内置」徽标、策略带「策略」徽标)+ 显示/隐藏开关;**任何 tab 均不支持重命名与删除**;拖动落点立即持久化;策略分组子 tab 瘦身为 新增/重命名/删除。
## 过程事实
1. **需求定稿(R-011**:老师提出设置页默认 tab 与策略 tab 一起排序(内置标记、不可重命名/删除)→ AI 分析现状(两套数据、两套 order 空间,内置恒在策略前)→ 提出统一 tabs 有序数组方案 → 老师确认 D1-D7 + Q1-Q5(拖动落点立即持久化 / 新增追加末尾 / 旧隐藏策略迁移后显示 / 名称 join 自动跟随 / 全部 tab 禁重命名删除);
2. **数据层(settings.js**:tabs 从布尔对象 → 统一有序数组(kind: builtin|strategy + refKey/refId + visible + order);strategies 收窄为 {id, name};旧格式读取时静默归一化迁移(schema union 兼容存量 + normalizeTabs 转换);addStrategy/removeStrategy 联动 tabs
3. **API 层(strategies.js**tabs/update 语义改整表(顺序 + 显隐);strategies/add 联动追加 tab(末尾);strategies/remove 联动删除 tab 条目;废弃 strategies/move
4. **客户端注册(client/index.js**:合并 registerGeneralTabs + registerStrategyTabs 为统一注册(读 tabs 数组按 order 排序、过滤 visiblebuiltin 走内置 render、strategy 走 StrategyTab),移除硬编码 order 间隔(10/11/12 与 13+);
5. **设置页 UISettingsSection.jsx**:「Tab 设置」子 tab(混排表格 + 徽标 + 显隐开关 + 拖动排序 + 落点立即持久化);策略分组瘦身(移除排序箭头与显隐开关,加指引提示);
6. **验证**:回归测试 35 项全通过(scripts/test-r011-tabs.mjs 数据层 23 项 + test-r011-api.mjs API 层 12 项)+ 真实 schema resolve 验证(旧配置归一化正确)+ 构建 + typecheck 通过。
## 经验教训(复盘沉淀)
### 1. schemastery 无 z.enum / .optional()schema 兼容存量用 z.union 双分支
- schemastery 只有 z.union([z.const(...), ...]) 无 z.enum,可选字段不调 .required() 即可;
- **关键**DSH settings 的 resolve 会用 schema 校验存量 user 层——新 schema 直接替换会导致旧配置(布尔对象 tabs)校验失败、插件启动报错;
- **沉淀**settings schema 变更必须先验证存量兼容——用 z.union 双分支(旧格式 + 新格式),旧值通过校验、读取时再归一化;改动 settings schema 前跑 schema-resolve 测试。
### 2. 读取时归一化 + schema 双分支 = 无感迁移
- 本次没有写一次性迁移脚本,而是「schema 接受旧格式 + normalizeTabs 读取时转新」:存量用户升级零操作、零报错;
- 归一化结果在首次写操作(updateTabs/add/remove)时落库为数组,之后自然持久化;
- **沉淀**settings 结构变更优先「schema 兼容 + 读取归一化」而非迁移脚本,符合 R-006/R-008 的迁移经验(幂等、无需用户操作)。
### 3. 前端字符串与 JSX 引号冲突
- 写 JSX 组件代码时,代码里同时有 JS 单双引号与 JSX 属性引号,用模板字符串包整段时内部反引号/插值冲突,多次报错;
- **沉淀**:批量生成代码用数组 join(每行独立字符串),避免模板字符串嵌套转义地狱。
## 遗留/后续
1. **Tab 设置拖动交互**:当前实现为整行 draggable(原生 DnD),落点插入到目标行位置;后续可优化为拖动手柄专属拖拽 + 拖拽中的视觉反馈(插入线);
2. **关注列表 tab**:仍为占位(PlaceholderTab),后续迭代实现;
3. **迁移落库时机**:旧配置首次读取不落库(纯读),首次写操作时才持久化新数组——如老师希望启动即落库可加一次性迁移(当前行为无感知差异,可接受);
4. **多 DSH 实例/多用户**:tabs 顺序为全局设置(非按会话),符合现状(strategies 亦为全局)。