fix: 修复鸿蒙元服务TabBar跳转失效问题
1. 修复多处页面onTabItemTap事件,使用uni.reLaunch兜底鸿蒙下switchTab静默失败的问题 2. 全局混入onTabItemTap兜底未手动处理的页面 3. 优化路由跳转逻辑,针对鸿蒙环境增加switchTab失败兜底和超时强制跳转 4. 优化可选链调用和空值判断,提升代码健壮性
This commit is contained in:
@@ -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 });
|
||||
}
|
||||
@@ -660,8 +691,14 @@ export default {
|
||||
if (isDiyTabRoot) {
|
||||
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;
|
||||
// 首页用switchTab,其他DIY tab根页用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层)
|
||||
|
||||
@@ -49,7 +49,7 @@ export default {
|
||||
* @type {boolean}
|
||||
*/
|
||||
isVisible() {
|
||||
return this.$refs.videoPopup?.visible || false;
|
||||
return Boolean(this.$refs?.videoPopup?.visible);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
58
main.js
58
main.js
@@ -14,22 +14,22 @@ import globalConfig from './common/js/golbalConfig.js';
|
||||
import {
|
||||
uniStorage
|
||||
} from './common/js/storage.js'
|
||||
import configExternal from './common/js/config-external.js'
|
||||
import PrivacyManager from './common/js/privacy.js'
|
||||
import splashState from './common/js/splash-state.js'
|
||||
|
||||
Vue.prototype.$store = store //挂在vue
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.prototype.$util = Util;
|
||||
Vue.prototype.$api = Http;
|
||||
|
||||
Vue.prototype.$langConfig = Lang; //语言包对象
|
||||
Vue.prototype.$lang = Lang.lang; //解析语言包
|
||||
|
||||
Vue.prototype.$config = Config;
|
||||
|
||||
import configExternal from './common/js/config-external.js'
|
||||
import PrivacyManager from './common/js/privacy.js'
|
||||
import splashState from './common/js/splash-state.js'
|
||||
|
||||
Vue.prototype.$store = store //挂在vue
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.prototype.$util = Util;
|
||||
Vue.prototype.$api = Http;
|
||||
|
||||
Vue.prototype.$langConfig = Lang; //语言包对象
|
||||
Vue.prototype.$lang = Lang.lang; //解析语言包
|
||||
|
||||
Vue.prototype.$config = Config;
|
||||
|
||||
Vue.prototype.$privacy = PrivacyManager; //全局隐私管理器
|
||||
|
||||
|
||||
@@ -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';
|
||||
|
||||
// 重写存储,增加前缀
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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地图选择位置回调数据
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user