diff --git a/web-admin/src/router/guards/beforeEach.ts b/web-admin/src/router/guards/beforeEach.ts index 03f983ae4..1d71e6347 100644 --- a/web-admin/src/router/guards/beforeEach.ts +++ b/web-admin/src/router/guards/beforeEach.ts @@ -55,6 +55,7 @@ import { ApiStatus } from '@/utils/http/status' import { isHttpError } from '@/utils/http/error' import { RouteRegistry, MenuProcessor, IframeRouteManager, RoutePermissionValidator } from '../core' import { refreshMenuBadges } from '@/utils/menu-badge-registry' +import { isMpWebviewPath } from '@/utils/mp-webview' // 路由注册器实例 let routeRegistry: RouteRegistry | null = null @@ -176,6 +177,11 @@ async function handleRouteGuard( // 3. 处理动态路由注册 if (!routeRegistry?.isRegistered() && userStore.isLogin) { + if (isMpWebviewPath(to.path)) { + setPageTitle(to) + next() + return + } // 防止并发请求(快速连续导航场景) if (routeInitInProgress) { // 正在初始化中,等待完成后重新导航 @@ -218,8 +224,13 @@ function handleLoginStatus( return false } - // 已登录或访问登录页或静态路由,直接放行 - if (userStore.isLogin || to.path === RoutesAlias.Login || isStaticRoute(to.path)) { + // 已登录或访问登录页、静态路由、小程序 WebView 路由,直接放行 + if ( + userStore.isLogin || + to.path === RoutesAlias.Login || + isStaticRoute(to.path) || + isMpWebviewPath(to.path) + ) { return true } diff --git a/web-admin/src/store/modules/user.ts b/web-admin/src/store/modules/user.ts index cfc0f3c5f..dcf0b44cc 100644 --- a/web-admin/src/store/modules/user.ts +++ b/web-admin/src/store/modules/user.ts @@ -28,6 +28,7 @@ import { StorageConfig } from '@/utils/storage/storage-config' import { fetchLogout } from '@/api/auth' import { RoutesAlias } from '@/router/routesAlias' import { resolveSafeRedirectTarget } from '@/utils/router' +import { isMpWebviewPath, redirectToMiniLogin } from '@/utils/mp-webview' /** * 用户状态管理 @@ -160,8 +161,12 @@ export const useUserStore = defineStore( clearPortalHomeActiveModule() // 重置路由状态 resetRouterState(500) - // 跳转到登录页,携带当前路由作为 redirect 参数 const currentRoute = router.currentRoute.value + if (isMpWebviewPath(currentRoute.path)) { + redirectToMiniLogin() + return + } + // 跳转到登录页,携带当前路由作为 redirect 参数 const redirect = currentRoute.path !== RoutesAlias.Login ? resolveSafeRedirectTarget(currentRoute.fullPath, '') diff --git a/web-admin/src/utils/mp-webview.ts b/web-admin/src/utils/mp-webview.ts new file mode 100644 index 000000000..e60776a5c --- /dev/null +++ b/web-admin/src/utils/mp-webview.ts @@ -0,0 +1,35 @@ +export const MP_WEBVIEW_PATH_PREFIX = '/m/' + +export function isMpWebviewPath(path: string): boolean { + return (path || '').startsWith(MP_WEBVIEW_PATH_PREFIX) +} + +export function getWxMiniProgram(): { + reLaunch?: (opt: { url: string }) => void + navigateBack?: (opt?: { delta?: number }) => void +} | null { + if (typeof window === 'undefined') return null + const wxObj = (window as unknown as { wx?: { miniProgram?: unknown } }).wx + const mini = wxObj?.miniProgram as + | { reLaunch?: (opt: { url: string }) => void; navigateBack?: (opt?: { delta?: number }) => void } + | undefined + return mini || null +} + +export function redirectToMiniLogin(): void { + const mini = getWxMiniProgram() + if (mini?.reLaunch) { + mini.reLaunch({ url: '/pages/login/login' }) + return + } + // 非小程序:只展示空态,禁止跳管理端登录 +} + +export function stripMpTicketFromUrl( + path: string, + query: Record +): Record { + const next = { ...query } + delete next.mpTicket + return next +}