refactor: 重构底部导航高亮逻辑,新增跨平台兼容与工具脚本
1. 抽离底部导航归属逻辑为纯函数resolveEntryTab,优化分包页面高亮规则,对齐iOS HIG规范 2. 新增页面Tab通配符映射,简化PAGE_TAB_MAP维护 3. 修复鸿蒙平台webview返回按钮适配问题 4. 新增pages.json校验与导航标题自动注入脚本 5. 优化启动页动画性能,提升合成渲染效率 6. 修复diy-picture组件v-for缺少key的警告 7. 清理鸿蒙平台多余的分包构建配置 8. 更新统计数据与store注释说明
This commit is contained in:
@@ -45,6 +45,7 @@
|
||||
|
||||
<script>
|
||||
import { adaptSubpackageUrl, checkTabBarActive, decodeEntity } from '@/common/js/util.js'
|
||||
import { resolveEntryTab } from '@/common/js/util-tabbar.js'
|
||||
import DiyMinx from './minx.js'
|
||||
// 底部导航栏
|
||||
export default {
|
||||
@@ -103,6 +104,11 @@ export default {
|
||||
packageEntryTab() {
|
||||
return this.$store.state.packageEntryTab;
|
||||
},
|
||||
// 响应 tabBarList 异步加载: 后端返回前 updateCurrentRoute 是 no-op,
|
||||
// tabBarList 就绪后必须重跑一次, 否则冷启动+秒点链接会出现"先不高亮→再突然高亮"
|
||||
tabBarReady() {
|
||||
return this.tabBarList && this.tabBarList.list && this.tabBarList.list.length > 0;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
cartChange: function (nval, oval) {
|
||||
@@ -118,7 +124,17 @@ export default {
|
||||
this.cartAnimation = animation.export();
|
||||
}, 300);
|
||||
}
|
||||
}
|
||||
},
|
||||
// tabBarList 异步加载完成后, 补一次 updateCurrentRoute
|
||||
// 修复: 冷启动时用户在 tabBarList 就绪前点击链接, 第一次 updateCurrentRoute 是 no-op
|
||||
tabBarReady: {
|
||||
handler(ready) {
|
||||
if (ready) {
|
||||
this.updateCurrentRoute();
|
||||
}
|
||||
},
|
||||
immediate: false,
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 统一归一化路径:currentPage.route 不带前导 '/',但 tab 的 wap_url 带前导 '/'
|
||||
@@ -145,45 +161,28 @@ export default {
|
||||
|
||||
// 归一化:补全前导 '/',确保后续 split('/') 后 parts[1]=分包名
|
||||
const newRoute = this._normalizeRoute(currentPage.route);
|
||||
const newRouteParts = newRoute.split('?')[0].split('/');
|
||||
const currentPackageName = newRouteParts[1] || '';
|
||||
const currentPackageName = newRoute.split('?')[0].split('/')[1] || '';
|
||||
|
||||
if (this.tabBarList && this.tabBarList.list && currentPackageName) {
|
||||
const tabUrls = this.tabBarList.list
|
||||
.filter(item => item.link && item.link.wap_url)
|
||||
.map(item => adaptSubpackageUrl(item.link.wap_url).split('?')[0]);
|
||||
// 收集历史栈路由 (排除当前页, 已 _normalizeRoute)
|
||||
// 注意: 组件里直接传 raw route 给 resolveEntryTab,
|
||||
// 内部 adaptSubpackageUrl 会兜底处理老路径 /pages/member/ 等
|
||||
const historyRoutes = currentPages.length >= 2
|
||||
? currentPages.slice(0, -1).map((p) =>
|
||||
p && p.route ? this._normalizeRoute(p.route) : null)
|
||||
: [];
|
||||
|
||||
// 1) 当前页面精确命中某个 tab → 该 tab 就是入口
|
||||
let entryTab = tabUrls.find(tabUrl => tabUrl === newRoute.split('?')[0]);
|
||||
|
||||
// 2) 当前页面在同一分包内 → 用分包名匹配
|
||||
if (!entryTab) {
|
||||
entryTab = tabUrls.find(tabUrl => {
|
||||
const tabParts = tabUrl.split('/');
|
||||
return tabParts[1] === currentPackageName;
|
||||
});
|
||||
}
|
||||
|
||||
// 3) 回退到上一页的分包匹配
|
||||
if (!entryTab) {
|
||||
const prevPage = currentPages[currentPages.length - 2];
|
||||
if (prevPage && prevPage.route) {
|
||||
const prevParts = this._normalizeRoute(prevPage.route).split('?')[0].split('/');
|
||||
const prevPackageName = prevParts[1] || '';
|
||||
entryTab = tabUrls.find(tabUrl => {
|
||||
const tabParts = tabUrl.split('/');
|
||||
return tabParts[1] === prevPackageName;
|
||||
});
|
||||
if (entryTab && prevPackageName !== currentPackageName) {
|
||||
// 上一页在别的分包 → 只记录到上一页的分包,不污染当前分包
|
||||
this.$store.commit('setPackageEntryTab', {
|
||||
...this.packageEntryTab,
|
||||
[prevPackageName]: entryTab
|
||||
});
|
||||
entryTab = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 调用纯函数 resolveEntryTab 完成 4 步查找
|
||||
// 规则: 从哪个 TabBar 出发, 非 tab 页就归属哪个 TabBar 高亮
|
||||
// 修复: home → diy 微页面 等跨分包导航被"同分包第一个 tab"误判的问题
|
||||
const entryTab = resolveEntryTab({
|
||||
currentPageRoute: newRoute,
|
||||
tabBarList: this.tabBarList,
|
||||
historyRoutes,
|
||||
// 传 NO_TAB_PAGES 进去, 让 login/pay/AI 等 modal 页不参与归属判定
|
||||
// 例子: home → login → diy 应算作 home → diy (login 是 modal)
|
||||
noTabPages: this.$util && this.$util.NO_TAB_PAGES ? this.$util.NO_TAB_PAGES : null,
|
||||
});
|
||||
|
||||
if (entryTab) {
|
||||
this.$store.commit('setPackageEntryTab', {
|
||||
@@ -253,8 +252,17 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
if (link.wap_url === this.$util.INDEX_PAGE_URL && this.name === 'DIY_VIEW_INDEX') {
|
||||
return true;
|
||||
if (this.name === 'DIY_VIEW_INDEX') {
|
||||
// DIY_VIEW_INDEX 短路: 当 name 是 DIY_VIEW_INDEX 时, 任意匹配的 tab 都高亮
|
||||
// 修复前: 只对 HOME (INDEX_PAGE_URL) 生效
|
||||
// 修复后: 适用于所有 tab 页面 (如 merchant DIY 首页、cart DIY 首页 等)
|
||||
// 前提: 当前页面本身就是该 tab 根, 链接 == 当前页 → step 1 早就命中
|
||||
// 这个短路主要兜底: "DIY_VIEW_INDEX 页面 + tab 链接" 的强语义关联
|
||||
const linkUrl = adaptSubpackageUrl(link.wap_url).split('?')[0];
|
||||
const currentUrl = currentPageRoute.split('?')[0];
|
||||
if (linkUrl === currentUrl) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return checkTabBarActive(link.wap_url, currentPageRoute, this.tabBarList, this.packageEntryTab, currentPageQuery);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<view data-component-name="diy-picture" class="diy-picture" :style="style">
|
||||
<view class="fui-picture">
|
||||
<view v-for="(item, index) in value.list" style="line-height: 0;">
|
||||
<view v-for="(item, index) in value.list" :key="index" style="line-height: 0;">
|
||||
<image mode="widthFix" style="width: 100%;height:auto" :src="$util.img(item.imageUrl)"
|
||||
v-if="item.link.wap_url" @tap.stop="handlerClick(item)" show-menu-by-longpress></image>
|
||||
<image mode="widthFix" style="width: 100%;height:auto" :src="$util.img(item.imageUrl)" v-else
|
||||
|
||||
Reference in New Issue
Block a user