优化内容: 1. 新增 MainLayout.vue 独立布局组件 - 封装 TopNav、SidebarNav、主内容区域 - 独立的页面脚注 2. 简化 App.vue - 只负责主题配置和SvgSprite - 只渲染 RouterView - 移除所有布局相关代码 3. 重构路由配置 - 登录页 /login:独立渲染,不使用Layout - 根路由 /:使用 MainLayout,渲染所有需要布局的页面 - 所有业务页面都作为根路由的子路由嵌套渲染 架构优势: - 登录页独立,不受主布局影响 - 主布局统一管理,减少重复代码 - 路由结构清晰,易于维护 - 符合Vue最佳实践 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
82 lines
2.6 KiB
Vue
82 lines
2.6 KiB
Vue
<script setup>
|
||
import { RouterView } from 'vue-router'
|
||
import { ref, onMounted } from 'vue'
|
||
import { theme } from 'ant-design-vue'
|
||
import SvgSprite from '@/components/icons/SvgSprite.vue'
|
||
import { useUserStore } from '@/stores/user'
|
||
import tokenManager from '@gold/utils/token-manager'
|
||
|
||
function readCssVar(name) {
|
||
return getComputedStyle(document.documentElement).getPropertyValue(name).trim() || undefined
|
||
}
|
||
|
||
const themeToken = ref({
|
||
algorithm: theme.darkAlgorithm,
|
||
token: {
|
||
colorPrimary: '#3B82F6',
|
||
colorInfo: '#1A66E0',
|
||
colorBgBase: '#0D0D0D',
|
||
colorBgContainer: '#1A1A1A',
|
||
colorTextBase: '#F2F2F2',
|
||
colorTextSecondary: '#CCCCCC',
|
||
colorBorder: '#333333',
|
||
borderRadius: 6,
|
||
}
|
||
})
|
||
|
||
onMounted(async () => {
|
||
// 运行时从 :root 读取,若存在则覆盖默认值
|
||
const next = { ...themeToken.value.token }
|
||
next.colorPrimary = readCssVar('--color-primary') || next.colorPrimary
|
||
next.colorInfo = readCssVar('--color-blue') || next.colorInfo
|
||
next.colorBgBase = readCssVar('--color-bg') || next.colorBgBase
|
||
next.colorBgContainer = readCssVar('--color-surface') || next.colorBgContainer
|
||
next.colorTextBase = readCssVar('--color-text') || next.colorTextBase
|
||
next.colorTextSecondary = readCssVar('--color-text-secondary') || next.colorTextSecondary
|
||
next.colorBorder = readCssVar('--color-border') || next.colorBorder
|
||
themeToken.value = { algorithm: theme.darkAlgorithm, token: next }
|
||
|
||
// 检查登录状态:如果有token但store中未标记为登录,则恢复登录状态
|
||
const userStore = useUserStore()
|
||
|
||
// 等待store从本地存储恢复完成(最多等待500ms)
|
||
let waitCount = 0
|
||
while (!userStore.isHydrated && waitCount < 50) {
|
||
await new Promise(resolve => setTimeout(resolve, 10))
|
||
waitCount++
|
||
}
|
||
|
||
const token = tokenManager.getAccessToken()
|
||
if (token) {
|
||
// 如果有token但未登录,可能是刷新页面,需要恢复登录状态
|
||
if (!userStore.isLoggedIn) {
|
||
userStore.isLoggedIn = true
|
||
// 尝试获取用户信息
|
||
try {
|
||
await userStore.fetchUserInfo()
|
||
} catch (error) {
|
||
console.error('初始化用户信息失败:', error)
|
||
}
|
||
} else if (!userStore.nickname && !userStore.userId) {
|
||
// 如果已登录但没有用户信息,尝试获取
|
||
try {
|
||
await userStore.fetchUserInfo()
|
||
} catch (error) {
|
||
console.error('获取用户信息失败:', error)
|
||
}
|
||
}
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<a-config-provider :theme="themeToken">
|
||
<SvgSprite />
|
||
<RouterView />
|
||
</a-config-provider>
|
||
</template>
|
||
|
||
<style>
|
||
/* 全局样式保持不变 */
|
||
</style>
|