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