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