277 lines
7.1 KiB
TypeScript
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 |