mirror of
http://112.124.100.131/GFRS/ebiz-h5.git
synced 2025-12-23 06:26:44 +08:00
- 实现递归查找路由函数,支持多层嵌套路由的定位 - 新增通过路径和名称两种方式查找路由的功能 - 添加构建完整路由路径的工具函数 - 完善路由查找相关单元测试覆盖 - 优化路径规范化处理,去除多余斜杠 - 改进错误处理逻辑,提升代码健壮性
194 lines
5.3 KiB
JavaScript
194 lines
5.3 KiB
JavaScript
import jump from '@/assets/js/utils/jump'
|
||
import router from '@/router'
|
||
/**
|
||
* 路由跳转函数
|
||
* @param path { String}路径
|
||
* @param name
|
||
* @param title {String} 标题内容
|
||
* @param params { Object}参数
|
||
*/
|
||
export function navigateRouter({ path = '', name = '', title = '', params = {} } = {}) {
|
||
const routes = router.options.routes
|
||
|
||
let options = {
|
||
flag: 'h5',
|
||
extra: {
|
||
title,
|
||
// forbidSwipeBack: 1, //当前页面禁止右滑返回
|
||
url: ''
|
||
},
|
||
routerInfo: { query: params }
|
||
}
|
||
if (path) {
|
||
// 查找路由支持任意深度的嵌套
|
||
const routeInfo = findRouteByPath(routes, path)
|
||
if (!routeInfo) {
|
||
console.error('在 routers 中无法找到该路径,请检查路径是否正确')
|
||
return false
|
||
}
|
||
|
||
options.extra = {
|
||
title: routeInfo.route.meta && routeInfo.route.meta.title ? routeInfo.route.meta.title : '',
|
||
url: location.origin + '/#' + path + '?' + processJson(params)
|
||
}
|
||
options.routerInfo = { ...options.routerInfo, path }
|
||
} else if (name) {
|
||
// 通过名称查找路由也支持任意深度嵌套
|
||
const routeInfo = findRouteByName(routes, name)
|
||
if (!routeInfo) {
|
||
console.error('在 routers 中无法找到该名称,请检查名称是否正确')
|
||
return false
|
||
}
|
||
|
||
// 构建完整的路径
|
||
const fullPath = buildFullPath(routeInfo.routeStack)
|
||
options.extra = {
|
||
title: routeInfo.route.meta && routeInfo.route.meta.title ? routeInfo.route.meta.title : '',
|
||
url: location.origin + '/#' + fullPath + '?' + processJson(params)
|
||
}
|
||
|
||
options.routerInfo = { ...options.routerInfo, name }
|
||
}
|
||
|
||
jump(options)
|
||
}
|
||
|
||
/**
|
||
* 递归查找具有指定路径的路由(支持多层嵌套)
|
||
* @param routes {import("vue-router").RouteConfig[]} 路由数组
|
||
* @param targetPath {String}目标路径
|
||
* @param parentPath {String}父级路径
|
||
* @return {undefined| {
|
||
* route: import("vue-router").RouteConfig,
|
||
* fullPath: String
|
||
* }}
|
||
*/
|
||
function findRouteByPath(routes, targetPath, parentPath = '') {
|
||
if (!routes || !Array.isArray(routes)) return undefined
|
||
|
||
// 规范化目标路径,移除多余的斜杠
|
||
targetPath = targetPath.replace(/\/+/g, '/')
|
||
|
||
for (const route of routes) {
|
||
// 构造当前路由的完整路径
|
||
let currentPath = parentPath
|
||
if (currentPath && !currentPath.endsWith('/') && route.path && !route.path.startsWith('/')) {
|
||
currentPath += '/' + route.path
|
||
} else {
|
||
currentPath += route.path
|
||
}
|
||
|
||
// 移除多余的斜杠
|
||
currentPath = currentPath.replace(/\/+/g, '/')
|
||
|
||
// 检查当前路由是否匹配
|
||
if (currentPath === targetPath) {
|
||
return {
|
||
route: route,
|
||
fullPath: currentPath
|
||
}
|
||
}
|
||
|
||
// 递归检查子路由
|
||
if (route.children && route.children.length > 0) {
|
||
const matchedChild = findRouteByPath(route.children, targetPath, currentPath)
|
||
|
||
if (matchedChild) {
|
||
return matchedChild
|
||
}
|
||
}
|
||
}
|
||
|
||
return undefined
|
||
}
|
||
|
||
/**
|
||
* 递归查找具有指定名称的路由(支持多层嵌套)
|
||
* @param routes 路由数组
|
||
* @param targetName 目标名称
|
||
* @param routeStack 用于追踪路由层级的堆栈
|
||
* @return {undefined| {
|
||
* route: import("vue-router").RouteConfig,
|
||
* routeStack: import("vue-router").RouteConfig[]
|
||
* }}
|
||
*/
|
||
function findRouteByName(routes, targetName, routeStack = []) {
|
||
if (!routes || !Array.isArray(routes)) return undefined
|
||
|
||
for (const route of routes) {
|
||
// 创建当前路由的堆栈副本
|
||
const currentStack = [...routeStack, route]
|
||
|
||
// 检查当前路由是否匹配
|
||
if (route.name === targetName) {
|
||
return {
|
||
route: route,
|
||
routeStack: currentStack
|
||
}
|
||
}
|
||
|
||
// 递归检查子路由
|
||
if (route.children && route.children.length > 0) {
|
||
const matchedChild = findRouteByName(route.children, targetName, currentStack)
|
||
|
||
if (matchedChild) {
|
||
return matchedChild
|
||
}
|
||
}
|
||
}
|
||
|
||
return undefined
|
||
}
|
||
|
||
/**
|
||
* 根据路由堆栈构建完整路径
|
||
* @param routeStack 路由堆栈
|
||
* @returns string
|
||
*/
|
||
function buildFullPath(routeStack) {
|
||
if (!routeStack || routeStack.length === 0) return ''
|
||
|
||
// 提取所有路由的路径并正确拼接
|
||
let fullPath = ''
|
||
routeStack.forEach((route, index) => {
|
||
// 特殊处理第一个路由
|
||
if (index === 0) {
|
||
fullPath += route.path
|
||
} else {
|
||
if (fullPath && !fullPath.endsWith('/') && route.path && !route.path.startsWith('/')) {
|
||
fullPath += '/' + route.path
|
||
} else if (fullPath.endsWith('/') && route.path.startsWith('/')) {
|
||
// 如果fullPath以/结尾,而route.path以/开头,则需要去掉一个/
|
||
fullPath += route.path.substring(1)
|
||
} else {
|
||
fullPath += route.path
|
||
}
|
||
}
|
||
})
|
||
|
||
// 移除多余的斜杠
|
||
fullPath = fullPath.replace(/\/+/g, '/')
|
||
|
||
// 确保不会在末尾留下斜杠(除非是根路径)
|
||
if (fullPath.length > 1 && fullPath.endsWith('/')) {
|
||
fullPath = fullPath.slice(0, -1)
|
||
}
|
||
|
||
return fullPath
|
||
}
|
||
|
||
/**
|
||
* 处理 json 键值对,到 url 中
|
||
*/
|
||
function processJson(json) {
|
||
if (typeof json !== 'object') return
|
||
if (window.URLSearchParams) return new URLSearchParams(json).toString()
|
||
|
||
let url = ''
|
||
for (const key in json) {
|
||
if (json.hasOwnProperty(key)) {
|
||
url += key + '=' + json[key] + '&'
|
||
}
|
||
}
|
||
return url.substring(0, url.length - 1)
|
||
} |