From fdc42e945de62e6068937acf402cba812dd2391c Mon Sep 17 00:00:00 2001 From: tianfeng <769204422@qq.com> Date: Fri, 22 Aug 2025 16:32:12 +0800 Subject: [PATCH] =?UTF-8?q?=E8=B7=AF=E7=94=B1=E5=AE=88=E5=8D=AB=E4=B8=8E?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E4=BF=A1=E6=81=AF=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/routeGuard.js | 225 +++++++++++++++++++++++++++++++++------- 1 file changed, 186 insertions(+), 39 deletions(-) diff --git a/src/utils/routeGuard.js b/src/utils/routeGuard.js index 153853a..1bda574 100644 --- a/src/utils/routeGuard.js +++ b/src/utils/routeGuard.js @@ -1,11 +1,145 @@ /** * 路由守卫 - * 提供页面访问权限控制和自动重定向功能 + * 提供APP连接检查、页面访问权限控制和自动重定向功能 */ import { permissionManager, PAGES, USER_ROLES } from './permissionManager.js' -import { getUserIdentity } from '../api/wallet.js' -import { getUserId } from './userStore.js' +import { getUserIdentity, getTeamEntry } from '../api/wallet.js' +import {getUserId, setUserInfo} from './userStore.js' +import { connectApplication, parseAccessOrigin, parseHeader, setHttpHeaders, isInApp } from './appBridge.js' +import { appConnectionManager, isAppConnected } from './appConnectionManager.js' + +/** + * APP连接检查器 + */ +class AppConnectionChecker { + constructor() { + this.isConnecting = false + } + + /** + * 确保APP连接 + * @returns {Promise} 连接是否成功 + */ + async ensureConnection() { + console.debug('🔗 Checking APP connection...') + + // 如果不在APP环境中,直接返回成功 + if (!isInApp()) { + console.debug('🌐 Browser environment, no connection needed') + return true + } + + // 如果已经连接且未超时,直接返回成功 + if (isAppConnected()) { + console.debug('✅ APP already connected') + return true + } + + // 如果正在连接中,等待现有连接 + if (appConnectionManager.isConnecting()) { + console.debug('⏳ Connection already in progress, waiting...') + try { + await appConnectionManager.getConnectionPromise() + return isAppConnected() + } catch (error) { + console.error('❌ Connection wait failed:', error) + return false + } + } + + // 开始新的连接 + return await this._performConnection() + } + + /** + * 执行APP连接 + * @returns {Promise} + */ + async _performConnection() { + try { + console.debug('📱 Starting new APP connection...') + + const connectionPromise = new Promise((resolve, reject) => { + connectApplication(async (access) => { + try { + const result = parseAccessOrigin(access) + + if (result.success) { + // 解析头部信息 + const headerInfo = parseHeader(result.data) + + // 设置HTTP请求头 + await setHttpHeaders(headerInfo) + + // 更新连接状态 + appConnectionManager.setConnected(headerInfo) + + console.debug('🎉 APP connection established successfully') + + // APP连接成功后立即获取用户信息 + await this._fetchUserInfoAfterConnection() + + resolve(true) + } else { + console.error('❌ Failed to parse access origin:', result.error) + appConnectionManager.reset() + reject(new Error(result.error)) + } + } catch (error) { + console.error('❌ Connection process failed:', error) + appConnectionManager.reset() + reject(error) + } + }) + }) + + // 设置连接状态 + appConnectionManager.setConnecting(connectionPromise) + + // 等待连接完成 + return await connectionPromise + + } catch (error) { + console.error('❌ APP connection failed:', error) + appConnectionManager.reset() + return false + } + } + + /** + * APP连接成功后获取用户信息 + * @private + */ + async _fetchUserInfoAfterConnection() { + try { + console.debug('👤 Fetching user info after connection...') + + const response = await getTeamEntry() + + if (response && response.status && response.body) { + // 缓存用户信息 + if (response.body.memberProfile) { + setUserInfo(response.body.memberProfile, response.body.teamProfile) + console.debug('✅ User info cached successfully') + } + } else { + console.warn('⚠️ Failed to get team entry or invalid response') + } + } catch (error) { + // 这里不抛出错误,因为APP连接已经成功 + // 用户信息获取失败可以在后续的身份检查中处理 + console.warn('⚠️ Failed to fetch user info after connection:', error) + } + } + + /** + * 重置连接状态 + */ + reset() { + appConnectionManager.reset() + } +} /** * 身份检查器 @@ -54,16 +188,16 @@ class IdentityChecker { async _performIdentityCheck(userId) { try { console.debug('🔍 Checking user identity for:', userId) - + const response = await getUserIdentity(userId) - + if (response && response.status && response.body) { const identity = response.body console.debug('✅ Identity fetched:', identity) - + // 设置权限信息 permissionManager.setUserIdentity(identity) - + return permissionManager.getPrimaryRole() } else { console.warn('⚠️ Invalid identity response') @@ -99,10 +233,10 @@ class PageRedirector { */ async redirectToCorrectPage(router, targetPath, currentPath) { const primaryRole = permissionManager.getPrimaryRole() - + // 检查目标页面权限 const hasPermission = permissionManager.hasPagePermission(targetPath) - + console.debug('🔄 Redirect check:', { targetPath, currentPath, @@ -120,9 +254,9 @@ class PageRedirector { } else { // 无权限访问,重定向到默认页面 const defaultPage = permissionManager.getDefaultPage() - + console.debug('❌ Access denied, redirecting to:', defaultPage) - + if (defaultPage !== currentPath) { await router.replace(defaultPage) return true // 已进行重定向 @@ -139,7 +273,7 @@ class PageRedirector { async handleUnauthorizedAccess(router, attemptedPage) { const primaryRole = permissionManager.getPrimaryRole() const defaultPage = permissionManager.getDefaultPage() - + console.warn('🚫 Unauthorized access attempt:', { attemptedPage, primaryRole, @@ -156,6 +290,7 @@ class PageRedirector { */ class RouteGuard { constructor() { + this.appConnectionChecker = new AppConnectionChecker() this.identityChecker = new IdentityChecker() this.pageRedirector = new PageRedirector() this.isGuardActive = false @@ -169,7 +304,7 @@ class RouteGuard { router.beforeEach(async (to, from, next) => { await this.handleRouteChange(to, from, next) }) - + this.isGuardActive = true console.debug('🛡️ Route guard installed') } @@ -177,7 +312,7 @@ class RouteGuard { /** * 处理路由变化 * @param {Object} to - 目标路由 - * @param {Object} from - 来源路由 + * @param {Object} from - 来源路由 * @param {Function} next - 路由继续函数 */ async handleRouteChange(to, from, next) { @@ -185,7 +320,7 @@ class RouteGuard { console.debug('📍 Route change:', from.path, '→', to.path) try { - // 1. 检查是否需要身份验证的页面 + // 1. 检查是否为公共页面(无需任何验证) if (this.isPublicPage(to.path)) { console.debug('🌐 Public page, allowing access') console.groupEnd() @@ -193,20 +328,26 @@ class RouteGuard { return } - // 2. 检查用户身份是否已加载 + // 2. 确保APP连接 + console.debug('🔗 Ensuring APP connection...') + const isConnected = await this.appConnectionChecker.ensureConnection() + + if (!isConnected) { + console.error('❌ APP connection failed, redirecting to error page') + console.groupEnd() + next(PAGES.NOT_APP) + return + } + + // 3. 检查用户身份是否已加载 if (!permissionManager.isLoaded()) { console.debug('🔍 Identity not loaded, checking...') - + const userId = getUserId() if (!userId) { - console.debug('❌ No user ID, redirecting to apply') + console.debug('❌ No user ID available, redirecting to apply') console.groupEnd() - // 防止无限循环:如果已经在申请页面,就不再重定向 - if (to.path === PAGES.APPLY) { - next() - } else { - next(PAGES.APPLY) - } + next(PAGES.APPLY) return } @@ -214,17 +355,17 @@ class RouteGuard { await this.identityChecker.checkUserIdentity(userId) } - // 3. 检查页面访问权限 + // 4. 检查页面访问权限 const hasPermission = permissionManager.hasPagePermission(to.path) - + if (hasPermission) { - console.debug('✅ Permission granted') + console.debug('✅ Permission granted, allowing access') console.groupEnd() next() } else { console.debug('❌ Permission denied') const defaultPage = permissionManager.getDefaultPage() - console.debug('🔄 Redirecting to:', defaultPage) + console.debug('🔄 Redirecting to default page:', defaultPage) console.groupEnd() next(defaultPage) } @@ -232,21 +373,26 @@ class RouteGuard { } catch (error) { console.error('❌ Route guard error:', error) console.groupEnd() - next(PAGES.APPLY) // 出错时重定向到申请页面 + + // 根据错误类型决定重定向目标 + if (error.message && error.message.includes('connection')) { + next(PAGES.NOT_APP) // 连接相关错误 + } else { + next(PAGES.APPLY) // 其他错误 + } } } /** - * 检查是否为公共页面(无需权限验证) + * 检查是否为公共页面(无需APP连接和权限验证) * @param {string} path - 页面路径 * @returns {boolean} */ isPublicPage(path) { const publicPages = [ - PAGES.APPLY, // 申请页面 - 任何人都可以访问 - PAGES.NOT_APP, // 错误页面 - '/404', - '/error' + PAGES.NOT_APP, // 错误页面 - APP连接失败时的页面 + '/404', // 404页面 + '/error' // 通用错误页面 ] return publicPages.includes(path) } @@ -259,21 +405,21 @@ class RouteGuard { async checkAndRedirect(router, userId) { try { console.debug('🔄 Manual identity check and redirect') - + // 检查身份 const primaryRole = await this.identityChecker.checkUserIdentity(userId) - + // 获取当前页面 const currentPath = router.currentRoute.value.path - + // 检查当前页面权限 const hasPermission = permissionManager.hasPagePermission(currentPath) - + if (!hasPermission) { // 重定向到默认页面 await this.pageRedirector.redirectToCorrectPage(router, currentPath, currentPath) } - + return primaryRole } catch (error) { console.error('❌ Manual check and redirect failed:', error) @@ -285,6 +431,7 @@ class RouteGuard { * 重置守卫状态 */ reset() { + this.appConnectionChecker.reset() this.identityChecker.reset() permissionManager.reset() console.debug('🔄 Route guard reset')