# menu-management 重构任务 ## 任务目标 重构 `fms-vue/src/views/module/menu-management/index.vue`,在不改变现有功能和交互行为的前提下,降低入口文件复杂度,建立清晰的页面编排层和业务面板边界。 当前入口文件约 2,000 行,同时包含菜单树、菜单表单、权限点、权限库、多语言、保存流程、确认弹窗和页面样式。重构后入口组件应主要负责页面编排和跨区域业务流程。 ## 目标目录结构 优先采用以下结构,面板组件直接放在 `menu-management` 根目录,和 `index.vue` 同级: ```text src/views/module/menu-management/ ├── index.vue ├── MenuTreePanel.vue ├── MenuBasicPanel.vue ├── MenuPowersPanel.vue └── utils.js ``` 只有当某个面板内部确实出现多个独立子组件时,才增加更深层目录,例如: ```text 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` 等单词拼接命名,没有新增无意义的兼容转发层; - 至少运行受影响的单元测试;条件允许时运行: ```powershell cd fms-vue pnpm test -- tests/views/menu-unsaved-node-switch.spec.js pnpm lint pnpm build ``` - 若测试、lint 或构建被重构前已有的问题阻断,明确记录原因,不修改无关代码来掩盖问题。