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