index.js 4.25 KB
Newer Older
LiangLiu's avatar
LiangLiu committed
1
2
3
4
5
6
7
8
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Login from '../views/Login.vue'
import Layout from '../views/Layout.vue'
import Generate from '../components/Generate.vue'
import Projects from '../components/Projects.vue'
import Inspirations from '../components/Inspirations.vue'
import Share from '../views/Share.vue'
9
import PodcastGenerate from '../views/PodcastGenerate.vue'
LiangLiu's avatar
LiangLiu committed
10
import { showAlert } from '../utils/other'
11
import i18n from '../utils/i18n'
LiangLiu's avatar
LiangLiu committed
12
13

const routes = [
LiangLiu's avatar
LiangLiu committed
14
15
16
17
18
19
20
  {
    path: '/',
    redirect: (to) => {
      // 保留查询参数(用于 OAuth 回调)
      return { path: '/generate', query: to.query }
    }
  },
LiangLiu's avatar
LiangLiu committed
21
22
23
24
25
26
  {
    path: '/login', name: 'Login', component: Login, meta: { requiresAuth: false }
  },
  {
    path: '/share/:shareId', name: 'Share', component: Share, meta: { requiresAuth: false }
  },
27
28
29
30
31
32
  {
    path: '/podcast_generate', name: 'PodcastGenerate', component: PodcastGenerate, meta: { requiresAuth: true }
  },
  {
    path: '/podcast_generate/:session_id', name: 'PodcastSession', component: PodcastGenerate, meta: { requiresAuth: true }
  },
LiangLiu's avatar
LiangLiu committed
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  {
    path: '/home',
    component: Layout,
    meta: {
      requiresAuth: true
    },
    children: [
      {
        path: '/generate',
        name: 'Generate',
        component: Generate,
        meta: { requiresAuth: true },
        props: route => ({ query: route.query })
      },
      {
        path: '/projects',
        name: 'Projects',
        component: Projects,
        meta: { requiresAuth: true },
        props: route => ({ query: route.query })
      },
      {
        path: '/inspirations',
        name: 'Inspirations',
        component: Inspirations,
        meta: { requiresAuth: true },
        props: route => ({ query: route.query })
      },
      {
        path: '/task/:taskId',
        name: 'TaskDetail',
        component: Projects,
        meta: { requiresAuth: true },
        props: route => ({ taskId: route.params.taskId, query: route.query })
      },
      {
        path: '/template/:templateId',
        name: 'TemplateDetail',
        component: Inspirations,
        meta: { requiresAuth: true },
        props: route => ({ templateId: route.params.templateId, query: route.query })
      },
    ]
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'NotFound',
    component: () => import('../views/404.vue')
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

LiangLiu's avatar
LiangLiu committed
89
// 路由守卫 - 整合和优化后的逻辑
LiangLiu's avatar
LiangLiu committed
90
91
router.beforeEach((to, from, next) => {
  const token = localStorage.getItem('accessToken')
LiangLiu's avatar
LiangLiu committed
92
  console.log('token', token)
LiangLiu's avatar
LiangLiu committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
  // 检查 URL 中是否有 code 参数(OAuth 回调)
  // 可以从路由查询参数或实际 URL 中获取
  const hasOAuthCode = to.query?.code !== undefined ||
                      (typeof window !== 'undefined' && new URLSearchParams(window.location.search).get('code') !== null)

  // 1. OAuth 回调处理:如果有 code 参数(GitHub/Google 登录回调),直接放行
  // App.vue 的 onMounted 会处理登录回调逻辑
  if (hasOAuthCode) {
    console.log('检测到 OAuth 回调,放行让 App.vue 处理')
    next()
    return
  }

  // 2. 不需要登录的页面(登录页、分享页等)
LiangLiu's avatar
LiangLiu committed
107
  if (to.meta.requiresAuth === false) {
LiangLiu's avatar
LiangLiu committed
108
    // 如果已登录用户访问登录页,重定向到生成页面
LiangLiu's avatar
LiangLiu committed
109
110
    if (token && to.path === '/login') {
      console.log('已登录用户访问登录页,重定向到生成页')
LiangLiu's avatar
LiangLiu committed
111
      next('/generate')
LiangLiu's avatar
LiangLiu committed
112
    } else {
LiangLiu's avatar
LiangLiu committed
113
      next()
LiangLiu's avatar
LiangLiu committed
114
    }
LiangLiu's avatar
LiangLiu committed
115
    return
LiangLiu's avatar
LiangLiu committed
116
117
  }

LiangLiu's avatar
LiangLiu committed
118
119
120
  // 3. 需要登录的页面处理
  if (!token) {
    // 未登录但访问需要登录的页面,跳转到登录页
LiangLiu's avatar
LiangLiu committed
121
    console.log('需要登录但未登录,跳转到登录页')
LiangLiu's avatar
LiangLiu committed
122
123
124
    next('/login')
    // 延迟显示提示,确保路由跳转完成
    setTimeout(() => {
125
      showAlert(i18n.global.t('pleaseLoginFirst'), 'warning')
LiangLiu's avatar
LiangLiu committed
126
127
128
129
130
131
132
133
134
135
    }, 100)
    return
  }

  // 4. 已登录用户处理
  // 已登录用户访问首页,重定向到生成页(保留查询参数)
  if (to.path === '/') {
    console.log('已登录用户访问首页,重定向到生成页')
    const query = to.query && Object.keys(to.query).length > 0 ? to.query : {}
    next({ path: '/generate', query })
LiangLiu's avatar
LiangLiu committed
136
  } else {
LiangLiu's avatar
LiangLiu committed
137
138
    // 已登录且访问其他页面,正常放行
    next()
LiangLiu's avatar
LiangLiu committed
139
140
141
142
143
144
  }
})



export default router;