fix: 修复鸿蒙元服务TabBar跳转失效问题

1.  修复多处页面onTabItemTap事件,使用uni.reLaunch兜底鸿蒙下switchTab静默失败的问题
2.  全局混入onTabItemTap兜底未手动处理的页面
3.  优化路由跳转逻辑,针对鸿蒙环境增加switchTab失败兜底和超时强制跳转
4.  优化可选链调用和空值判断,提升代码健壮性
This commit is contained in:
2026-07-06 16:48:38 +08:00
parent 9815f09c1f
commit aa7d967422
6 changed files with 120 additions and 20 deletions

View File

@@ -590,6 +590,9 @@ export default {
*/
redirectTo(to, param = {}, mode = 'navigateTo') {
// 1. 拆分 path 与已有 query,避免后面 indexOf('?') 误判
// #ifdef MP-HARMONY
console.log('[navigate][HARMONY] redirectTo entry: to=', to, 'mode=', mode, 'param=', param);
// #endif
const queryIdx = to.indexOf('?');
let path = queryIdx === -1 ? to : to.substring(0, queryIdx);
const existingParams = {};
@@ -635,8 +638,36 @@ export default {
if (url.indexOf(tabBarUrl) == 0) {
// 首页使用switchTab(pages.json中注册的tabBar页面),其他tab页面使用reLaunch
// reLaunch关闭所有页面再打开目标页,确保页面栈与浏览器历史一致,避免返回按钮异常
// 鸿蒙元服务环境下系统 TabBar 点击 uni.switchTab 静默失败, 用 reLaunch 兜底
if (tabBarUrl == INDEX_PAGE_URL) {
// #ifdef MP-HARMONY
// 鸿蒙元服务环境下系统 TabBar 点击 uni.switchTab 静默失败, 用 reLaunch 兜底
// 用不携带 query 的干净路径, 避免 HarmonyOS 对带 query 的 tabBar 跳转有兼容性问题
const cleanUrl = url.split('?')[0];
console.log('[navigate][HARMONY] tabBar INDEX navigate, url=', cleanUrl);
let navigated = false;
uni.switchTab({
url: cleanUrl,
success: () => { navigated = true; console.log('[navigate][HARMONY] switchTab success:', cleanUrl); },
fail: (err) => {
navigated = true;
console.warn('[navigate][HARMONY] switchTab fail, fallback reLaunch:', cleanUrl, err);
uni.reLaunch({ url: cleanUrl });
}
});
// 兜底: 500ms 后若仍无回调或未完成, 强制 reLaunch
// (鸿蒙下 switchTab 经常静默失败, success/fail 都不调用)
setTimeout(() => {
if (!navigated) {
console.warn('[navigate][HARMONY] switchTab silent fail, forcing reLaunch:', cleanUrl);
uni.reLaunch({ url: cleanUrl });
}
}, 500);
// #endif
// #ifndef MP-HARMONY
uni.switchTab({ url });
// #endif
} else {
uni.reLaunch({ url });
}
@@ -661,7 +692,13 @@ export default {
const adaptedUrl = adaptSubpackageUrl(cleanUrl);
const inSystemTabBar = systemTabBarList.some(sysUrl => adaptedUrl === sysUrl || cleanUrl === sysUrl);
// 首页用switchTab,其他DIY tab根页用reLaunch确保页面栈干净
const navApi = inSystemTabBar ? (adaptedUrl === INDEX_PAGE_URL ? uni.switchTab : uni.reLaunch) : uni.reLaunch;
let navApi = inSystemTabBar ? (adaptedUrl === INDEX_PAGE_URL ? uni.switchTab : uni.reLaunch) : uni.reLaunch;
// 鸿蒙元服务环境下 uni.switchTab 有兼容性问题, 全部使用 reLaunch
// #ifdef MP-HARMONY
navApi = uni.reLaunch;
// #endif
navApi({
url,
fail: (err) => {
@@ -676,9 +713,18 @@ export default {
switch (mode) {
case 'tabbar':
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。重置页面栈,仅保留 tabBar 页面
// 鸿蒙元服务环境下 uni.switchTab 静默失败, 改用 reLaunch
// #ifdef MP-HARMONY
uni.reLaunch({
url
});
// #endif
// #ifndef MP-HARMONY
uni.switchTab({
url
});
// #endif
break;
case 'redirectTo':
// 关闭当前页面,跳转到应用内的某个页面。替换栈顶页面,长度不变(上限10层)

View File

@@ -49,7 +49,7 @@ export default {
* @type {boolean}
*/
isVisible() {
return this.$refs.videoPopup?.visible || false;
return Boolean(this.$refs?.videoPopup?.visible);
}
},
methods: {

26
main.js
View File

@@ -52,6 +52,32 @@ Vue.mixin({
}
});
// 鸿蒙元服务环境: 全局接管 onTabItemTap, 兜底系统 TabBar 点击
// 背景: 鸿蒙下 uni.switchTab 对系统 TabBar 点击静默失败
// 通过全局 mixin 覆盖所有未显式定义 onTabItemTap 的页面(子包动态 tab 页等),
// 显式定义 onTabItemTap 的页面(如 pages/empty/index.vue、index.js)优先级高于此 mixin
// #ifdef MP-HARMONY
Vue.mixin({
onTabItemTap(e) {
console.log('[TabBar][HARMONY] global onTabItemTap fired:', e);
if (!e || !e.pagePath) return;
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentPath = currentPage ? '/' + currentPage.route : '';
const targetPath = e.pagePath.startsWith('/') ? e.pagePath : '/' + e.pagePath;
console.log('[TabBar][HARMONY] onTabItemTap currentPath=', currentPath, 'targetPath=', targetPath);
// 已经在目标页则不重复跳转
if (currentPath === targetPath) return;
// 用干净路径(不带 query), 避免 HarmonyOS 对带 query 的 tabBar 跳转有兼容性问题
uni.reLaunch({
url: targetPath,
success: () => console.log('[TabBar][HARMONY] global reLaunch success:', targetPath),
fail: (err) => console.error('[TabBar][HARMONY] global reLaunch fail:', targetPath, err)
});
}
});
// #endif
App.mpType = 'app';
// 重写存储,增加前缀

View File

@@ -8,7 +8,21 @@
export default {
data() {
return {}
},
// 鸿蒙元服务环境: 系统 TabBar 点击 uni.switchTab 静默失败
// 手动接管 onTabItemTap, 用 uni.reLaunch 兜底, 确保 TabBar 跳转在鸿蒙下也能工作
// #ifdef MP-HARMONY
onTabItemTap(e) {
if (!e || !e.pagePath) return;
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentPath = currentPage ? '/' + currentPage.route : '';
const targetPath = e.pagePath.startsWith('/') ? e.pagePath : '/' + e.pagePath;
// 已经在目标页则不重复跳转
if (currentPath === targetPath) return;
uni.reLaunch({ url: targetPath });
}
// #endif
}
</script>

View File

@@ -7,6 +7,20 @@ export default {
shopInfo: null // 店铺信息
};
},
// 鸿蒙元服务环境: 系统 TabBar 点击 uni.switchTab 静默失败
// 手动接管 onTabItemTap, 用 uni.reLaunch 兜底, 确保 TabBar 跳转在鸿蒙下也能工作
// #ifdef MP-HARMONY
onTabItemTap(e) {
if (!e || !e.pagePath) return;
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentPath = currentPage ? '/' + currentPage.route : '';
const targetPath = e.pagePath.startsWith('/') ? e.pagePath : '/' + e.pagePath;
// 已经在目标页则不重复跳转
if (currentPath === targetPath) return;
uni.reLaunch({ url: targetPath });
},
// #endif
onLoad(option) {
// #ifdef H5
// H5地图选择位置回调数据

View File

@@ -60,7 +60,7 @@ export default {
// #endif
},
onUnload() {
if (!this.storeToken && this.$refs.login) this.$refs.login.cancelCompleteInfo();
!this.storeToken && this.$refs.login?.cancelCompleteInfo?.();
},
methods: {
getDiyInfo() {