Files
urbanLifeline/urbanLifelineWeb/packages/workcase/src/router/index.ts
2025-12-27 17:34:19 +08:00

279 lines
10 KiB
TypeScript
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.

import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
// @ts-ignore
import { TokenManager } from 'shared/api'
// @ts-ignore
import { APP_CONFIG } from 'shared/config'
// @ts-ignore
import { loadRoutesFromStorage } from './dynamicRoute'
// 公开路由(不需要登录认证)
const routes: RouteRecordRaw[] = [
{
path: '/meeting',
name: 'Meeting',
component: () => import('@/views/public/JitsiMeeting/JitsiMeetingView.vue'),
meta: {
title: '视频会议',
requiresAuth: false // 不需要登录认证允许通过token访问
}
}
]
const router = createRouter({
history: createWebHistory('/workcase'), // 与nginx保持一致使用/workcase前缀
routes
})
// 标记动态路由是否已加载
let dynamicRoutesLoaded = false
// 路由守卫
router.beforeEach(async (to, from, next) => {
console.log('[Workcase Router] 路由守卫触发:', {
to: to.path,
from: from.path,
meta: to.meta,
query: to.query
})
// 设置页面标题
if (to.meta.title) {
document.title = `${to.meta.title} - 工单管理系统`
}
// 检查URL参数中是否有token用于外部链接和小程序访问
const tokenParam = to.query.token as string | undefined
// 如果URL中有token参数使用refresh接口验证并刷新登录状态
// 这样可以用新token覆盖旧的登录状态如果有的话
if (tokenParam) {
console.log('[Workcase Router] 检测到token参数尝试验证并刷新登录状态...')
try {
const response = await fetch('/api/urban-lifeline/auth/refresh', {
method: 'POST',
headers: {
'Authorization': `Bearer ${tokenParam}`,
'Content-Type': 'application/json'
}
})
if (response.ok) {
const result = await response.json()
if (result.success && result.data) {
const loginDomain = result.data
const newToken = loginDomain.token
// 保存到localStorage覆盖旧的登录状态
localStorage.setItem('token', newToken)
localStorage.setItem('loginDomain', JSON.stringify(loginDomain))
TokenManager.setToken(newToken)
console.log('[Workcase Router] Token验证成功登录状态已刷新')
} else {
console.warn('[Workcase Router] Token验证失败:', result.message)
}
} else {
console.warn('[Workcase Router] Token验证请求失败:', response.status)
}
} catch (error) {
console.error('[Workcase Router] Token验证异常:', error)
}
}
// 检查是否需要登录
const requiresAuth = to.meta.requiresAuth !== false
const hasToken = TokenManager.hasToken()
console.log('[Workcase Router] 认证检查:', {
requiresAuth,
hasToken,
tokenValue: localStorage.getItem('token')
})
// 其他页面:检查是否需要登录
if (requiresAuth && !hasToken) {
// 需要登录但未登录,重定向到 platform 的登录页
// 重要必须使用完整URL包含origin避免被workcase的路由拦截造成循环
const currentUrl = window.location.href
const origin = window.location.origin
// 构建platform登录页的完整URL
const loginUrl = `${origin}/login?redirect=${encodeURIComponent(currentUrl)}`
console.log('[Workcase Router] 未登录重定向到Platform登录页:', loginUrl)
// 使用完整URL跳转跳出workcase的路由系统
window.location.href = loginUrl
return
}
// 如果已登录且动态路由未加载,先加载动态路由
if (hasToken && !dynamicRoutesLoaded) {
console.log('[Workcase Router] 开始加载动态路由...')
console.log('[Workcase Router] LocalStorage 内容:', {
loginDomain: localStorage.getItem('loginDomain'),
token: localStorage.getItem('token')
})
dynamicRoutesLoaded = true
const loaded = loadRoutesFromStorage?.()
console.log('[Workcase Router] 动态路由加载结果:', loaded)
console.log('[Workcase Router] 当前路径:', to.path)
console.log('[Workcase Router] 所有路由:', router.getRoutes().map(r => r.path))
if (loaded) {
if (to.path === '/') {
// 访问根路径,重定向到第一个可用路由
const firstRoute = getFirstAvailableRoute()
if (firstRoute && firstRoute !== '/') {
// 只有当第一个路由不是 / 时才重定向,避免无限循环
console.log('[Workcase Router] 根路径重定向到:', firstRoute)
next({ path: firstRoute, replace: true })
return
} else {
// 第一个路由就是 /,直接放行
console.log('[Workcase Router] 第一个路由就是根路径,直接放行')
}
} else if (to.path === '/admin') {
// 访问 /admin 路径,重定向到第一个 admin 路由
const firstAdminRoute = getFirstAdminRoute()
if (firstAdminRoute) {
console.log('[Workcase Router] /admin 重定向到:', firstAdminRoute)
next({ path: firstAdminRoute, replace: true })
return
}
} else {
// 动态路由加载成功,重新导航以匹配新添加的路由
console.log('[Workcase Router] 动态路由加载成功,重新导航到:', to.path)
next({ ...to, replace: true })
return
}
} else {
console.warn('[Workcase Router] 动态路由加载失败')
}
}
// 如果已登录且访问根路径,但动态路由已加载,重定向到第一个可用路由
if (hasToken && to.path === '/' && dynamicRoutesLoaded) {
const firstRoute = getFirstAvailableRoute()
if (firstRoute && firstRoute !== '/') {
// 只有当第一个路由不是 / 时才重定向,避免无限循环
console.log('[Workcase Router] 已登录访问根路径,重定向到:', firstRoute)
next({ path: firstRoute, replace: true })
return
}
}
// 如果访问 /admin重定向到第一个 admin 路由
if (hasToken && to.path === '/admin' && dynamicRoutesLoaded) {
const firstAdminRoute = getFirstAdminRoute()
if (firstAdminRoute) {
console.log('[Workcase Router] 访问 /admin重定向到:', firstAdminRoute)
next({ path: firstAdminRoute, replace: true })
return
}
}
console.log('[Workcase Router] 继续正常导航')
next()
})
/**
* 获取第一个可用的路由路径
*/
function getFirstAvailableRoute(): string | null {
try {
console.log('[Workcase Router] 开始获取第一个可用路由...')
const loginDomainStr = localStorage.getItem('loginDomain')
if (!loginDomainStr) {
console.warn('[Workcase Router] localStorage 中没有 loginDomain')
return null
}
const loginDomain = JSON.parse(loginDomainStr)
const userViews = loginDomain.userViews || []
console.log('[Workcase Router] 所有用户视图:', userViews.length)
// 过滤出 workcase 服务的非 admin 视图
// 注意:不限制 type因为首页路由可能是 type=3路由类型而不是 type=1菜单类型
const workcaseViews = userViews.filter((view: any) =>
view.service === 'workcase' &&
!view.url?.startsWith('/admin') &&
view.url // 必须有 url 字段
)
console.log('[Workcase Router] Workcase 服务视图:', workcaseViews)
if (workcaseViews.length === 0) {
console.warn('[Workcase Router] 没有找到 workcase 服务的菜单视图')
return null
}
// 按 orderNum 排序
workcaseViews.sort((a: any, b: any) => (a.orderNum || 0) - (b.orderNum || 0))
const firstRoute = workcaseViews[0].url
console.log('[Workcase Router] 第一个路由:', firstRoute, '视图:', workcaseViews[0].name)
return firstRoute
} catch (error) {
console.error('[Workcase Router] 获取首页路由失败:', error)
return null
}
}
/**
* 获取第一个 admin 路由
*/
function getFirstAdminRoute(): string | null {
try {
console.log('[Workcase Router] 开始获取第一个 admin 路由...')
const loginDomainStr = localStorage.getItem('loginDomain')
if (!loginDomainStr) {
console.warn('[Workcase Router] localStorage 中没有 loginDomain')
return null
}
const loginDomain = JSON.parse(loginDomainStr)
const userViews = loginDomain.userViews || []
// 过滤出 workcase 服务的 admin 路由(排除目录类型)
const adminViews = userViews.filter((view: any) =>
view.service === 'workcase' &&
view.url?.startsWith('/admin') &&
view.layout === 'SubSidebarLayout' &&
!view.parentId && // 顶级菜单
view.url // 必须有 url 字段
)
console.log('[Workcase Router] Admin 视图:', adminViews)
if (adminViews.length === 0) {
console.warn('[Workcase Router] 没有找到 workcase admin 路由')
return null
}
// 按 orderNum 排序
adminViews.sort((a: any, b: any) => (a.orderNum || 0) - (b.orderNum || 0))
const firstRoute = adminViews[0].url
console.log('[Workcase Router] 第一个 admin 路由:', firstRoute, '视图:', adminViews[0].name)
return firstRoute
} catch (error) {
console.error('[Workcase Router] 获取 admin 路由失败:', error)
return null
}
}
// 重置动态路由加载状态
export function resetDynamicRoutes() {
dynamicRoutesLoaded = false
}
export default router