7.4 KiB
Client Web 导航分级与移动侧栏设计
背景
apps/client-web 当前把业务总览、企业资料、企业成员、角色管理、菜单权限和头程订单全部渲染为同级侧栏链接。权威原型 docs/悦/头程下单/柏悦客户端.html 采用“一级业务域 + 二级具体任务”的导航结构,现有实现没有延续这一信息架构,也无法承接后续业务扩展。
Impeccable 验收还发现一个阻断性问题:720px 以下侧栏被隐藏,但页面上的菜单按钮没有打开移动导航的行为,导致移动端无法切换模块。
目标
- 将客户工作台的平铺菜单改为可扩展的两级分组导航。
- 保留现有路由、页面、文案、品牌颜色与 Element Plus 技术体系。
- 修复移动端导航不可用的问题。
- 让菜单节点显式携带图标与权限信息,避免依赖数组下标。
- 为后续真实权限集合接入保留清晰边界,不在本次伪造授权数据。
非目标
- 不新增原型中尚未实现的一键导入、快速下单、海外仓或财务结算入口。
- 不改变现有路由地址,不拆分当前
ModuleView.vue页面。 - 不照搬原型的紫色渐变视觉,不重做登录、注册或业务内容页。
- 不实现服务端权限校验,也不把前端菜单隐藏当作安全控制。
- 不新增测试框架;当前项目尚未声明测试脚本。
导航信息架构
采用两级分组,业务总览保留直接入口:
业务总览 /
头程业务 可展开分组
└── 头程订单 /orders/first-leg
企业管理 可展开分组
├── 企业资料 /company/profile
├── 企业成员 /organization/members
├── 角色管理 /organization/roles
└── 菜单权限 /organization/permissions
分组遵循原型的结构原则,但只呈现当前真实存在的客户端路由。后续功能只有在页面与路由实现后,才加入对应业务分组。
组件与数据结构
导航配置
新增客户端本地导航配置 src/navigation/clientNavigation.ts。定义客户端专用的 ClientNavigationNode,包含:
- 稳定
key; - 用户可见
title; - Lucide 图标组件;
- 可选
path; - 可选
permission; - 可选
children。
共享包中的 NavigationItem 仍保持单层公共模型,避免为了单个应用的壳层结构扩大跨项目契约。
侧栏菜单组件
新增独立的客户端侧栏菜单组件,使用 Element Plus 的 el-menu、el-sub-menu 与 el-menu-item:
active-path由当前路由提供;- 父分组可展开和收起;
- 当前路由所在分组默认展开;
- 叶子菜单负责实际路由跳转;
- 图标来自节点配置,不依赖渲染顺序;
- 桌面与移动端复用同一组件和同一份导航数据。
本轮不额外实现展开状态持久化;Element Plus 在当前会话中维护用户开合状态,且当前路由所在分组始终可识别。持久化不是修复平铺结构与移动阻断所必需的能力。
应用壳层
AppLayout.vue 继续负责品牌、租户、用户和页面标题,同时增加:
mobileMenuOpen状态;- 移动菜单按钮的
aria-expanded; - 遮罩关闭;
- 路由切换后自动关闭;
- Escape 键关闭;
- 打开时阻止背景页面滚动;
- 退出确认取消时不产生未处理异常。
桌面侧栏保持固定宽度和现有绿色服务型视觉,不引入后台的深色侧栏,也不增加桌面折叠模式。
交互与状态流
桌面端
- 路由加载后,菜单以
route.path高亮对应叶子。 - “业务总览”为直接入口。
- “头程业务”和“企业管理”为分组触发器。
- 当前页面属于某分组时,该分组保持展开并显示父级激活语义。
- 用户可以独立展开或收起其他分组。
移动端
- 720px 以下侧栏移出视口,而不是使用
display: none永久移除。 - 点击页面标题前的菜单按钮打开抽屉并显示遮罩。
- 点击遮罩、按 Escape 或选择任一叶子路由后关闭抽屉。
- 抽屉打开时禁止背景滚动,关闭或组件卸载时恢复。
- 抽屉沿用完整租户导航,不维护第二份移动菜单。
权限
导航节点继续携带权限编码。当前模拟用户没有可靠的权限集合,因此静态阶段显示全部已实现菜单。真实认证接口返回权限集合后,再增加叶子过滤;父分组没有可访问子项时隐藏。服务端必须继续执行租户与权限校验。
视觉与可访问性
- 保留现有
--primary、--navy、--border和--muted设计令牌。 - 一级分组与二级叶子通过缩进、字号、颜色和激活背景形成清晰层级。
- 分组触发器与移动菜单按钮使用真实可聚焦控件。
- 保持可见
:focus-visible状态,不只依赖 hover 或颜色表达当前状态。 - 菜单触控目标不低于约 44px。
- 二级菜单文本允许单行省略,避免长租户业务名称破坏侧栏宽度。
- 侧栏导航区域允许纵向滚动;底部帮助区保持可达。
- 320px、720px 与桌面宽度均不能依赖水平滚动完成导航。
错误与边界处理
- 用户取消退出确认时保持当前页面,不产生控制台未处理异常。
- 移动抽屉在快速路由切换、浏览器后退和组件卸载后不得残留锁定滚动状态。
- 不存在或被移除的路由继续走现有兜底重定向。
- 当前不虚构客户经理电话、微信或帮助中心链接;帮助区保留为信息提示,后续有真实渠道后再做可执行入口。
- 权限为空或数据尚未加载时,本轮不提前隐藏菜单,避免模拟阶段出现无法恢复的空侧栏。
实施范围
预计修改或新增:
apps/client-web/src/navigation/clientNavigation.tsapps/client-web/src/components/ClientSidebarMenu.vueapps/client-web/src/layouts/AppLayout.vueapps/client-web/src/router/index.tsapps/client-web/src/styles/index.css
仅当实现需要声明自动导入组件时,依赖现有插件自动生成声明,不手工编辑 auto-imports.d.ts 或 components.d.ts。
验收与验证
自动验证
在 apps/client-web 执行:
pnpm typecheck
pnpm build
项目当前没有 test 或 lint 脚本,因此不声称相应检查通过,也不为本次导航改动引入整套测试设施。
Impeccable 验收
- 运行一次机械检测,目标覆盖本次变更的 Vue 文件。
- 桌面检查:一级分组、二级缩进、当前路由高亮、可见焦点和侧栏滚动。
- 720px 检查:断点切换时导航仍可达。
- 320px 检查:抽屉、遮罩、触控目标与页面内容不发生水平溢出。
- 浏览器可用时检查菜单打开、选择路由、遮罩关闭和 Escape 关闭;若浏览器不可用,明确记录回退证据,不伪装成已完成视觉实测。
完成标准
- 侧栏不再把全部功能放在一级菜单。
- 当前六个页面入口全部可达,路由地址不变。
- 桌面端当前页面与父分组状态清晰。
- 720px 以下菜单按钮能够打开和关闭真实导航抽屉。
- 导航图标不会因菜单调序或新增分组而错位。
- 未实现的原型功能不会作为无效入口出现。
- 类型检查、生产构建与 Impeccable 检测无未解释失败。