dramaling-app/apps/web/src/router/index.ts

277 lines
7.1 KiB
TypeScript

import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'home',
component: () => import('@/views/HomeView.vue'),
meta: {
title: 'Drama Ling - 戲劇式語言學習',
requiresAuth: false
}
},
{
path: '/auth',
component: () => import('@/layouts/AuthLayout.vue'),
children: [
{
path: 'login',
name: 'login',
component: () => import('@/views/auth/LoginView.vue'),
meta: {
title: '登入 - Drama Ling',
requiresAuth: false
}
},
{
path: 'register',
name: 'register',
component: () => import('@/views/auth/RegisterView.vue'),
meta: {
title: '註冊 - Drama Ling',
requiresAuth: false
}
},
{
path: 'forgot-password',
name: 'forgot-password',
component: () => import('@/views/auth/ForgotPasswordView.vue'),
meta: {
title: '忘記密碼 - Drama Ling',
requiresAuth: false
}
}
]
},
{
path: '/learning',
component: () => import('@/layouts/AppLayout.vue'),
meta: { requiresAuth: true },
children: [
{
path: '',
name: 'learning',
component: () => import('@/views/learning/LearningHomeView.vue'),
meta: {
title: '學習地圖 - Drama Ling'
}
},
{
path: 'vocabulary',
name: 'vocabulary',
component: () => import('@/views/learning/VocabularyViewSimple.vue'),
meta: {
title: '詞彙學習 - Drama Ling'
}
},
{
path: 'vocabulary-native',
name: 'vocabulary-native',
component: () => import('@/views/learning/VocabularyViewNative.vue'),
meta: {
title: '詞彙學習 (原生樣式) - Drama Ling'
}
},
{
path: 'vocabulary/practice',
name: 'vocabulary-practice',
component: () => import('@/views/learning/VocabularyPracticeView.vue'),
meta: {
title: '詞彙練習 - Drama Ling'
}
},
{
path: 'vocabulary/choice-practice',
name: 'vocabulary-choice-practice',
component: () => import('@/views/learning/VocabularyChoicePracticeView.vue'),
meta: {
title: '選擇題練習 - Drama Ling'
}
},
{
path: 'vocabulary/choice-results/:sessionId',
name: 'vocabulary-choice-results',
component: () => import('@/views/learning/VocabularyChoiceResultsView.vue'),
meta: {
title: '練習結果 - Drama Ling'
},
props: true
},
{
path: 'vocabulary/matching-practice',
name: 'vocabulary-matching-practice',
component: () => import('@/views/learning/VocabularyMatchingPracticeView.vue'),
meta: {
title: '圖片匹配練習 - Drama Ling'
}
},
{
path: 'vocabulary/reorganize-practice',
name: 'vocabulary-reorganize-practice',
component: () => import('@/views/learning/VocabularyReorganizePracticeView.vue'),
meta: {
title: '句子重組練習 - Drama Ling'
}
},
{
path: 'vocabulary/analytics',
name: 'vocabulary-analytics',
component: () => import('@/views/learning/VocabularyAnalyticsDashboard.vue'),
meta: {
title: '詞彙學習分析儀表板 - Drama Ling'
}
},
{
path: 'vocabulary/review',
name: 'vocabulary-review',
component: () => import('@/views/learning/VocabularyReviewMain.vue'),
meta: {
title: '智能複習系統 - Drama Ling'
}
},
{
path: 'dialogue/:id',
name: 'dialogue',
component: () => import('@/views/learning/DialogueView.vue'),
meta: {
title: '對話練習 - Drama Ling'
},
props: true
},
{
path: 'roleplay/:id',
name: 'roleplay',
component: () => import('@/views/learning/RoleplayView.vue'),
meta: {
title: '角色扮演 - Drama Ling'
},
props: true
},
{
path: 'pronunciation/:id',
name: 'pronunciation',
component: () => import('@/views/learning/PronunciationView.vue'),
meta: {
title: '發音練習 - Drama Ling'
},
props: true
}
]
},
{
path: '/profile',
component: () => import('@/layouts/AppLayout.vue'),
meta: { requiresAuth: true },
children: [
{
path: '',
name: 'profile',
component: () => import('@/views/profile/ProfileView.vue'),
meta: {
title: '個人檔案 - Drama Ling'
}
},
{
path: 'progress',
name: 'progress',
component: () => import('@/views/profile/ProgressView.vue'),
meta: {
title: '學習進度 - Drama Ling'
}
},
{
path: 'settings',
name: 'settings',
component: () => import('@/views/profile/SettingsView.vue'),
meta: {
title: '設定 - Drama Ling'
}
}
]
},
{
path: '/shop',
component: () => import('@/layouts/AppLayout.vue'),
meta: { requiresAuth: true },
children: [
{
path: '',
name: 'shop',
component: () => import('@/views/shop/ShopView.vue'),
meta: {
title: '商店 - Drama Ling'
}
},
{
path: 'subscription',
name: 'subscription',
component: () => import('@/views/shop/SubscriptionView.vue'),
meta: {
title: '訂閱方案 - Drama Ling'
}
}
]
},
{
path: '/offline',
name: 'offline',
component: () => import('@/views/OfflineView.vue'),
meta: {
title: '離線模式 - Drama Ling',
requiresAuth: false
}
},
{
path: '/:pathMatch(.*)*',
name: 'not-found',
component: () => import('@/views/NotFoundView.vue'),
meta: {
title: '頁面未找到 - Drama Ling',
requiresAuth: false
}
}
]
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
}
if (to.hash) {
return { el: to.hash }
}
return { top: 0 }
}
})
router.beforeEach(async (to, from, next) => {
const authStore = useAuthStore()
// 設定頁面標題
if (to.meta.title) {
document.title = to.meta.title as string
}
console.log('Route to:', to.path, 'Auth:', authStore.isAuthenticated)
// 檢查認證需求
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
// 保存目標路徑,登入後跳轉
authStore.setRedirectPath(to.fullPath)
next({ name: 'login' })
return
}
// 已登入用戶訪問登入頁面時跳轉到首頁
if ((to.name === 'login' || to.name === 'register') && authStore.isAuthenticated) {
next({ name: 'learning' })
return
}
next()
})
export default router