Files
th-hotel-simple/client/src/router/index.ts
2026-07-10 18:32:34 +08:00

227 lines
6.1 KiB
TypeScript

import { createRouter, createWebHistory, type RouteLocationNormalized } from 'vue-router'
import { useAuthStore } from '@/stores/authStore'
import type { AuthPermissionCode } from '@/types/auth'
import { resolveAuthenticatedEntryPath, resolveLoginRedirectPath } from '@/utils/authNavigation'
type AuthStore = ReturnType<typeof useAuthStore>
type AppRouteMeta = {
public?: boolean
layout?: 'plain' | 'app'
permission?: AuthPermissionCode
}
export const router = createRouter({
history: createWebHistory(),
routes: [
{
path: '/',
name: 'home',
component: {
name: 'HomeRedirectView',
render: () => null,
},
},
{
path: '/login',
name: 'login',
component: () => import('@/views/auth/LoginView.vue'),
meta: {
public: true,
layout: 'plain',
titleKey: 'auth.loginTitle',
},
},
{
path: '/unauthorized',
name: 'unauthorized',
component: () => import('@/views/auth/UnauthorizedView.vue'),
meta: {
titleKey: 'auth.unauthorizedTitle',
},
},
{
path: '/reservation/workbench',
redirect: '/reservation/orders',
},
{
path: '/reservation/orders',
name: 'reservation-order-list',
component: () => import('@/views/reservation/ReservationOrderListView.vue'),
meta: {
titleKey: 'nav.orders',
permission: 'RESERVATION_ORDER_READ',
},
},
{
path: '/reservation/tasks',
name: 'reservation-task-list',
component: () => import('@/views/reservation/ReservationTaskListView.vue'),
meta: {
titleKey: 'nav.taskQueue',
permission: 'RESERVATION_TASK_READ',
},
},
{
path: '/reservation/orders/:orderId',
name: 'reservation-order-detail',
component: () => import('@/views/reservation/ReservationOrderDetailView.vue'),
meta: {
titleKey: 'nav.orderDetail',
permission: 'RESERVATION_ORDER_READ',
},
},
{
path: '/reservation/tasks/:taskId',
name: 'reservation-task-detail',
component: () => import('@/views/reservation/ReservationTaskDetailView.vue'),
meta: {
titleKey: 'nav.taskDetail',
permission: 'RESERVATION_TASK_READ',
},
},
{
path: '/reservation/source-messages/:sourceMessageId/conversation',
name: 'reservation-source-message-conversation',
component: () => import('@/views/reservation/ReservationSourceMessageConversationView.vue'),
meta: {
titleKey: 'nav.sourceMessageConversation',
permission: 'SOURCE_MESSAGE_ORIGINAL_READ',
},
},
{
path: '/debug/eml-superagent',
name: 'debug-eml-superagent',
component: () => import('@/views/debug/DebugEmlSuperAgentRunView.vue'),
meta: {
titleKey: 'debugEml.title',
permission: 'SYSTEM_DEBUG_EML_RUN',
},
},
{
path: '/system',
component: () => import('@/views/system/SystemAdminLayoutView.vue'),
meta: {
titleKey: 'nav.systemSettings',
permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS',
},
children: [
{
path: 'users',
name: 'system-users',
component: () => import('@/views/system/SystemUsersView.vue'),
meta: {
titleKey: 'nav.systemUsers',
permission: 'SYSTEM_USER_MANAGE',
},
},
{
path: 'roles',
name: 'system-roles',
component: () => import('@/views/system/SystemRolesView.vue'),
meta: {
titleKey: 'nav.systemRoles',
permission: 'SYSTEM_ROLE_MANAGE',
},
},
{
path: 'menus',
name: 'system-menus',
component: () => import('@/views/system/SystemMenusView.vue'),
meta: {
titleKey: 'nav.systemMenus',
permission: 'SYSTEM_MENU_MANAGE',
},
},
{
path: 'hotels',
name: 'system-hotels',
component: () => import('@/views/system/SystemHotelsView.vue'),
meta: {
titleKey: 'nav.systemHotels',
permission: 'HOTEL_MANAGE',
},
},
{
path: 'audits',
name: 'system-audits',
component: () => import('@/views/system/SystemAuditsView.vue'),
meta: {
titleKey: 'nav.systemAudits',
permission: 'SYSTEM_ADMIN_CONSOLE_ACCESS',
},
},
],
},
{
path: '/:pathMatch(.*)*',
name: 'not-found',
component: () => import('@/views/system/RouteNotFoundView.vue'),
meta: {
titleKey: 'notFound.title',
},
},
],
})
router.beforeEach(createAuthGuard())
export function createAuthGuard(resolveAuthStore: () => AuthStore = () => useAuthStore()) {
return async (to: RouteLocationNormalized) => {
const authStore = resolveAuthStore()
const meta = to.meta as AppRouteMeta
if (!authStore.restoreAttempted && authStore.hasStoredToken()) {
await authStore.restoreFromSession()
}
if (meta.public) {
if (to.name === 'login' && authStore.isAuthenticated) {
return resolveLoginRedirectPath(to.query.redirect, authStore.firstMenuPath)
}
return true
}
if (!authStore.isAuthenticated) {
return {
path: '/login',
query: {
redirect: to.fullPath,
},
}
}
if (to.path === '/') {
return resolveAuthenticatedEntryPath(authStore.firstMenuPath)
}
if (meta.permission && !authStore.hasPermission(meta.permission)) {
return {
name: 'unauthorized',
}
}
if (to.path === '/system') {
return resolveSystemAdminEntryPath(authStore)
}
return true
}
}
function resolveSystemAdminEntryPath(authStore: AuthStore): string {
if (authStore.hasPermission('SYSTEM_USER_MANAGE')) {
return '/system/users'
}
if (authStore.hasPermission('SYSTEM_ROLE_MANAGE')) {
return '/system/roles'
}
if (authStore.hasPermission('SYSTEM_MENU_MANAGE')) {
return '/system/menus'
}
if (authStore.hasPermission('HOTEL_MANAGE')) {
return '/system/hotels'
}
return '/system/audits'
}