修改页面结构
This commit is contained in:
290
docs/admin/ORDER_MENU_HIGHLIGHT_FIX.md
Normal file
290
docs/admin/ORDER_MENU_HIGHLIGHT_FIX.md
Normal file
@@ -0,0 +1,290 @@
|
||||
# 订单菜单高亮问题修复文档
|
||||
|
||||
## 问题描述
|
||||
|
||||
在订单管理页面,无论点击哪个订单子菜单项(订单统计、订单管理、售后订单等),菜单高亮显示都始终停留在"订单管理",不会切换到实际选中的菜单项。
|
||||
|
||||
### 根本原因(两层)
|
||||
|
||||
#### 1. 路径标准化移除query参数
|
||||
|
||||
所有订单子菜单项使用相同的路由路径 `/pages/mall/admin/order-management`,仅通过不同的query参数(?tab=stats、?tab=list等)来区分。
|
||||
|
||||
在 `layouts/admin/utils/nav.uts` 中的 `normalize()` 函数会将路径标准化,**移除query参数部分**:
|
||||
|
||||
```uts
|
||||
// 旧代码 - 问题所在
|
||||
function normalize(p: string): string {
|
||||
if (!p) return ''
|
||||
const s = p.startsWith('/') ? p.slice(1) : p
|
||||
const q = s.indexOf('?')
|
||||
return q >= 0 ? s.slice(0, q) : s // ❌ 移除了 ?tab=xxx
|
||||
}
|
||||
```
|
||||
|
||||
这导致所有订单子菜单路径被标准化为相同值:
|
||||
|
||||
- `/pages/mall/admin/order-management?tab=stats` → `pages/mall/admin/order-management`
|
||||
- `/pages/mall/admin/order-management?tab=list` → `pages/mall/admin/order-management` ✓(第一个命中)
|
||||
- `/pages/mall/admin/order-management?tab=aftersale` → `pages/mall/admin/order-management` ✓(第一个命中)
|
||||
|
||||
#### 2. 页面硬编码currentPage
|
||||
|
||||
订单管理页面 (`pages/mall/admin/order-management.uvue`) 硬编码了:
|
||||
|
||||
```typescript
|
||||
const currentPage = ref<string>("order-list"); // ❌ 始终是 order-list
|
||||
```
|
||||
|
||||
导致即使路由正确,布局组件收到的activeSubId也始终是`order-list`。
|
||||
|
||||
---
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 修改1:保留query参数在路径标准化中
|
||||
|
||||
**文件:** `layouts/admin/utils/nav.uts`
|
||||
|
||||
```uts
|
||||
// 新代码 - 支持 query 参数匹配
|
||||
function normalize(p: string): string {
|
||||
if (!p) return ''
|
||||
const s = p.startsWith('/') ? p.slice(1) : p
|
||||
// ✅ 保留完整路径(包括query参数)以支持 tab 参数的正确匹配
|
||||
return s
|
||||
}
|
||||
```
|
||||
|
||||
### 修改2:增强getCurrentRoutePath()支持query参数
|
||||
|
||||
**文件:** `layouts/admin/utils/nav.uts`
|
||||
|
||||
```typescript
|
||||
export function getCurrentRoutePath(): string {
|
||||
const pages = getCurrentPages();
|
||||
const last: any = pages[pages.length - 1];
|
||||
// #ifdef H5
|
||||
if (last?.route) {
|
||||
// H5 环境下从 location.search 获取 query 参数
|
||||
const qs = typeof window !== "undefined" ? window.location.search : "";
|
||||
return `/${last.route}${qs}`;
|
||||
}
|
||||
return "";
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
// 小程序/App 环境处理
|
||||
if (last?.route) {
|
||||
const qs = last?.$page?.options
|
||||
? new URLSearchParams(last.$page.options).toString()
|
||||
: "";
|
||||
return `/${last.route}${qs ? "?" + qs : ""}`;
|
||||
}
|
||||
return last?.$page?.fullPath || "";
|
||||
// #endif
|
||||
}
|
||||
```
|
||||
|
||||
### 修改3:页面动态设置currentPage
|
||||
|
||||
**文件:** `pages/mall/admin/order-management.uvue`
|
||||
|
||||
```typescript
|
||||
onLoad((options: Record<string, string | undefined>) => {
|
||||
params.value = JSON.stringify(options ?? {});
|
||||
|
||||
// ✅ 改:根据 tab 参数动态设置 currentPage,以实现正确的菜单高亮
|
||||
const tab = options?.tab as string | undefined;
|
||||
if (tab) {
|
||||
// 从 tab 值映射到菜单 id(保持与 menu.uts 中的定义一致)
|
||||
const tabToMenuIdMap: Record<string, string> = {
|
||||
stats: "order-stats",
|
||||
list: "order-list",
|
||||
aftersale: "order-aftersale",
|
||||
cashier: "order-cashier",
|
||||
verify: "order-verify",
|
||||
config: "order-config",
|
||||
};
|
||||
|
||||
const menuId = tabToMenuIdMap[tab];
|
||||
if (menuId) {
|
||||
currentPage.value = menuId;
|
||||
|
||||
// 同时更新页面标题
|
||||
const titleMap: Record<string, string> = {
|
||||
"order-stats": "订单统计",
|
||||
"order-list": "订单管理",
|
||||
"order-aftersale": "售后订单",
|
||||
"order-cashier": "收银订单",
|
||||
"order-verify": "核销记录",
|
||||
"order-config": "订单配置",
|
||||
};
|
||||
title.value = titleMap[menuId] || "订单管理";
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 影响范围
|
||||
|
||||
此修改**直接影响所有使用query参数进行功能区分的页面**:
|
||||
|
||||
### 受益的菜单项:
|
||||
|
||||
1. **订单管理** - 使用 ?tab 参数区分不同订单视图 ✅
|
||||
2. **营销管理** - 使用 ?tab 参数区分不同营销功能(建议采用相同方案)
|
||||
3. **其他tab式菜单** - 同样依赖query参数的任何菜单
|
||||
|
||||
### 兼容性:
|
||||
|
||||
- ✅ 不影响不使用query参数的菜单项
|
||||
- ✅ 不影响传统路由参数(如 :id)的菜单项
|
||||
- ✅ 向后兼容现有所有路由结构
|
||||
|
||||
---
|
||||
|
||||
## 菜单结构参考
|
||||
|
||||
### 订单管理菜单(正确结构)
|
||||
|
||||
```typescript
|
||||
{
|
||||
id: 'order',
|
||||
title: '订单',
|
||||
icon: '/static/order.svg',
|
||||
path: '/pages/mall/admin/order-management?tab=list',
|
||||
groups: [
|
||||
{
|
||||
id: 'order-management',
|
||||
title: '订单管理',
|
||||
children: [
|
||||
{
|
||||
id: 'order-stats',
|
||||
title: '订单统计',
|
||||
path: '/pages/mall/admin/order-management?tab=stats' // ✓ 唯一的tab值
|
||||
},
|
||||
{
|
||||
id: 'order-list',
|
||||
title: '订单管理',
|
||||
path: '/pages/mall/admin/order-management?tab=list' // ✓ 唯一的tab值
|
||||
},
|
||||
{
|
||||
id: 'order-aftersale',
|
||||
title: '售后订单',
|
||||
path: '/pages/mall/admin/order-management?tab=aftersale' // ✓ 唯一的tab值
|
||||
},
|
||||
// ... 其他订单菜单项
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 高亮匹配流程(修复后)
|
||||
|
||||
```
|
||||
用户点击"售后订单"菜单
|
||||
↓
|
||||
导航至: /pages/mall/admin/order-management?tab=aftersale
|
||||
↓
|
||||
order-management.uvue onLoad() 获取 tab=aftersale
|
||||
↓
|
||||
映射到菜单id: order-aftersale
|
||||
↓
|
||||
设置 currentPage.value = 'order-aftersale'
|
||||
↓
|
||||
AdminLayout 接收 currentPage='order-aftersale'
|
||||
↓
|
||||
findActiveByCurrentPage() 匹配菜单项
|
||||
↓
|
||||
设置 activeSubId = 'order-aftersale'
|
||||
↓
|
||||
高亮显示: "售后订单" ✓ 正确
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 测试检查清单
|
||||
|
||||
- [ ] 订单统计 - 点击并验证高亮显示正确
|
||||
- [ ] 订单管理 - 点击并验证高亮显示正确
|
||||
- [ ] 售后订单 - 点击并验证高亮显示正确
|
||||
- [ ] 收银订单 - 点击并验证高亮显示正确
|
||||
- [ ] 核销记录 - 点击并验证高亮显示正确
|
||||
- [ ] 订单配置 - 点击并验证高亮显示正确
|
||||
- [ ] 页面刷新 - 验证高亮仍能正确还原(基于当前URL的tab参数)
|
||||
- [ ] 其他菜单 - 验证无回归,其他菜单仍能正常工作
|
||||
|
||||
---
|
||||
|
||||
## 与营销管理的对应方案
|
||||
|
||||
营销管理页面使用同样的?tab结构,建议对 `pages/mall/admin/marketing-management.uvue` 采用同样的修复方案:
|
||||
|
||||
```typescript
|
||||
// marketing-management.uvue 中的 onLoad
|
||||
onLoad((options: Record<string, string | undefined>) => {
|
||||
const tab = options?.tab as string | undefined;
|
||||
if (tab) {
|
||||
const tabToMenuIdMap: Record<string, string> = {
|
||||
stats: "marketing-stats",
|
||||
coupon: "coupon-list",
|
||||
points: "points-stats",
|
||||
member: "member-type",
|
||||
// ... 其他映射
|
||||
};
|
||||
const menuId = tabToMenuIdMap[tab];
|
||||
if (menuId) {
|
||||
currentPage.value = menuId;
|
||||
// 更新标题
|
||||
}
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 提交信息
|
||||
|
||||
```
|
||||
fix: 修复订单菜单高亮问题 - 支持query参数的完整路径匹配
|
||||
|
||||
问题:
|
||||
- 订单菜单的所有子项高亮都显示为"订单管理"
|
||||
- 原因:路径标准化移除query参数,导致路径重复;页面硬编码currentPage
|
||||
|
||||
解决方案:
|
||||
1. 保留query参数在路径标准化中(nav.uts normalize函数)
|
||||
2. 增强getCurrentRoutePath()支持完整URL含query参数
|
||||
3. 页面根据tab参数动态设置currentPage,实现菜单项与页面的同步
|
||||
|
||||
文件修改:
|
||||
- layouts/admin/utils/nav.uts (normalize + getCurrentRoutePath)
|
||||
- pages/mall/admin/order-management.uvue (onLoad中的tab处理)
|
||||
|
||||
验证:点击各个订单子菜单,高亮正确切换
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
- [nav.uts](../layouts/admin/utils/nav.uts) - 导航高亮逻辑
|
||||
- [menu.uts](../layouts/admin/utils/menu.uts) - 菜单结构定义
|
||||
- [order-management.uvue](../pages/mall/admin/order-management.uvue) - 订单管理页面
|
||||
- [AdminLayout.uvue](../layouts/admin/AdminLayout.uvue) - 布局组件
|
||||
- [AdminSubsider.uvue](../layouts/admin/components/AdminSubsider.uvue) - 二级侧边栏
|
||||
|
||||
---
|
||||
|
||||
## 修复日期
|
||||
|
||||
2026年1月31日
|
||||
|
||||
## 修复版本
|
||||
|
||||
v1.1.0
|
||||
Reference in New Issue
Block a user