diff --git a/code/fms/.codebuddy/plans/popover-zero-wrapper-refactor_f54580ca.md b/code/fms/.codebuddy/plans/popover-zero-wrapper-refactor_f54580ca.md new file mode 100644 index 00000000..026d86ad --- /dev/null +++ b/code/fms/.codebuddy/plans/popover-zero-wrapper-refactor_f54580ca.md @@ -0,0 +1,173 @@ +--- +name: popover-zero-wrapper-refactor +overview: 为 Popover 组件增加显式 unwrapped 开关的"零包裹"模式(事件注入到用户触发器 vnode),并将 Tooltip/Dropdown/Select/DatePicker/RangePicker 及 AppSidebar、AppTabs、结构树等全部调用方迁移到零包裹,删除所有 .popover-trigger 相关补丁样式与 stretch-trigger 业务用法,全程保持现有行为不回归。 +todos: + - id: core-popover-unwrapped + content: 改造 popover.vue:加 unwrapped prop、cloneVNode 注入事件与锚点指令、双分支模板 + status: completed + - id: migrate-derived + content: 迁移 Tooltip/Dropdown/menu/Select/DatePicker/RangePicker 开启 unwrapped,删除各 index.scss 的 .popover-trigger 补丁 + status: completed + dependencies: + - core-popover-unwrapped + - id: migrate-usages + content: 迁移外部使用点:AppSidebar/AppTabs 删 :deep 规则、结构树去 stretch-trigger、help-icon 开 unwrapped,用 [subagent:code-explorer] 核对全量清单 + status: completed + dependencies: + - migrate-derived + - id: demo-tests + content: demo/popover.vue 补 fallback/组件触发器/事件合并三用例,新增 popover vitest 单测 + status: completed + dependencies: + - core-popover-unwrapped + - id: verify-all + content: 跑 pnpm lint、fmt:check、build、test 全量验证,并人工回归四类触发场景 + status: completed + dependencies: + - migrate-derived + - migrate-usages + - demo-tests +--- + +## 用户需求 + +为 fms-vue 的 Popover 组件实现"零包裹"(antdv 式事件注入)模式,并全量迁移派生组件与外部调用点,同时保证不引入性能开销。 + +> 执行策略:**直接迁移(非渐进)**。项目处于初期阶段,迁移成本低,不做"迁移一个验证一个",派生组件与外部使用点一次性全部开启 `unwrapped`,最后统一跑验证。`unwrapped` prop 保留默认 `false` 作为 API 兜底,但本次全量调用点均显式开启。 + +## 核心功能 + +- Popover 新增显式 `unwrapped` prop(默认 `false`,保持现有行为):触发器插槽为单根元素/组件 vnode 时,通过 `cloneVNode` 把 6 个内部事件 handler(click/contextmenu/mouseenter/mouseleave/focusin/focusout)合并进用户 vnode,并用注入指令获取根 DOM 作为定位锚点;多根 fragment / 文本节点自动回退到现有 `span.popover-trigger` 包裹层。 +- 派生组件全量迁移:Tooltip、Dropdown(含子菜单)、Select、DatePicker、RangePicker 内部显式开启 `unwrapped`,删除各自样式里的 `.popover-trigger` 布局补丁。 +- 外部使用点迁移:AppSidebar / AppTabs 删除 `:deep(.popover-trigger)` 规则,结构树移除 `stretch-trigger`,FormEditPanel / TableEditPanel 的帮助图标 Popover 一并开启 `unwrapped`。 +- demo 补充零包裹/fallback/事件合并用例;新增 Popover 组件单测(vitest + @vue/test-utils + jsdom)。 +- 性能约束:归一化走 computed 缓存、不新增任何 watcher/observer/全局监听、`unwrapped=false` 时零额外开销。 + +## 边界 + +- fallback 路径保留 `stretch-trigger` 与 `.popover-trigger` 样式,不做破坏性删除。 +- 事件合并采用 Vue `mergeProps` 原生语义:用户 handler 先执行、内部 handler 后执行,两者都触发,不覆盖。 +- 零包裹模式下 `stretch-trigger` 无意义,静默忽略。 + +## 技术栈 + +- 现有栈:Vue 3.5.41(`