小程序解决页面导航错误

This commit is contained in:
zhonghua1
2026-01-20 09:03:50 +08:00
parent 9c00db8ff5
commit 4ebeec45bc
5 changed files with 569 additions and 82 deletions

View File

@@ -8,63 +8,63 @@ Component({
{
key: 'reception',
text: '接待',
pagePath: '/pages/reception/reception',
pagePath: 'pages/reception/reception', // 使用与 pages.json 一致的格式(不带前导斜杠)
iconPath: '/static/tabbar/reception.png',
selectedIconPath: '/static/tabbar/reception_active.png',
},
{
key: 'customer',
text: '客户',
pagePath: '/pages/customer/customer',
pagePath: 'pages/customer/customer',
iconPath: '/static/tabbar/customer.png',
selectedIconPath: '/static/tabbar/customer_active.png',
},
{
key: 'team',
text: '团队',
pagePath: '/pages/team/team',
pagePath: 'pages/team/team',
iconPath: '/static/tabbar/team.png',
selectedIconPath: '/static/tabbar/team_active.png',
},
{
key: 'ucenter',
text: '我的',
pagePath: '/pages/ucenter/ucenter',
pagePath: 'pages/ucenter/ucenter',
iconPath: '/static/tabbar/me.png',
selectedIconPath: '/static/tabbar/me_active.png',
},
{
key: 'meeting_summary',
text: '总结和统计',
pagePath: '/pages/meeting_summary/meeting_summary',
pagePath: 'pages/meeting_summary/meeting_summary',
iconPath: '/static/tabbar/insight.png',
selectedIconPath: '/static/tabbar/insight_active.png',
},
{
key: 'furniture_reception',
text: '接待',
pagePath: '/pages/furniture_reception/furniture_reception',
pagePath: 'pages/furniture_reception/furniture_reception',
iconPath: '/static/tabbar/reception.png',
selectedIconPath: '/static/tabbar/reception_active.png',
},
{
key: 'common_begin_reception',
text: '开始接待',
pagePath: '/pages/furniture_reception/common_begin_reception',
pagePath: 'pages/furniture_reception/common_begin_reception',
iconPath: '/static/tabbar/reception.png',
selectedIconPath: '/static/tabbar/reception_active.png',
},
{
key: 'furniture_customer',
text: '客户',
pagePath: '/pages/furniture_customer/furniture_customer',
pagePath: 'pages/furniture_customer/furniture_customer',
iconPath: '/static/tabbar/customer.png',
selectedIconPath: '/static/tabbar/customer_active.png',
},
{
key: 'furniture_top_sales',
text: '销冠',
pagePath: '/pages/furniture_top_sales/furniture_top_sales',
pagePath: 'pages/furniture_top_sales/furniture_top_sales',
iconPath: '/static/tabbar/insight.png',
selectedIconPath: '/static/tabbar/insight_active.png',
},
@@ -73,6 +73,7 @@ Component({
lifetimes: {
attached() {
console.log('[TabBar][lifetimes] attached, 组件已挂载');
this.refreshRole();
this.updateActivePath();
@@ -91,8 +92,21 @@ Component({
} catch (e) {
console.warn('设置tabBar刷新监听失败:', e);
}
// 记录组件挂载时的页面信息
try {
const pages = getCurrentPages();
console.log('[TabBar][lifetimes] 组件挂载时的页面栈:', {
pagesLength: pages.length,
currentRoute: pages.length > 0 ? pages[pages.length - 1].route : 'unknown',
allRoutes: pages.map(p => p.route)
});
} catch (e) {
console.warn('[TabBar][lifetimes] 获取页面栈失败:', e);
}
},
detached() {
console.log('[TabBar][lifetimes] detached, 组件已卸载');
// 清理定时器
if (this._refreshTimer) {
clearInterval(this._refreshTimer);
@@ -149,7 +163,9 @@ Component({
updateActivePath() {
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentPath = currentPage && currentPage.route ? `/${currentPage.route}` : '';
// currentPage.route 格式为 pages/xxx/xxx不带前导斜杠
// 为了匹配 allTabs 中的 pagePath我们也使用不带前导斜杠的格式
const currentPath = currentPage && currentPage.route ? currentPage.route : '';
this.setData({
currentPath: currentPath,
});
@@ -197,53 +213,281 @@ Component({
},
switchTab(e) {
const item = e.currentTarget.dataset.item;
if (!item) return;
// 只从 dataset 获取 key避免路径传递问题
const dataset = e.currentTarget.dataset || {};
const key = dataset.key;
if (!key) {
console.error('[TabBar][switchTab] 缺少必要参数 key:', dataset);
return;
}
// 根据key找到对应的item
const item = this.data.allTabs.find(tab => tab.key === key);
if (!item) {
console.error('[TabBar][switchTab] 未找到对应的tab项:', key);
return;
}
// 直接使用 item 中的 pagePath确保路径正确
// 重要:创建一个全新的字符串,避免任何引用或编码问题
let pagePath = String(item.pagePath);
// 移除所有前导和尾部空白字符、斜杠
pagePath = pagePath.trim().replace(/^\/+/, '').replace(/\/+$/, '');
console.log('[TabBar][switchTab] 准备跳转:', {
key: key,
pagePath: pagePath,
currentPath: this.data.currentPath,
itemPagePath: item.pagePath
});
this.refreshRole();
const allowedKeys = this.getAllowedKeys();
if (!allowedKeys.includes(item.key)) {
if (!allowedKeys.includes(key)) {
wx.showToast({
title: '当前账号无此模块权限',
icon: 'none',
duration: 1200
});
console.warn('[TabBar][block-switch]', 'key:', item.key, 'path:', item.pagePath, 'allowed:', allowedKeys);
console.warn('[TabBar][block-switch]', 'key:', key, 'path:', pagePath, 'allowed:', allowedKeys);
return;
}
if (this.data.currentPath === item.pagePath) return;
// 检查是否已经是当前页面
const normalizedCurrent = (this.data.currentPath || '').trim().replace(/^\/+/, '').replace(/\/+$/, '');
const normalizedTarget = pagePath.trim().replace(/^\/+/, '').replace(/\/+$/, '');
if (normalizedCurrent === normalizedTarget) {
console.log('[TabBar][switchTab] 已经是当前页面,跳过跳转');
return;
}
const url = item.pagePath.startsWith('/') ? item.pagePath.substring(1) : item.pagePath;
// switchTab 的 url 必须与 pages.json 中 tabBar.list 的 pagePath 完全一致
// 格式pages/xxx/xxx不带前导斜杠
// 重要:使用字符串字面量重新构建路径,确保是全新的字符串
// 根据 key 直接构建路径,避免使用 item.pagePath 可能存在的引用问题
const pathMap = {
'reception': 'pages/reception/reception',
'customer': 'pages/customer/customer',
'team': 'pages/team/team',
'ucenter': 'pages/ucenter/ucenter',
'meeting_summary': 'pages/meeting_summary/meeting_summary',
'furniture_reception': 'pages/furniture_reception/furniture_reception',
'common_begin_reception': 'pages/furniture_reception/common_begin_reception',
'furniture_customer': 'pages/furniture_customer/furniture_customer',
'furniture_top_sales': 'pages/furniture_top_sales/furniture_top_sales'
};
wx.switchTab({
url: url,
// 直接从 pathMap 获取路径,确保路径是全新的字符串字面量
let switchTabUrl = pathMap[key];
if (!switchTabUrl) {
console.error('[TabBar][switchTab] 未找到对应的路径映射:', key);
wx.showToast({
title: '页面路径不存在',
icon: 'none',
duration: 2000
});
return;
}
// 获取当前页面信息,用于调试
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
const currentRoute = currentPage ? currentPage.route : 'unknown';
const currentOptions = currentPage ? currentPage.options : {};
// 验证路径格式
if (!switchTabUrl.match(/^pages\/[^\/]+\/[^\/]+$/)) {
console.error('[TabBar][switchTab] 路径格式错误:', switchTabUrl);
return;
}
// 创建全新的字符串,确保没有任何引用或隐藏字符
// 使用 JSON 序列化再反序列化,确保是全新的字符串
switchTabUrl = JSON.parse(JSON.stringify(switchTabUrl));
// 再次验证
if (!switchTabUrl.match(/^pages\/[^\/]+\/[^\/]+$/)) {
console.error('[TabBar][switchTab] JSON处理后路径格式错误:', switchTabUrl);
return;
}
// 详细日志:记录所有相关信息
console.log('[TabBar][switchTab] ========== 详细调试信息 ==========');
console.log('[TabBar][switchTab] 1. 基本信息:', {
key: key,
switchTabUrl: switchTabUrl,
switchTabUrlType: typeof switchTabUrl,
switchTabUrlLength: switchTabUrl.length,
switchTabUrlCharCodes: switchTabUrl.split('').map(c => c.charCodeAt(0)),
switchTabUrlJSON: JSON.stringify(switchTabUrl)
});
console.log('[TabBar][switchTab] 2. 当前页面信息:', {
currentPath: this.data.currentPath,
currentRoute: currentRoute,
currentOptions: currentOptions,
pagesLength: pages.length,
allRoutes: pages.map(p => p.route)
});
console.log('[TabBar][switchTab] 3. 路径对比:', {
switchTabUrl: switchTabUrl,
itemPagePath: item.pagePath,
pathMapValue: pathMap[key],
areEqual: switchTabUrl === pathMap[key],
startsWithPages: switchTabUrl.startsWith('pages/'),
endsWithSlash: switchTabUrl.endsWith('/')
});
console.log('[TabBar][switchTab] 4. 准备调用 wx.switchTab');
console.log('[TabBar][switchTab] ====================================');
// 尝试使用 getApp() 获取全局配置,检查是否有路径配置
try {
const app = getApp();
console.log('[TabBar][switchTab] 5. App全局信息:', {
hasApp: !!app,
globalData: app ? Object.keys(app.globalData || {}) : []
});
} catch (e) {
console.warn('[TabBar][switchTab] 获取App实例失败:', e);
}
// 尝试获取 tabBar 配置
try {
const tabBarConfig = wx.getTabBar ? wx.getTabBar() : null;
console.log('[TabBar][switchTab] 6. TabBar配置:', {
hasTabBarConfig: !!tabBarConfig,
tabBarType: typeof tabBarConfig
});
} catch (e) {
console.warn('[TabBar][switchTab] 获取TabBar配置失败:', e);
}
// 根本解决方案:根据微信小程序文档和错误分析
// 问题:在自定义 tabBar 组件中直接调用 wx.switchTab 时,微信小程序会错误地将当前页面路径拼接
// 解决方案:通过页面实例调用,或者使用事件机制通知页面调用
// 方法:通过页面实例的 selectComponent 或直接调用页面方法
// 但更好的方法是:使用 wx.navigateTo 先跳转到一个中间页面,然后立即 switchTab
// 或者:直接使用 wx.reLaunch虽然文档说 tabBar 不支持,但实际可以)
console.log('[TabBar][switchTab] ========== 尝试解决路径拼接问题 ==========');
console.log('[TabBar][switchTab] 目标路径:', switchTabUrl);
console.log('[TabBar][switchTab] 当前页面:', this.data.currentPath);
// 关键发现:根据错误信息,微信小程序会将当前页面路径错误拼接
// 解决方案:使用 wx.reLaunch 替代 wx.switchTab
// reLaunch 会关闭所有页面,然后打开指定页面,不会进行路径拼接
console.log('[TabBar][switchTab] 使用 wx.reLaunch 替代 wx.switchTab避免路径拼接');
wx.reLaunch({
url: '/' + switchTabUrl, // reLaunch 需要带前导斜杠
success: () => {
console.log('[TabBar][switchTab] success:', url);
this.updateActivePath();
},
fail: (err) => {
console.error('[TabBar][switchTab] fail:', err, 'url:', url);
wx.reLaunch({
url: url,
fail: (err2) => {
console.error('[TabBar][reLaunch] fail:', err2, 'url:', url);
wx.showToast({
title: '页面跳转失败,请检查页面配置',
icon: 'none',
duration: 2000
});
},
success: () => {
this.updateActivePath();
}
});
},
complete: () => {
console.log('[TabBar][switchTab] reLaunch 成功:', '/' + switchTabUrl);
setTimeout(() => {
this.updateActivePath();
}, 100);
},
fail: (err) => {
console.error('[TabBar][switchTab] reLaunch 失败:', err);
// 如果 reLaunch 失败,尝试使用 switchTab带前导斜杠
console.log('[TabBar][switchTab] reLaunch 失败,尝试 switchTab带前导斜杠');
wx.switchTab({
url: '/' + switchTabUrl,
success: () => {
console.log('[TabBar][switchTab] switchTab带前导斜杠成功');
setTimeout(() => {
this.updateActivePath();
}, 100);
},
fail: (err2) => {
console.error('[TabBar][switchTab] switchTab带前导斜杠也失败:', err2);
// 最后尝试:不带前导斜杠的 switchTab
console.log('[TabBar][switchTab] 最后尝试switchTab不带前导斜杠');
this.callWxSwitchTab(switchTabUrl, key, pagePath);
}
});
}
});
},
// 单独的方法调用 wx.switchTab便于调试和错误处理
callWxSwitchTab(switchTabUrl, key, pagePath) {
console.log('[TabBar][callWxSwitchTab] 调用 wx.switchTab:', {
url: switchTabUrl,
key: key,
urlType: typeof switchTabUrl,
urlLength: switchTabUrl.length
});
wx.switchTab({
url: switchTabUrl,
success: () => {
console.log('[TabBar][callWxSwitchTab] success:', switchTabUrl);
setTimeout(() => {
this.updateActivePath();
}, 100);
},
fail: (err) => {
console.error('[TabBar][callWxSwitchTab] ========== 失败详情 ==========');
console.error('[TabBar][callWxSwitchTab] 错误对象:', err);
console.error('[TabBar][callWxSwitchTab] 传递的url:', {
url: switchTabUrl,
urlType: typeof switchTabUrl,
urlLength: switchTabUrl.length,
urlCharCodes: switchTabUrl.split('').map(c => c.charCodeAt(0)),
urlJSON: JSON.stringify(switchTabUrl),
urlString: String(switchTabUrl),
urlSlice: switchTabUrl.slice(0),
urlSubstring: switchTabUrl.substring(0)
});
console.error('[TabBar][callWxSwitchTab] 错误消息:', err.errMsg);
console.error('[TabBar][callWxSwitchTab] 当前页面:', {
currentPath: this.data.currentPath,
currentRoute: getCurrentPages().length > 0 ? getCurrentPages()[getCurrentPages().length - 1].route : 'unknown',
allRoutes: getCurrentPages().map(p => p.route)
});
// 解析错误消息中的路径
const errorPathMatch = err.errMsg ? err.errMsg.match(/page\s+"([^"]+)"/) : null;
const actualSearchedPath = errorPathMatch ? errorPathMatch[1] : null;
console.error('[TabBar][callWxSwitchTab] 路径分析:', {
passedUrl: switchTabUrl,
errorPathInMsg: actualSearchedPath,
isPathConcatenated: actualSearchedPath && actualSearchedPath.includes('pages/reception/pages/'),
expectedPath: switchTabUrl,
actualSearchedPath: actualSearchedPath,
pathDifference: actualSearchedPath ? actualSearchedPath.replace(switchTabUrl, '') : null,
currentPagePrefix: this.data.currentPath ? this.data.currentPath.split('/').slice(0, -1).join('/') : null
});
// 检查是否是路径拼接问题
if (actualSearchedPath && actualSearchedPath.includes('pages/reception/pages/')) {
console.error('[TabBar][callWxSwitchTab] 确认是路径拼接问题!');
console.error('[TabBar][callWxSwitchTab] 当前页面路径被错误地拼接到了目标路径前面');
console.error('[TabBar][callWxSwitchTab] 这可能是因为微信小程序在处理自定义 tabBar 的 switchTab 时的 bug');
}
console.error('[TabBar][callWxSwitchTab] ====================================');
// 如果 switchTab 失败,尝试检查是否是路径问题
// 注意:不能使用 reLaunch 替代 switchTab因为 reLaunch 不支持 tabBar 页面
wx.showToast({
title: '页面跳转失败,请检查页面配置',
icon: 'none',
duration: 2000
});
},
complete: () => {
// 延迟更新,确保页面切换完成
setTimeout(() => {
this.updateActivePath();
}, 200);
},
});
},

View File

@@ -3,7 +3,7 @@
wx:for="{{visibleTabs}}"
wx:key="key"
class="tabbar-item {{currentPath === item.pagePath ? 'active' : ''}}"
data-item="{{item}}"
data-key="{{item.key}}"
bindtap="switchTab"
>
<image class="tabbar-icon" src="{{currentPath === item.pagePath ? item.selectedIconPath : item.iconPath}}" />