fix(theme): 深色模式下主色衍生色阶改用暗底混合

applyPrimaryColor 恒定用白色混出 --el-color-primary-light-N,而这些值写的是 documentElement 内联变量,优先级高于 Element Plus 的 html.dark 样式表,导致深色下 light-9 仍是近白(#ecf5ff),plain 按钮(底色=light-9)在深色界面里是一块近白补丁。改为按当前明暗选择混合基色:深色 light-N 混 #141414、dark-2 反向混白 0.2,取值与 EP 暗色主题逐值一致(light-9 #18222b / dark-2 #66b1ff);浅色逻辑不变。
This commit is contained in:
TermiNexus committed 2026-09-30 20:24:46 +08:00
1 parent 5e277eb167
commit 1cdc44c1d0
1 file changed
+26 -13
+26 -13
View File
@@ -4,7 +4,7 @@ import { ref } from 'vue'
/** 主题类型:default / light / dark / green / purple / red */
export type ThemeMode = 'default' | 'light' | 'dark' | 'green' | 'purple' | 'red'
/** 主题色板:主色 + Element Plus 衍生色(light-N 为主色混白,dark-2 为主色混黑) */
/** 主题色板:主色 + Element Plus 衍生色(浅色 light-N=混白、深色 light-N=混暗底) */
interface ThemePalette {
/** 是否深色模式(驱动 html.dark) */
dark: boolean
@@ -94,7 +94,8 @@ const PRIMARY_KEY = 'gerp-primary'
/**
* 十六进制颜色与白/黑按比例混合(对齐 Element Plus light-N/dark-2 派生规则)
* light-N:主色混白 N*10%;dark-2:主色混黑 20%
* 浅色主题:light-N = 主色混白 N*10%;深色主题:light-N = 主色混暗底 N*10%
* dark-2:浅色主题混黑 20%;深色主题反向提亮(混白 20%)
*/
function mixColor(hex: string, mix: string, weight: number): string {
const parse = (c: string): [number, number, number] => {
@@ -114,17 +115,29 @@ function mixColor(hex: string, mix: string, weight: number): string {
return `#${[r, g, b].map((v) => v.toString(16).padStart(2, '0')).join('')}`
}
/** 把主色应用到 Element Plus CSS 变量(含全部衍生色阶) */
function applyPrimaryColor(color: string): void {
/** Element Plus 暗色主题 light-N 的混合基色(取 EP dark 变量 --el-bg-color: #141414) */
const DARK_MIX_BASE = '#141414'
/**
* 把主色应用到 Element Plus CSS 变量(含全部衍生色阶)。
*
* 必须以「当前是否深色」区分混合基色:这里写入的是 documentElement 的内联变量,
* 优先级高于 Element Plus 的 html.dark 样式表;若两种模式都混白,深色下
* light-9 仍是近白色(如 #ecf5ff),plain 按钮底色(= light-9)会变成深色界面里的
* 一块近白补丁。深色取值与 EP 暗色主题逐值一致(light-9 #18222b / dark-2 #66b1ff)。
*/
function applyPrimaryColor(color: string, isDark: boolean): void {
const root = document.documentElement
const lightMix = isDark ? DARK_MIX_BASE : '#ffffff'
const darkMix = isDark ? '#ffffff' : '#000000'
const vars: Record<string, string> = {
'--el-color-primary': color,
'--el-color-primary-light-3': mixColor(color, '#ffffff', 0.3),
'--el-color-primary-light-5': mixColor(color, '#ffffff', 0.5),
'--el-color-primary-light-7': mixColor(color, '#ffffff', 0.7),
'--el-color-primary-light-8': mixColor(color, '#ffffff', 0.8),
'--el-color-primary-light-9': mixColor(color, '#ffffff', 0.9),
'--el-color-primary-dark-2': mixColor(color, '#000000', 0.2),
'--el-color-primary-light-3': mixColor(color, lightMix, 0.3),
'--el-color-primary-light-5': mixColor(color, lightMix, 0.5),
'--el-color-primary-light-7': mixColor(color, lightMix, 0.7),
'--el-color-primary-light-8': mixColor(color, lightMix, 0.8),
'--el-color-primary-light-9': mixColor(color, lightMix, 0.9),
'--el-color-primary-dark-2': mixColor(color, darkMix, 0.2),
}
for (const [k, v] of Object.entries(vars)) {
root.style.setProperty(k, v)
@@ -153,7 +166,7 @@ export const useAppStore = defineStore('app', () => {
root.classList.toggle('dark', cfg.dark)
// vxe-table 暗色主题([data-vxe-ui-theme="dark"] 触发其内置暗色变量)
root.setAttribute('data-vxe-ui-theme', cfg.dark ? 'dark' : 'light')
applyPrimaryColor(customPrimary.value ?? cfg.primary)
applyPrimaryColor(customPrimary.value ?? cfg.primary, cfg.dark)
localStorage.setItem(THEME_KEY, value)
}
@@ -164,7 +177,7 @@ export const useAppStore = defineStore('app', () => {
function setCustomColor(color: string | null): void {
customPrimary.value = color
const cfg = THEME_CONFIGS[theme.value] ?? THEME_CONFIGS.default
applyPrimaryColor(color ?? cfg.primary)
applyPrimaryColor(color ?? cfg.primary, cfg.dark)
if (color) localStorage.setItem(PRIMARY_KEY, color)
else localStorage.removeItem(PRIMARY_KEY)
}
@@ -179,7 +192,7 @@ export const useAppStore = defineStore('app', () => {
const root = document.documentElement
root.classList.toggle('dark', cfg.dark)
root.setAttribute('data-vxe-ui-theme', cfg.dark ? 'dark' : 'light')
applyPrimaryColor(customPrimary.value ?? cfg.primary)
applyPrimaryColor(customPrimary.value ?? cfg.primary, cfg.dark)
}
/** 顶栏快捷切换:浅色主题 ↔ 深色主题(保持当前配色) */