Files
workspace/code/fms/.codebuddy/plans/fix-tree-component_1ea98de2.md
2026-08-16 22:01:32 +08:00

6.9 KiB
Raw Permalink Blame History

name, overview, todos
name overview todos
fix-tree-component 修复 fms-vue 中 Tree 组件的多个缺陷:致命运行时错误(filterExpand 未定义)、受控键模型遗漏、过滤高亮缺失、键盘焦点不同步、展开交互混乱与拖拽视觉残留,并同步完善 demo。
id content status
fix-critical-errors 修复 tree.vue 中 filterExpand 未定义导致的渲染崩溃,并补充缺失的 defaultLoadedKeys prop completed
id content status dependencies
refactor-expand-select 重构展开/选中交互:加回 switcher 箭头、toggleExpand 改用用户展开集合、行点击只选中并同步键盘焦点,参考 [skill:antdv-next] 交互规范 completed
fix-critical-errors
id content status dependencies
filter-highlight 在 tree-node.vue 实现过滤关键词高亮渲染,命中片段包裹 tree-highlight completed
fix-critical-errors
id content status dependencies
fix-drag-cleanup 修复 onDragLeave 未清理 drop 状态导致的指示线残留,并清理 index.scss 无用样式 completed
fix-critical-errors
id content status
fix-demo 修正 demo/tree.vue 中 check-strictly 示例绑定与联动文案错乱问题 completed
id content status dependencies
verify-build 运行 pnpm lint、fmt:check 与 build 验证修复无回归 completed
refactor-expand-select
filter-highlight
fix-drag-cleanup
fix-demo

用户需求

用户反馈 fms-vue/src/components/ui/tree 组件由上一个 AI 编写,存在较多问题,要求自检问题并修复。经过代码自检,已确认以下问题:

核心问题

  • 致命错误:tree.vue 的 effectiveExpanded computed 引用了未定义的 filterExpand 变量,组件渲染即抛 ReferenceError,Tree 完全不可用
  • Props 缺失:useKeyModel('loadedKeys', 'defaultLoadedKeys', ...) 引用了不存在的 defaultLoadedKeys prop
  • 过滤高亮缺失:filterTree 返回的命中集合与 .tree-highlight 样式均未用于渲染关键词高亮
  • 展开交互缺陷:展开/收起箭头被移除,无可展开视觉提示;行点击同时触发展开与选中造成误触;toggleExpand 基于 effectiveExpanded 会把过滤临时展开的祖先固化进用户展开集合
  • 键盘导航缺陷:点击节点后未同步 activeKey 与焦点,键盘导航起点错乱
  • 拖拽视觉残留:onDragLeave 未清理 dropKey/dropPosition,指示线残留
  • 样式残留:.tree-node.is-danger、.tree-leaf-icon 等无用样式
  • Demo 错乱:check-strictly 示例未绑定 checkedKeys,联动文案错标在严格模式示例下

修复范围

仅修复内部实现与 demo 演示,保持组件既有 API(props/emits/slot 名称)不变,不引入新依赖,样式沿用现有 --fms-* token。

技术栈

  • Vue 3.5(<script setup>)+ SCSS,项目现有技术栈,无需变更
  • 图标使用项目已依赖的 @lucide/vue(现有导出 ChevronRight、Loader、LoaderCircle)
  • 验证命令:pnpm lint(oxlint)、pnpm fmt:check(oxfmt)、pnpm build(vite build)

实现方案

1. 修复致命错误与模型缺失(tree.vue)

  • 删除 effectiveExpanded 中对未定义 filterExpand 的引用,改为从 filterResult.value.expand 派生过滤需展开的祖先集合(computed 缓存,判空处理)
  • props 补充声明 defaultLoadedKeys: { type: Array, default: () => [] },与其余受控键的 default* 声明保持一致

2. 重构展开/选中交互(tree.vue + tree-node.vue + index.scss)

  • 加回 switcher 箭头:tree-node.vue 行首渲染 ChevronRight(展开时旋转 90°),懒加载中渲染 Loader/LoaderCircle 转圈;箭头 @click.stop 只负责 toggleExpand,避免与行选中互相干扰;利用现有 .tree-node-switcher/.tree-switcher-icon 样式(已存在于 index.scss,仅模板缺失)
  • toggleExpand 基准改为 expandedSet:基于用户展开集合增删,不再把过滤自动展开的祖先路径写回 expandedKeys,清除过滤后展开状态可正确还原
  • 行点击只选中:onContentClick 移除隐式 toggleExpand 调用(展开交给箭头),消除误触
  • 点击同步键盘焦点:onContentClick 中更新 activeKey.value = key.value 并 rowRef.value.focus(),保证 roving tabindex 与键盘导航起点正确
  • 键盘导航 ArrowRight/ArrowLeft 保持调用 toggleExpand 不变

3. 实现过滤关键词高亮(tree-node.vue)

  • 默认文本标题渲染时,依据 ctx.filter 与 filterVisible 中 matched 集合,用 split 匹配关键词片段,命中部分用 <span class="tree-highlight"> 包裹(大小写不敏感,与 filterTree 一致);自定义 #title 插槽场景不干预
  • 高亮逻辑抽为组件内方法,避免重复计算;每次渲染仅处理当前节点标题,开销 O(title 长度),无性能问题

4. 修复拖拽残留与样式清理(tree.vue + index.scss)

  • onDragLeave 中清空 dropKey/dropPosition(仍 emit dragleave);onDragEnd 已有兜底清理保留
  • 清理 index.scss 中未使用的 .tree-node.is-danger、.tree-leaf-icon 规则(switcher 相关样式因加回箭头而保留复用)

5. 修复 Demo(demo/tree.vue)

  • check-strictly 示例补充 v-model:checked-keys 绑定与输出展示;"checkedKeys(联动)"文案移回联动示例下方,修正演示语义

性能与可靠性

  • 全部派生状态为 computed 缓存,effectiveExpanded 修复后只依赖 expandedSet + filterResult,无重复遍历
  • 修改仅限 tree 组件目录与 demo 文件,不影响其他组件;无新依赖,无构建体积变化

目录结构

fms-vue/src/components/ui/tree/
├── tree.vue        # [MODIFY] 修复 filterExpand 未定义;补 defaultLoadedKeys;toggleExpand 基准改为 expandedSet;
│                   #          onDragLeave 清理 drop 状态;onContentClick 同步 activeKey/focus
├── tree-node.vue   # [MODIFY] 加回 switcher 箭头(ChevronRight/Loader,@click.stop);行点击只选中;
│                   #          实现过滤关键词高亮渲染
├── index.scss      # [MODIFY] 清理 .is-danger/.tree-leaf-icon 无用规则;switcher 样式保留复用
└── utils.js        # [不变] 纯函数逻辑正确,无需修改
fms-vue/src/components/ui/demo/tree.vue  # [MODIFY] 修正 check-strictly 示例绑定与文案

Agent Extensions

Skill

  • antdv-next
  • 用途:在重构展开/选中交互时,参考 Ant Design Tree 的 switcher 箭头交互、行点击与箭头职责分离、键盘导航规范,确保修复后的交互符合成熟组件库惯例
  • 预期结果:展开箭头点击展开/收起、行点击仅选中、键盘 ArrowRight/ArrowLeft 行为与成熟组件库一致,避免修复后再次出现交互职责混淆