/** * 路由守卫 */ import type { Router } from 'vue-router' import { useUserStore, type UserRole } from '@/store/modules/user' import { useAppStore } from '@/store/modules/app' import { showToast } from 'vant' import i18n from '@/locale' const { t } = i18n.global /** * 前置守卫 */ export function setupRouterGuards(router: Router) { router.beforeEach(async (to, from, next) => { const userStore = useUserStore() const appStore = useAppStore() // 0. 模式守卫 if (to.path === '/index') { // 进入首页,切换为平台模式 if (!appStore.isPlatformMode) { appStore.enterPlatformMode() } } else if (to.path === '/menu') { // 进入菜单页,检查是否有店铺上下文 const queryShopId = to.query.shopId as string // 如果URL有shopId,优先使用(处理直接访问) if (queryShopId && (!appStore.currentShop || appStore.currentShop.id !== queryShopId)) { // TODO: 这里应该从API加载店铺信息 // 暂时只设置简单的上下文 appStore.enterShopMode({ id: queryShopId, name: '加载中...', status: 'operating', companyId: '', address: '' }) } // 如果没有context且没有query参数,重定向回首页 else if (!appStore.currentShop) { showToast('请先选择店铺') next('/index') return } } // 1. 检查是否需要登录 // guest 用户允许访问菜单和购物车,但不能访问需要登录的页面 if (to.meta.requiresAuth) { // 检查是否登录或有有效会话 if (!userStore.isLogin && !userStore.isGuest) { // 特殊处理:如果是Shop Mode下的购物车/结算,提示登录 if (appStore.isShopMode && ['/cart', '/payment'].some(p => to.path.startsWith(p))) { // 允许访问,但在页面内处理登录逻辑 // 或者跳转登录 showToast(t('common.pleaseLogin')) next({ path: '/login', query: { redirect: to.fullPath } }) return } showToast(t('common.pleaseLogin')) next({ path: '/login', query: { redirect: to.fullPath } }) return } // guest 用户尝试访问需要登录的页面 if (userStore.isGuest && to.meta.requiresAuth) { // 允许 guest 访问部分页面(订单创建相关) const guestAllowedPaths = ['/cart', '/payment', '/order/detail'] if (!guestAllowedPaths.some(p => to.path.startsWith(p))) { showToast(t('common.pleaseLogin')) next({ path: '/login', query: { redirect: to.fullPath } }) return } } } // 2. 检查角色要求 if (to.meta.requiresRole) { const requiredRoles = Array.isArray(to.meta.requiresRole) ? to.meta.requiresRole as UserRole[] : [to.meta.requiresRole] as UserRole[] const hasRole = requiredRoles.some(role => userStore.availableRoles.includes(role) ) if (!hasRole) { showToast(t('role.noPermission')) next(false) return } // 3. 自动切换角色(如果当前角色不匹配) if (!requiredRoles.includes(userStore.currentRole)) { // 如果当前角色不匹配,但用户拥有所需角色,自动切换 const targetRole = requiredRoles.find(role => userStore.availableRoles.includes(role) ) if (targetRole) { userStore.setCurrentRole(targetRole) } } } // 4. 检查权限(可选) if (to.meta.requiresPermission) { const permission = to.meta.requiresPermission as string if (!userStore.can(permission)) { showToast(t('role.noPermission')) next(false) return } } next() }) router.afterEach((to) => { // 设置页面标题(支持国际化) if (to.meta.title) { const title = typeof to.meta.title === 'string' ? t(to.meta.title) : to.meta.title document.title = typeof title === 'string' ? title : 'FastEat' } }) }