feat: 使用自定义主题色

This commit is contained in:
2026-06-18 11:01:11 +08:00
parent c1e292ea18
commit 3bd6e972ea
12 changed files with 111 additions and 44 deletions

View File

@@ -1,6 +0,0 @@
{
"recommendations": [
"Vue.volar",
"oxc.oxc-vscode"
]
}

View File

@@ -1,3 +1,6 @@
/* ============================================================
* 全局重置样式
* ============================================================ */
*,
*::before,
*::after {
@@ -15,8 +18,8 @@ body {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
line-height: 1.5;
color: #333;
background-color: #fff;
color: var(--text-primary);
background-color: var(--bg-body);
}
#app {

View File

@@ -1 +1,2 @@
import './variables.scss'
import './base.css'

View File

@@ -0,0 +1,65 @@
// ============================================================
// 亮色主题 CSS 自定义属性
// 所有颜色和样式变量集中定义在此,组件通过 var() 引用
// ============================================================
:root {
// ---- 品牌色 ----
// 用于按钮、链接、选中态等需要突出品牌感的元素
--color-primary: #4f46e5; /* 主色(靛蓝):主要按钮、链接文字、激活态 */
--color-primary-hover: #4338ca; /* 主色悬停:按钮 hover / focus 时加深 */
--color-primary-light: #eef2ff; /* 主色浅底:选中背景、标签、高亮条底色 */
// ---- 文字色 ----
// 按重要性分三级,覆盖主要内容到辅助提示
--text-primary: #0f172a; /* 一级文字:标题、正文、重要信息 */
--text-secondary: #475569; /* 二级文字:描述、标签、次要信息 */
--text-tertiary: #94a3b8; /* 三级文字:占位符、禁用态、水印 */
--text-inverse: #ffffff; /* 反色文字:用于深色 / 品牌色背景上 */
--text-link: #4f46e5; /* 链接文字色 */
// ---- 背景色 ----
// 从底层到顶层依次变亮,形成自然层级
--bg-body: #f1f5f9; /* 页面底色:最底层背景 */
--bg-surface: #ffffff; /* 卡片/面板背景:浮于页面之上的容器 */
--bg-surface-hover: #f8fafc; /* 卡片悬停:鼠标经过时的微变反馈 */
--bg-sidebar: #f8fafc; /* 侧边栏背景:导航区域的专用底色 */
--bg-topbar: #ffffff; /* 顶部栏背景:顶部导航条的底色 */
--bg-elevated: #ffffff; /* 浮层背景:弹出菜单、下拉面板等最高层 */
// ---- 边框色 ----
--border-default: #e2e8f0; /* 默认边框:卡片、输入框、分割线 */
--border-light: #f1f5f9; /* 浅边框:表格行间、轻分割 */
// ---- 阴影 ----
// 按海拔高度递进,越高的层级阴影越重
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05); /* 微小阴影:卡片默认态 */
--shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.07); /* 中等阴影:悬停卡片 */
--shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.08); /* 大阴影:弹窗、抽屉 */
// ---- 圆角 ----
--radius-sm: 6px; /* 小圆角:标签、小按钮 */
--radius-md: 12px; /* 中圆角:卡片、面板、输入框 */
--radius-lg: 24px; /* 大圆角:模态框、大卡片 */
// ---- 间距 ----
--space-xs: 4px; /* 极小间距:图标与文字之间 */
--space-sm: 8px; /* 小间距:组件内部紧凑排列 */
--space-md: 16px; /* 中间距:卡片内边距、列表项间隙 */
--space-lg: 24px; /* 大间距:区块之间 */
// ---- 语义色 ----
// 传达状态和反馈,不与品牌色混淆
--color-success: #10b981; /* 成功:通过、完成、在线 */
--color-success-light: #ecfdf5; /* 成功浅底 */
--color-warning: #f59e0b; /* 警告:需要注意、待处理 */
--color-warning-light: #fffbeb; /* 警告浅底 */
--color-danger: #ef4444; /* 危险:错误、删除、不可逆操作 */
--color-danger-light: #fef2f2; /* 危险浅底 */
--color-info: #3b82f6; /* 信息:提示、帮助、说明 */
--color-info-light: #eff6ff; /* 信息浅底 */
// ---- 滚动条 ----
--scrollbar-thumb: #cbd5e1; /* 滚动条滑块颜色 */
--scrollbar-track: transparent; /* 滚动条轨道颜色 */
}

