Files
workspace/code/fms/ai-plans/TASK1.md
T
2026-09-04 17:31:36 +08:00

5.9 KiB
Raw Blame History

menu-management 重构任务

任务目标

重构 fms-vue/src/views/module/menu-management/index.vue,在不改变现有功能和交互行为的前提下,降低入口文件复杂度,建立清晰的页面编排层和业务面板边界。

当前入口文件约 2,000 行,同时包含菜单树、菜单表单、权限点、权限库、多语言、保存流程、确认弹窗和页面样式。重构后入口组件应主要负责页面编排和跨区域业务流程。

目标目录结构

优先采用以下结构,面板组件直接放在 menu-management 根目录,和 index.vue 同级:

src/views/module/menu-management/
├── index.vue
├── MenuTreePanel.vue
├── MenuBasicPanel.vue
├── MenuPowersPanel.vue
└── utils.js

只有当某个面板内部确实出现多个独立子组件时,才增加更深层目录,例如:

components/powers/PowerTable.vue
components/powers/PowerLibrary.vue

不要为了目录整齐而预先创建大量空组件或 composable。

职责边界

index.vue 编排层

保留以下职责:

  • 持有核心业务数据和基线:maindata、maindata_org、i18n_values、i18n_values_org、i18n_org、powers、powers_org;
  • 菜单树和菜单配置的加载入口;
  • handleSave → beforeSave → buildSaveData → 保存 → afterSave 主流程;
  • 未保存切换确认、刷新确认和统一确认弹窗;
  • 跨区域联动,例如菜单类型影响权限面板、菜单编码影响多语言键;
  • 将数据和业务回调传给子面板。

不要把同一份数据同时复制到父子组件,也不要让子面板自行加载或保存同一份菜单配置。

MenuTreePanel.vue

负责:

  • 菜单搜索框和树展示;
  • 展开、选中、拖拽、右键菜单的 UI 交互;
  • 菜单节点启用/停用的操作入口;
  • 通过事件通知父级新增、删除、移动、刷新和选择。

树数据加载、保存以及涉及其他区域的业务处理仍由 index.vue 决定。可将搜索关键字、展开键等纯 UI 状态放在本组件;如果父级需要控制它们,则使用 v-model。

MenuBasicPanel.vue

负责:

  • 菜单名称、编码、类型、路由、绑定模块、图标、排序号等表单字段;
  • 表单展示和字段级交互;
  • 多语言名称编辑入口;
  • 通过 v-model 直接读写 maindata,通过事件通知类型变化或需要打开多语言弹窗。

保存校验和最终请求数据构建仍由父级统一处理,除非是纯字段级校验。

MenuPowersPanel.vue

负责:

  • 当前菜单权限点表格;
  • 权限点新增、删除和编辑;
  • 权限来源库加载和导入;
  • 权限相关的表格选择状态和加载状态。

通过 v-model 读写 powers。如果权限库和当前权限点的实现确实需要独立复用,再继续拆分 components/powers/,否则保持在一个面板中。

utils.js

只放纯函数或无 Vue 状态依赖的逻辑,例如:

  • 树节点位置计算;
  • 兄弟节点排序号重排;
  • 目录节点非叶子标记;
  • 可独立测试的菜单数据转换。

只有一个简单调用点且放在入口中更易读的逻辑,不要为了拆文件强行抽取。

命名要求

  • 页面状态、局部变量、computed、方法使用 camelCase,例如 menuTreeLoading、selectedMenu、loadMenuConfig();
  • 与后端表结构对应的业务数据使用 snake_case,例如 maindata、maindata_org、i18n_values、i18n_values_org;
  • 数据和原始基线必须成对命名,使用 _org 分隔;禁止 maintableorg、subtablereceiveorg 等单词直接拼接;
  • 方法使用明确动词,例如 loadMenuConfig()、handleSave()、buildSaveData(),不要使用 loadMod()、dealData() 等不明确名称;
  • 组件文件名和组件名使用 PascalCase;模板中的 props、事件和具名 v-model 使用 kebab-case;
  • 不要因为重构而修改后端字段、接口字段、路由 meta、第三方组件 API 或已有公共事件名称。

重构约束

  1. 先完整阅读现有 index.vue、相关测试、utils/tree、utils/dataChanges 和被使用的公共组件,再开始修改。
  2. 保留现有功能:菜单树加载/刷新/搜索/拖拽/右键操作,菜单新增/删除,菜单类型联动,未保存切换确认,多语言编辑,权限点维护,权限库导入,保存 diff 和保存后重载。
  3. 父子组件通信优先使用 v-model 和语义明确的事件,不写 onMenuUpdate(section, data) 这类按 section 中转的通用回调。
  4. 不复制状态源,不在子面板中重复请求同一份菜单数据,不把保存主流程拆散到多个组件。
  5. 移动模板和样式时同步移动对应 CSS,避免保留失效样式;页面布局样式可以继续放在 index.vue。
  6. 注意当前工作区可能存在其他未提交改动;不得回滚、覆盖或顺手清理与本任务无关的改动。
  7. 删除或移动代码后,全局搜索旧导入、旧组件路径、旧方法名和旧事件名,确认没有残留。
  8. 不要求一次性重命名整个项目;只处理本次重构涉及的引用。

验收标准

  • index.vue 只保留页面编排、核心状态、加载保存流程和跨面板联动;
  • MenuTreePanel.vue、MenuBasicPanel.vue、MenuPowersPanel.vue 均有清晰单一职责;
  • 页面视觉和交互行为与重构前一致;
  • 菜单新增、编辑、删除、拖拽、刷新、切换未保存确认、多语言编辑、权限新增/删除/导入、保存和重载均可正常工作;
  • 没有 maintableorg 等单词拼接命名,没有新增无意义的兼容转发层;
  • 至少运行受影响的单元测试;条件允许时运行:
cd fms-vue
pnpm test -- tests/views/menu-unsaved-node-switch.spec.js
pnpm lint
pnpm build
  • 若测试、lint 或构建被重构前已有的问题阻断,明确记录原因,不修改无关代码来掩盖问题。