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

4.5 KiB
Raw Blame History

迭代复盘: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.jstabs/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 亦为全局)。