Files
chat/frontend/src/router/index.ts
T
2026-06-13 07:33:46 +08:00

178 lines
5.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router'
import { useAuthStore } from '@/stores/auth'
const routes: RouteRecordRaw[] = [
// ==================== 认证页面(套用 AuthLayout=====================
{
path: '/auth',
component: () => import('@/layouts/AuthLayout.vue'),
meta: { requiresAuth: false },
children: [
{ path: '/login', name: 'Login', component: () => import('@/views/auth/LoginView.vue') },
{ path: '/register', name: 'Register', component: () => import('@/views/auth/RegisterView.vue') },
],
},
// ==================== 主界面(统一布局)=====================
{
path: '/',
component: () => import('@/layouts/UnifiedLayout.vue'),
meta: { requiresAuth: true },
children: [
// 聊天
{
path: 'chat',
children: [
{
path: '',
name: 'ChatList',
components: {
secondary: () => import('@/views/chat/ConversationListPanel.vue'),
default: () => import('@/views/chat/ChatListView.vue'),
},
},
{
path: ':id',
name: 'ChatRoom',
meta: { hideSecondary: true },
components: {
secondary: () => import('@/views/chat/ConversationListPanel.vue'),
default: () => import('@/views/chat/ChatRoomView.vue'),
},
},
],
},
// 通讯录
{
path: 'contacts',
children: [
{
path: '',
name: 'Contacts',
components: {
secondary: () => import('@/views/contacts/ContactsSidebar.vue'),
default: () => import('@/views/contacts/ContactsView.vue'),
},
},
{
path: 'search',
name: 'Search',
components: {
secondary: () => import('@/views/contacts/ContactsSidebar.vue'),
default: () => import('@/views/contacts/SearchView.vue'),
},
},
],
},
// 朋友圈
{
path: 'moments',
name: 'Moments',
components: {
secondary: () => import('@/views/moments/MomentsFeedView.vue'),
default: () => import('@/views/moments/MomentsFeedView.vue'),
},
},
// 设置
{
path: 'settings',
children: [
{
path: '',
redirect: '/settings/profile',
},
{
path: 'profile',
name: 'SettingsProfile',
components: {
secondary: () => import('@/views/settings/SettingsSidebar.vue'),
default: () => import('@/views/settings/ProfileSettingsView.vue'),
},
},
{
path: 'account',
name: 'SettingsAccount',
components: {
secondary: () => import('@/views/settings/SettingsSidebar.vue'),
default: () => import('@/views/settings/AccountSettingsView.vue'),
},
},
{
path: 'notifications',
name: 'SettingsNotifications',
components: {
secondary: () => import('@/views/settings/SettingsSidebar.vue'),
default: () => import('@/views/settings/NotificationSettingsView.vue'),
},
},
{
path: 'about',
name: 'SettingsAbout',
components: {
secondary: () => import('@/views/settings/SettingsSidebar.vue'),
default: () => import('@/views/settings/AboutView.vue'),
},
},
],
},
// 根路径重定向
{ path: '', redirect: '/chat' },
{ path: 'profile', redirect: '/settings/profile' },
],
},
// ==================== 管理后台 =====================
{
path: '/admin/login',
name: 'AdminLogin',
component: () => import('@/views/admin/AdminLoginView.vue'),
meta: { requiresAuth: false },
},
{
path: '/admin',
component: () => import('@/layouts/AdminLayout.vue'),
meta: { requiresAuth: true },
children: [
{ path: '', redirect: '/admin/dashboard' },
{ path: 'dashboard', name: 'AdminDashboard', component: () => import('@/views/admin/AdminDashboardView.vue') },
{ path: 'users', name: 'AdminUsers', component: () => import('@/views/admin/AdminUsersView.vue') },
{ path: 'messages', name: 'AdminMessages', component: () => import('@/views/admin/AdminMessagesView.vue') },
{ path: 'config', name: 'AdminConfig', component: () => import('@/views/admin/AdminConfigView.vue') },
],
},
]
const router = createRouter({
history: createWebHistory(),
routes,
})
// 路由守卫
router.beforeEach(async (to, _from, next) => {
const authStore = useAuthStore()
// 首次加载时尝试恢复登录状态
if (!authStore.isAuthenticated && localStorage.getItem('access_token')) {
try {
await authStore.fetchProfile()
} catch {
authStore.logout()
}
}
const needsAuth = to.matched.some((record) => record.meta.requiresAuth)
if (needsAuth && !authStore.isAuthenticated) {
next({ name: 'Login', query: { redirect: to.fullPath } })
return
}
next()
})
export default router