This commit is contained in:
2026-02-25 23:18:06 +08:00
parent 3e8218658b
commit 8beb4a5508
6 changed files with 1120 additions and 233 deletions

View File

@@ -1,16 +1,151 @@
<script setup>
import { RouterView } from 'vue-router'
import { ref, onMounted } from 'vue'
import { theme } from 'ant-design-vue'
import { ref, computed, watchEffect } from 'vue'
import SvgSprite from '@/components/icons/SvgSprite.vue'
import { useUserStore } from '@/stores/user'
import tokenManager from '@gold/utils/token-manager'
import zhCN from 'ant-design-vue/es/locale/zh_CN';
const themeToken = ref({
import zhCN from 'ant-design-vue/es/locale/zh_CN'
// ========================================
// Ant Design Vue 主题配置
// ========================================
const isDark = ref(false)
// 初始化主题
const initTheme = () => {
const stored = localStorage.getItem('theme')
if (stored) {
isDark.value = stored === 'dark'
} else {
isDark.value = window.matchMedia('(prefers-color-scheme: dark)').matches
}
document.documentElement.setAttribute('data-theme', isDark.value ? 'dark' : 'light')
}
// 主题切换
const toggleTheme = () => {
isDark.value = !isDark.value
document.documentElement.setAttribute('data-theme', isDark.value ? 'dark' : 'light')
localStorage.setItem('theme', isDark.value ? 'dark' : 'light')
}
// Ant Design 主题 Token
const themeToken = computed(() => {
const lightToken = {
// 品牌色
colorPrimary: '#3B82F6',
colorSuccess: '#22C55E',
colorWarning: '#F59E0B',
colorError: '#EF4444',
colorInfo: '#3B82F6',
// 背景色
colorBgContainer: '#FFFFFF',
colorBgElevated: '#FFFFFF',
colorBgLayout: '#F9FAFB',
// 边框
colorBorder: '#E5E7EB',
colorBorderSecondary: '#F3F4F6',
// 文字
colorText: '#111827',
colorTextSecondary: '#4B5563',
colorTextTertiary: '#6B7280',
colorTextQuaternary: '#9CA3AF',
// 填充
colorFill: '#F3F4F6',
colorFillSecondary: '#F9FAFB',
// 字体
fontFamily: '-apple-system, BlinkMacSystemFont, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif',
fontSize: 14,
// 圆角
borderRadius: 6,
borderRadiusSM: 4,
borderRadiusLG: 8,
// 控件尺寸
controlHeight: 32,
controlHeightSM: 28,
controlHeightLG: 40,
// 动画
motionDurationFast: '0.15s',
motionDurationMid: '0.2s',
motionDurationSlow: '0.3s',
// 阴影
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)',
boxShadowSecondary: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)',
}
const darkToken = {
colorPrimary: '#60A5FA',
colorBgContainer: '#1E293B',
colorBgElevated: '#334155',
colorBgLayout: '#0F172A',
colorBorder: '#334155',
colorBorderSecondary: '#1E293B',
colorText: '#F1F5F9',
colorTextSecondary: '#94A3B8',
colorTextTertiary: '#64748B',
colorTextQuaternary: '#475569',
colorFill: '#334155',
colorFillSecondary: '#1E293B',
boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.4), 0 1px 2px -1px rgba(0, 0, 0, 0.4)',
boxShadowSecondary: '0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -2px rgba(0, 0, 0, 0.4)',
}
return {
token: isDark.value ? { ...lightToken, ...darkToken } : lightToken,
components: {
Button: {
primaryShadow: 'none',
defaultShadow: 'none',
fontWeight: 500,
},
Input: {
paddingBlock: 6,
paddingInline: 12,
activeShadow: '0 0 0 3px rgba(59, 130, 246, 0.15)',
},
Select: {
optionSelectedBg: isDark.value ? 'rgba(96, 165, 250, 0.15)' : '#EFF6FF',
optionActiveBg: isDark.value ? '#334155' : '#F3F4F6',
},
Table: {
headerBg: isDark.value ? '#1E293B' : '#F9FAFB',
rowHoverBg: isDark.value ? '#334155' : '#F9FAFB',
borderColor: isDark.value ? '#334155' : '#E5E7EB',
headerColor: '#4B5563',
},
Card: {
paddingLG: 20,
borderRadiusLG: 12,
},
Modal: {
borderRadiusLG: 12,
},
Menu: {
itemHoverBg: isDark.value ? '#334155' : '#F3F4F6',
itemSelectedBg: isDark.value ? 'rgba(96, 165, 250, 0.15)' : '#EFF6FF',
itemSelectedColor: isDark.value ? '#60A5FA' : '#3B82F6',
},
},
}
})
onMounted(async () => {})
// 初始化
initTheme()
// 监听系统主题变化
watchEffect(() => {
const media = window.matchMedia('(prefers-color-scheme: dark)')
const handler = (e) => {
if (!localStorage.getItem('theme')) {
isDark.value = e.matches
document.documentElement.setAttribute('data-theme', e.matches ? 'dark' : 'light')
}
}
media.addEventListener('change', handler)
})
// 暴露给模板使用
defineExpose({ toggleTheme, isDark })
</script>
<template>