View File

@@ -117,7 +117,7 @@ function selectGame(id: string) {
display: flex;
height: 100%;
width: 100%;
color: #fff;
color: var(--text-primary);
}
/* ===== 左侧图标列表 ===== */
@@ -129,7 +129,7 @@ function selectGame(id: string) {
flex-shrink: 0;
padding: 8px 4px;
overflow-y: auto;
border-right: 1px solid rgba(255, 255, 255, 0.15);
border-right: 1px solid var(--border-light);
}
.game-list__icon-item {
@@ -143,11 +143,11 @@ function selectGame(id: string) {
transition: background-color 0.2s ease;
&:hover {
background-color: rgba(255, 255, 255, 0.15);
background-color: var(--bg-surface-hover);
}
&--active {
background-color: rgba(255, 255, 255, 0.25);
background-color: var(--color-primary-light);
}
}
@@ -174,7 +174,7 @@ function selectGame(id: string) {
.game-list__detail-desc {
font-size: 14px;
line-height: 1.6;
color: rgba(255, 255, 255, 0.8);
color: var(--text-secondary);
margin-bottom: 24px;
}
@@ -183,13 +183,13 @@ function selectGame(id: string) {
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
color: rgba(255, 255, 255, 0.9);
color: var(--text-primary);
}
p {
font-size: 13px;
line-height: 1.7;
color: rgba(255, 255, 255, 0.7);
color: var(--text-secondary);
}
}
@@ -198,7 +198,7 @@ function selectGame(id: string) {
align-items: center;
justify-content: center;
height: 100%;
color: rgba(255, 255, 255, 0.5);
color: var(--text-tertiary);
font-size: 14px;
}
</style>

View File

@@ -17,7 +17,7 @@
</el-popover>
<div class="feature">
<el-icon color="#fff" :size="26"><Setting /></el-icon>
<el-icon :size="26"><Setting /></el-icon>
</div>
</div>
</div>
@@ -42,7 +42,7 @@ import { Setting } from '@element-plus/icons-vue'
}
.user-badge :deep(.el-badge__content.is-dot) {
background-color: #008000;
background-color: var(--color-success);
}
.container {

View File

@@ -11,8 +11,8 @@
</Transition>
</RouterView>
<div class="auth-layout__footer">
<span style="color: #71717a">Copyright © 2024</span>
<a href="javascript:void(0)" class="auth-layout__footer-link" style="color: #2080f0"
<span style="color: var(--text-tertiary)">Copyright © 2024</span>
<a href="javascript:void(0)" class="auth-layout__footer-link" style="color: var(--text-link)"
>MarchGlow</a
>
</div>
@@ -61,8 +61,8 @@
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #fff;
border-radius: 24px;
background-color: var(--bg-surface);
border-radius: var(--radius-lg);
padding: 40px 24px 40px 24px;
width: 100%;
}

View File

@@ -58,7 +58,8 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
width: 100%;
height: 30px;
padding: 0 12px;
background-color: #fde68a; // amber-200
background-color: var(--bg-topbar);
border-bottom: 1px solid var(--border-default);
}
.base-layout__topbar-title {
@@ -83,7 +84,7 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
font-weight: 500;
line-height: 1;
height: 100%;
color: #1a1a1a;
color: var(--text-primary);
}
.base-layout__main {
@@ -99,8 +100,9 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
position: relative;
width: 400px;
height: 100%;
padding: 8px;
background-color: #fcd34d; // amber-300
padding: var(--space-sm);
background-color: var(--bg-sidebar);
border-right: 1px solid var(--border-default);
}
.base-layout__sidebar-content {
@@ -109,7 +111,6 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
height: 100%;
width: 100%;
padding-bottom: 72px;
background-color: #f59e0b; // amber-500
}
.base-layout__sidebar-bottom {
@@ -120,7 +121,7 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
height: 72px;
left: 0;
bottom: 0;
padding: 8px;
padding: var(--space-sm);
}
.base-layout__sidebar-bottom-inner {
@@ -128,8 +129,10 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
flex: 1;
width: 100%;
height: 100%;
border-radius: 12px;
background-color: #92400e; // amber-800
border-radius: var(--radius-md);
background-color: var(--bg-surface);
box-shadow: var(--shadow-sm);
border: 1px solid var(--border-light);
}
.base-layout__resize-handle {
@@ -139,9 +142,10 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
top: 0;
right: 0;
cursor: ew-resize;
transition: background-color 0.2s ease;
&:hover {
background-color: #d1d5db; // gray-300
background-color: var(--border-default);
}
}
@@ -150,6 +154,6 @@ const { activeGameIcon, activeGameName } = storeToRefs(baseLayoutStore)
flex: 1;
width: 100%;
height: 100%;
background-color: #fbbf24; // amber-400
background-color: var(--bg-body);
}
</style>

