refactor(diy-bottom-nav): 优化 TabBar 高亮逻辑,新增来源参数记忆和页面映射规则
1. 新增 redirectLink 处理,添加 from_tab 来源参数实现 Tab 高亮记忆 2. 新增 TAB_BAR_KEYS、NO_TAB_PAGES、PAGE_TAB_MAP 统一管理 Tab 归属配置 3. 重构 checkTabBarActive 函数,增加页面精确映射和来源参数判断逻辑 4. 兼容小程序和 H5 的页面 query 参数获取
This commit is contained in:
@@ -128,6 +128,144 @@ export const PAGE_KEY_MAP = {
|
||||
PAGE_WEBVIEW: '/pages_tool/webview/webview'
|
||||
};
|
||||
|
||||
// ================== TabBar 高亮映射配置 ==================
|
||||
|
||||
// TabBar 标识(使用各 Tab 根页面的 wap_url)
|
||||
export const TAB_BAR_KEYS = {
|
||||
HOME: '/pages/index/index',
|
||||
CATEGORY: '/pages_goods/category',
|
||||
MERCHANT: '/pages_promotion/merch/merchcategory',
|
||||
CART: '/pages_goods/cart',
|
||||
MEMBER: '/pages_tool/member/index'
|
||||
};
|
||||
|
||||
// 明确不归属任何 TabBar 的独立页面:进入这些页面时 TabBar 全不亮
|
||||
export const NO_TAB_PAGES = new Set([
|
||||
// 登录/注册/找回密码
|
||||
'/pages_tool/login/login',
|
||||
'/pages_tool/login/register',
|
||||
'/pages_tool/login/find',
|
||||
|
||||
// 支付/收银流程
|
||||
'/pages_tool/pay/index',
|
||||
'/pages_tool/pay/wx_pay',
|
||||
'/pages_tool/pay/cashier',
|
||||
'/pages_tool/pay/result',
|
||||
|
||||
// 订单独立流程页(详情/退款/物流/评价)
|
||||
'/pages_order/payment',
|
||||
'/pages_order/detail',
|
||||
'/pages_order/detail_local_delivery',
|
||||
'/pages_order/detail_pickup',
|
||||
'/pages_order/detail_point',
|
||||
'/pages_order/refund',
|
||||
'/pages_order/refund_detail',
|
||||
'/pages_order/refund_goods_select',
|
||||
'/pages_order/refund_type_select',
|
||||
'/pages_order/refund_batch',
|
||||
'/pages_order/logistics',
|
||||
'/pages_order/activist',
|
||||
'/pages_order/order/evaluate',
|
||||
'/pages_order/detail_virtual',
|
||||
|
||||
// 表单
|
||||
'/pages_tool/form/form',
|
||||
'/pages_tool/form/formdata',
|
||||
|
||||
// 外部/特殊页面
|
||||
'/pages_tool/webview/webview',
|
||||
'/pages_tool/ai-chat/index',
|
||||
'/pages_tool/vr/index',
|
||||
'/pages_tool/cases/index',
|
||||
'/pages_tool/contact/contact',
|
||||
'/pages_tool/weapp/order_shipping',
|
||||
'/pages_tool/file-preview/file-preview',
|
||||
|
||||
// 帮助/公告/文章详情
|
||||
'/pages_tool/help/detail',
|
||||
'/pages_tool/notice/detail',
|
||||
'/pages_tool/article/detail',
|
||||
|
||||
// 介质材料
|
||||
'/pages_tool/seal/structure',
|
||||
'/pages_tool/seal/medium/detail'
|
||||
]);
|
||||
|
||||
// 页面级 TabBar 精确归属映射(key: 页面路径, value: TabBar 根路径)
|
||||
// 未在此映射中的页面,优先走 NO_TAB_PAGES 判断,其次走同分包回退逻辑
|
||||
export const PAGE_TAB_MAP = {
|
||||
// 首页
|
||||
'/pages/index/index': TAB_BAR_KEYS.HOME,
|
||||
'/pages/empty/index': TAB_BAR_KEYS.HOME,
|
||||
|
||||
// 分类
|
||||
'/pages_goods/category': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_goods/list': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_goods/detail': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_tool/goods/search': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_tool/goods/brand': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_tool/goods/coupon': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_tool/goods/coupon_receive': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_tool/goods/evaluate': TAB_BAR_KEYS.CATEGORY,
|
||||
'/pages_tool/goods/not_exist': TAB_BAR_KEYS.CATEGORY,
|
||||
|
||||
// 入驻企业
|
||||
'/pages_promotion/merch/merchcategory': TAB_BAR_KEYS.MERCHANT,
|
||||
'/pages_promotion/merch/detail': TAB_BAR_KEYS.MERCHANT,
|
||||
|
||||
// 购物车
|
||||
'/pages_goods/cart': TAB_BAR_KEYS.CART,
|
||||
|
||||
// 我的(会员中心及子页面)
|
||||
'/pages_tool/member/index': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/info': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/info_edit': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/address': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/address_edit': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/account': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/account_edit': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/balance': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/balance_detail': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/point': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/point_detail': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/coupon': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/level': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/level_growth_rules': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/card': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/card_buy': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/card_log': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/card_agreement': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/invite_friends': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/collection': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/footprint': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/contact': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/modify_face': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/pay_password': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/apply_withdrawal': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/withdrawal': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/withdrawal_detail': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/cancellation': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/cancelstatus': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/cancelsuccess': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/cancelrefuse': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/assets': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/signin': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/member/bind_mobile': TAB_BAR_KEYS.MEMBER,
|
||||
|
||||
// 我的频道下的其他功能页
|
||||
'/pages_order/list': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/recharge/list': TAB_BAR_KEYS.MEMBER,
|
||||
'/pages_tool/recharge/order_list': TAB_BAR_KEYS.MEMBER,
|
||||
|
||||
// 帮助/公告/文章列表属于首页频道
|
||||
'/pages_tool/help/list': TAB_BAR_KEYS.HOME,
|
||||
'/pages_tool/notice/list': TAB_BAR_KEYS.HOME,
|
||||
'/pages_tool/article/list': TAB_BAR_KEYS.HOME,
|
||||
|
||||
// 文件列表(视业务可归首页,暂不归任何 Tab)
|
||||
'/pages_tool/files/list': null
|
||||
};
|
||||
|
||||
/**
|
||||
* 根据 page_key + params 解析得到实际跳转URL
|
||||
* @param {string} page_key 页面语义常量,如 PAGE_GOODS_LIST
|
||||
@@ -366,9 +504,10 @@ export const isTabBarRootPage = (pagePath, tabBarList) => {
|
||||
* @param {string} currentPageRoute 当前页面路径 /pages_goods/category
|
||||
* @param {Object} tabBarList tabBar配置对象,用于动态判断
|
||||
* @param {Object} packageEntryTab 追踪每个分包的入口Tab { 'pages_goods': '/pages_goods/category' }
|
||||
* @param {Object} currentPageQuery 当前页面 query 参数,用于读取 from_tab 来源记忆
|
||||
* @returns {boolean} 是否激活
|
||||
*/
|
||||
export const checkTabBarActive = (linkUrl, currentPageRoute, tabBarList, packageEntryTab) => {
|
||||
export const checkTabBarActive = (linkUrl, currentPageRoute, tabBarList, packageEntryTab, currentPageQuery = {}) => {
|
||||
// 1) 归一化 linkUrl:统一前导 '/' + 子包路径适配 + 去除 query
|
||||
const normalizedLink = _normalizePath(linkUrl);
|
||||
const normalizedCurrent = _normalizePath(currentPageRoute);
|
||||
@@ -378,7 +517,10 @@ export const checkTabBarActive = (linkUrl, currentPageRoute, tabBarList, package
|
||||
// 2) 精确匹配:当前页面就是 linkUrl 指向的页面
|
||||
if (normalizedLink === normalizedCurrent) return true;
|
||||
|
||||
// 3) 若传入 tabBarList,使用动态判断逻辑
|
||||
// 3) 独立流程页:不点亮任何 Tab
|
||||
if (NO_TAB_PAGES.has(normalizedCurrent)) return false;
|
||||
|
||||
// 4) 若传入 tabBarList,使用动态判断逻辑
|
||||
if (tabBarList && tabBarList.list && Array.isArray(tabBarList.list)) {
|
||||
const tabUrls = tabBarList.list
|
||||
.filter(item => item.link && item.link.wap_url)
|
||||
@@ -387,13 +529,27 @@ export const checkTabBarActive = (linkUrl, currentPageRoute, tabBarList, package
|
||||
// 检查当前 linkUrl 是否是合法的 tab URL
|
||||
if (!tabUrls.includes(normalizedLink)) return false;
|
||||
|
||||
// 找出当前页面所属的 tab
|
||||
const matchingTabUrl = _findMatchingTabUrl(currentPageRoute, tabBarList, packageEntryTab);
|
||||
// 5) 页面级 Tab 精确绑定
|
||||
const mappedTabUrl = PAGE_TAB_MAP[normalizedCurrent];
|
||||
if (mappedTabUrl) {
|
||||
return normalizedLink === _normalizePath(mappedTabUrl);
|
||||
}
|
||||
if (mappedTabUrl === null) return false;
|
||||
|
||||
// 当前页面若命中某个 tab,则只有该 tab 高亮
|
||||
// 6) 来源记忆兜底:从哪个 Tab 跳转过来,就保持那个 Tab 高亮
|
||||
const fromTab = currentPageQuery.from_tab;
|
||||
if (fromTab) {
|
||||
const normalizedFromTab = _normalizePath(fromTab);
|
||||
if (tabUrls.includes(normalizedFromTab)) {
|
||||
return normalizedLink === normalizedFromTab;
|
||||
}
|
||||
}
|
||||
|
||||
// 7) 分包入口追踪:通过 updateCurrentRoute 写入的入口 tab
|
||||
const matchingTabUrl = _findMatchingTabUrl(currentPageRoute, tabBarList, packageEntryTab);
|
||||
if (matchingTabUrl) return normalizedLink === matchingTabUrl;
|
||||
|
||||
// 4) 同分包回退:linkUrl 和当前页面在同一分包 → 高亮
|
||||
// 8) 同分包回退:linkUrl 和当前页面在同一分包 → 高亮
|
||||
const linkPackage = _getPackageName(normalizedLink);
|
||||
const currentPackage = _getPackageName(normalizedCurrent);
|
||||
return linkPackage && currentPackage && linkPackage === currentPackage;
|
||||
|
||||
@@ -197,6 +197,7 @@ export default {
|
||||
},
|
||||
redirectTo(link) {
|
||||
this.$emit('callback');
|
||||
const redirectLink = link ? { ...link } : link;
|
||||
|
||||
if (link && link.wap_url) {
|
||||
const decodedUrl = decodeEntity(link.wap_url);
|
||||
@@ -209,9 +210,27 @@ export default {
|
||||
[packageName]: adaptedUrl.split('?')[0]
|
||||
});
|
||||
}
|
||||
|
||||
// 若目标页面不是 TabBar 根页面,追加 from_tab 来源参数,
|
||||
// 用于非 Tab 页面的 TabBar 高亮记忆
|
||||
if (this.tabBarList && this.tabBarList.list) {
|
||||
const tabUrls = this.tabBarList.list
|
||||
.filter(item => item.link && item.link.wap_url)
|
||||
.map(item => adaptSubpackageUrl(decodeEntity(item.link.wap_url)).split('?')[0]);
|
||||
if (!tabUrls.includes(adaptedUrl.split('?')[0])) {
|
||||
const currentPages = getCurrentPages();
|
||||
const currentPage = currentPages[currentPages.length - 1];
|
||||
const currentTab = currentPage && currentPage.route
|
||||
? tabUrls.find(tabUrl => checkTabBarActive(tabUrl, '/' + currentPage.route, this.tabBarList, this.packageEntryTab))
|
||||
: null;
|
||||
if (currentTab) {
|
||||
redirectLink.from_tab = currentTab;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.$util.diyRedirectTo(link);
|
||||
this.$util.diyRedirectTo(redirectLink);
|
||||
},
|
||||
verify(link) {
|
||||
if (link == null || link == '' || !link.wap_url) return false;
|
||||
@@ -222,11 +241,23 @@ export default {
|
||||
? this._normalizeRoute(currentPage.route)
|
||||
: '';
|
||||
|
||||
// 读取当前页面 query 参数(兼容小程序与 H5)
|
||||
let currentPageQuery = {};
|
||||
if (currentPage) {
|
||||
if (currentPage.options) {
|
||||
currentPageQuery = currentPage.options;
|
||||
} else if (currentPage.$page && currentPage.$page.options) {
|
||||
currentPageQuery = currentPage.$page.options;
|
||||
} else if (currentPage.$route && currentPage.$route.query) {
|
||||
currentPageQuery = currentPage.$route.query;
|
||||
}
|
||||
}
|
||||
|
||||
if (link.wap_url === this.$util.INDEX_PAGE_URL && this.name === 'DIY_VIEW_INDEX') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return checkTabBarActive(link.wap_url, currentPageRoute, this.tabBarList, this.packageEntryTab);
|
||||
return checkTabBarActive(link.wap_url, currentPageRoute, this.tabBarList, this.packageEntryTab, currentPageQuery);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user