xiangyixiangqin/miniapp/utils/navigate.js
2026-01-27 20:09:30 +08:00

201 lines
4.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 页面导航工具函数
* 统一处理小程序内的各种跳转逻辑
*/
/**
* TabBar 页面路径列表
* 这些页面需要使用 switchTab 而不是 navigateTo
*/
export const TABBAR_PAGES = [
'/pages/index/index',
'/pages/message/index',
'/pages/mine/index'
]
/**
* 链接类型枚举
*/
export const LINK_TYPE = {
/** 内部页面 */
INTERNAL: 1,
/** 外部链接H5 */
EXTERNAL: 2,
/** 其他小程序 */
MINI_PROGRAM: 3
}
/**
* 判断是否为 TabBar 页面
* @param {string} url - 页面路径
* @returns {boolean}
*/
export function isTabBarPage(url) {
return TABBAR_PAGES.includes(url)
}
/**
* 统一页面跳转函数
* 根据链接类型自动选择合适的跳转方式
*
* @param {string} url - 跳转地址
* @param {number} linkType - 链接类型1=内部页面, 2=外部链接, 3=小程序
* @param {Object} options - 额外配置
* @param {Function} options.onFail - 跳转失败回调
* @param {Function} options.onSuccess - 跳转成功回调
*/
export function navigateToPage(url, linkType = LINK_TYPE.INTERNAL, options = {}) {
if (!url) {
console.warn('[navigate] url 为空,跳过跳转')
return
}
const { onFail, onSuccess } = options
switch (linkType) {
case LINK_TYPE.EXTERNAL:
// 外部链接:复制到剪贴板(小程序限制无法直接打开外部链接)
handleExternalLink(url)
break
case LINK_TYPE.MINI_PROGRAM:
// 跳转其他小程序
handleMiniProgramLink(url, { onFail, onSuccess })
break
case LINK_TYPE.INTERNAL:
default:
// 内部页面跳转
handleInternalLink(url, { onFail, onSuccess })
break
}
}
/**
* 处理内部页面跳转
* 自动判断是否为 TabBar 页面
*
* @param {string} url - 页面路径
* @param {Object} callbacks - 回调函数
*/
function handleInternalLink(url, { onFail, onSuccess } = {}) {
const navigateMethod = isTabBarPage(url) ? uni.switchTab : uni.navigateTo
navigateMethod({
url,
success: () => {
onSuccess && onSuccess()
},
fail: (err) => {
console.error('[navigate] 页面跳转失败:', url, err)
if (onFail) {
onFail(err)
} else {
uni.showToast({
title: '页面跳转失败',
icon: 'none'
})
}
}
})
}
/**
* 处理外部链接
* 由于小程序限制,外部链接只能复制到剪贴板
*
* @param {string} url - 外部链接地址
*/
function handleExternalLink(url) {
uni.setClipboardData({
data: url,
success: () => {
uni.showToast({
title: '链接已复制',
icon: 'success'
})
},
fail: () => {
uni.showToast({
title: '复制失败',
icon: 'none'
})
}
})
}
/**
* 处理小程序跳转
* URL 格式appId:pathpath 可选)
*
* @param {string} url - 格式为 "appId:path" 的字符串
* @param {Object} callbacks - 回调函数
*/
function handleMiniProgramLink(url, { onFail, onSuccess } = {}) {
const [appId, path] = url.split(':')
if (!appId) {
console.error('[navigate] 小程序 appId 为空')
uni.showToast({
title: '跳转配置错误',
icon: 'none'
})
return
}
uni.navigateToMiniProgram({
appId,
path: path || '',
success: () => {
onSuccess && onSuccess()
},
fail: (err) => {
console.error('[navigate] 跳转小程序失败:', appId, err)
if (onFail) {
onFail(err)
} else {
uni.showToast({
title: '跳转失败',
icon: 'none'
})
}
}
})
}
/**
* 跳转到 WebView 页面
* 用于在小程序内打开 H5 页面
*
* @param {string} url - H5 页面地址
*/
export function navigateToWebView(url) {
if (!url) return
uni.navigateTo({
url: `/pages/webview/index?url=${encodeURIComponent(url)}`
})
}
/**
* 返回上一页
* @param {number} delta - 返回的页面数,默认 1
*/
export function navigateBack(delta = 1) {
uni.navigateBack({ delta })
}
/**
* 重定向到指定页面(关闭当前页)
* @param {string} url - 页面路径
*/
export function redirectTo(url) {
if (!url) return
if (isTabBarPage(url)) {
uni.switchTab({ url })
} else {
uni.redirectTo({ url })
}
}