View File

@@ -3,7 +3,7 @@
<div class="login-wrapper__header">
<h2 class="login-wrapper__title">欢迎回来 👋🏻</h2>
<p>
<span style="color: #71717a">登录账号以进入对战</span>
<span style="color: var(--text-tertiary)">登录账号以进入对战</span>
</p>
</div>
<el-form
@@ -34,7 +34,7 @@
<el-form-item>
<div class="login-wrapper__actions">
<el-checkbox v-model="rememberAccount">记住账号</el-checkbox>
<a href="javascript:void(0)" style="color: #2080f0">忘记密码</a>
<a href="javascript:void(0)" style="color: var(--text-link)">忘记密码</a>
</div>
</el-form-item>
<el-form-item>
@@ -55,7 +55,7 @@
<el-form-item>
<div class="login-wrapper__register-link">
<span>没有账号</span>
<router-link to="/auth/register" style="color: #2080f0">创建账号</router-link>
<router-link to="/auth/register" style="color: var(--text-link)">创建账号</router-link>
</div>
</el-form-item>
</el-form>

View File

@@ -3,7 +3,7 @@
<div class="phone-login-wrapper__header">
<h2 class="phone-login-wrapper__title">欢迎回来 📲</h2>
<p>
<span style="color: #71717a">请输入手机号码登录账号以进入对战</span>
<span style="color: var(--text-tertiary)">请输入手机号码登录账号以进入对战</span>
</p>
</div>
<el-form
@@ -27,7 +27,7 @@
v-model="loginModel.code"
:length="6"
:formatter="onlyAllowNumber"
style="flex: 2; --el-input-otp-gap: 0"
style="flex: 2; --el-input-otp-gap: 4px"
>
<template #separator></template>
</el-input-otp>

View File

@@ -3,7 +3,7 @@
<div class="qrcode-login-wrapper__header">
<h2 class="qrcode-login-wrapper__title">欢迎回来 📱</h2>
<p>
<span style="color: #71717a">请用手机扫描二维码登录</span>
<span style="color: var(--text-tertiary)">请用手机扫描二维码登录</span>
</p>
</div>
<el-form hide-required-asterisk class="qrcode-login-wrapper__form">

View File

@@ -3,7 +3,7 @@
<div class="register-wrapper__header">
<h2 class="register-wrapper__title">创建一个账号 🚀</h2>
<p>
<span style="color: #71717a">创建账号进入对战</span>
<span style="color: var(--text-tertiary)">创建账号进入对战</span>
</p>
</div>
<el-form
@@ -39,7 +39,7 @@
></div>
</div>
</div>
<p class="register-wrapper__password-hint" style="color: #71717a">
<p class="register-wrapper__password-hint" style="color: var(--text-tertiary)">
使用 8 个或更多字符混合大小写字母数字
</p>
</div>
@@ -57,7 +57,7 @@
<el-form-item prop="agreement">
<div class="register-wrapper__agreement">
<el-checkbox v-model="registerModel.agreement">我同意</el-checkbox>
<a href="javascript:void(0)" style="color: #2080f0">隐私政策 & 条款</a>
<a href="javascript:void(0)" style="color: var(--text-link)">隐私政策 & 条款</a>
</div>
</el-form-item>
<el-form-item>
@@ -68,7 +68,7 @@
<el-form-item>
<div class="register-wrapper__login-link">
<span>已经有账号了</span>
<router-link to="/auth/login" style="color: #2080f0">去登录</router-link>
<router-link to="/auth/login" style="color: var(--text-link)">去登录</router-link>
</div>
</el-form-item>
</el-form>
@@ -275,7 +275,7 @@ const userRegisterFun = () => {
height: 8px;
border-radius: 12px;
position: relative;
background-color: #e5e7eb;
background-color: var(--border-default);
overflow: hidden;
}
@@ -284,7 +284,7 @@ const userRegisterFun = () => {
left: 0;
top: 0;
height: 100%;
background-color: #ef4444;
background-color: var(--color-danger);
transition: all 500ms;
}