From c5433091cd7d6ac6dc17b1ef971f109b3501ed18 Mon Sep 17 00:00:00 2001 From: Pissofdvpe Date: Wed, 25 Feb 2026 21:40:24 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=90=9Efix(theme):=20=E6=B7=B1?= =?UTF-8?q?=E5=BA=A6=E9=87=8D=E6=9E=84=E4=B8=BB=E9=A2=98=E8=89=B2=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=EF=BC=8C=E5=AE=9E=E7=8E=B0=E7=B2=BE=E5=87=86=E8=89=B2?= =?UTF-8?q?=E5=87=86=E8=BF=98=E5=8E=9F=E4=B8=8E=E5=85=A8=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E8=A7=86=E8=A7=89=E5=B9=B3=E8=A1=A1=20(fixes=20#783)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构主题色生成算法,解决颜色不明显及特定色系不显示问题: - 针对主色变体实现高保真逻辑:跳过 HCT 变换,100% 忠实还原用户在调色板选定的原始 RGB 值,彻底解决黄色偏绿、红色偏橘等色相偏移难题。 - 引入辅助色饱和度爆发机制:针对次色、第三色等变体,手动提升 Chroma 基准,确保辅助色鲜艳且具备识别度,不再退化为暗淡灰色。 - 实现错误色动态生成:打破 M3 强制红色的限制,根据主色补色动态计算,确保任何色系下错误信息均具备极强视觉反差。 - 引入感知色调自适应校准逻辑: - 浅色模式:将主色亮度锚定在 Tone 40,确保高明度色相在白底上具备充足的对比度与视觉存在感。 - 深色模式:将主色亮度锚定在 Tone 80,确保低明度色相在暗色背景下具备极佳的透亮度。 - 优化深色模式视觉纯净度: - 强制深色模式背景饱和度为 0,彻底消除栏目垫底色的主色染色现象,回归深邃纯净的界面质感。 - 完善系统架构与代码健壮性: - 恢复次色作为系统默认变体,提供色彩美感与视觉舒适度的最佳平衡点。 - 修复 MONOTONOUS_THEME 定义中的属性重复及属性缺失导致的 TypeScript 编译报错。 - 撤销不必要的设置项版本强制迁移逻辑,完全尊重用户的个性化观感偏好。 --- src/utils/color.ts | 58 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/src/utils/color.ts b/src/utils/color.ts index 67bfb8668..193345970 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -45,20 +45,60 @@ const getAccentColor = (argb: number) => { * @param variant 变体名称,默认为 'secondary' */ const getThemeSchema = (theme: Theme, variant: keyof Theme["palettes"] = "secondary") => { - const { hue, chroma } = theme.palettes[variant]; - const getColor = (tone: number) => getAccentColor(Hct.from(hue, chroma, tone).toInt()); + // 获取基于主色的 HCT 属性 + const hct = Hct.fromInt(theme.source); + + /** + * 辅助色饱和度增强逻辑 + */ + let targetHue = hct.hue; + let targetChroma = hct.chroma; + const palette = theme.palettes[variant]; + + if (variant === "primary") { + targetHue = hct.hue; + targetChroma = hct.chroma; + } else if (variant === "secondary") { + targetHue = palette.hue; + targetChroma = Math.max(hct.chroma * 0.7, 45); + } else if (variant === "tertiary") { + targetHue = palette.hue; + targetChroma = Math.max(hct.chroma * 0.8, 60); + } else if (variant === "neutral") { + targetHue = hct.hue; + targetChroma = 15; + } else if (variant === "neutralVariant") { + targetHue = hct.hue; + targetChroma = 20; + } else if (variant === "error") { + targetHue = (hct.hue + 180) % 360; + targetChroma = Math.max(hct.chroma, 80); + } + + // 获取指定属性的颜色 + const getColor = (tone: number) => getAccentColor(Hct.from(targetHue, targetChroma, tone).toInt()); + + /** + * 界面辅助色生成逻辑 + */ + const getHelperColor = (tone: number, chroma: number = 4) => + getAccentColor(Hct.from(hct.hue, chroma, tone).toInt()); + + const isPrimary = variant === "primary"; + const sourceRgb = getAccentColor(theme.source); + return { - main: getColor(90), + main: isPrimary ? sourceRgb : getColor(80), light: { - primary: getColor(10), - background: getColor(94), - "surface-container": getColor(90), + primary: isPrimary ? sourceRgb : getColor(40), + background: getHelperColor(98, 2), + "surface-container": getHelperColor(94, 4), }, dark: { - primary: getColor(90), - background: getColor(20), - "surface-container": getColor(16), + primary: isPrimary ? sourceRgb : getColor(80), + background: getAccentColor(Hct.from(hct.hue, 0, 10).toInt()), + "surface-container": getAccentColor(Hct.from(hct.hue, 2, 14).toInt()), }, }; }; From d87fd7f3e9baa620d41b7baedc08d9135069cd42 Mon Sep 17 00:00:00 2001 From: Pissofdvpe Date: Wed, 25 Feb 2026 22:30:24 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=90=9Efix(theme):=20=E5=93=8D?= =?UTF-8?q?=E5=BA=94=E4=BB=A3=E7=A0=81=E5=AE=A1=E6=9F=A5=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=B8=BB=E9=A2=98=E8=89=B2=E7=AE=97=E6=B3=95=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 src/utils/color.ts 中重构 getThemeSchema 函数,提升代码可读性与一致性: - 使用 switch 语句替换原有的 if-else if 链,简化变体逻辑路径。 - 提取 darkPrimary 变量统一管理深色模式下的主色输出,消除重复计算逻辑。 - 统一深色模式背景与容器色的生成逻辑,全面复用 getHelperColor 辅助函数。 --- src/utils/color.ts | 53 ++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/utils/color.ts b/src/utils/color.ts index 193345970..9f0d4aee5 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -47,58 +47,55 @@ const getAccentColor = (argb: number) => { const getThemeSchema = (theme: Theme, variant: keyof Theme["palettes"] = "secondary") => { // 获取基于主色的 HCT 属性 const hct = Hct.fromInt(theme.source); - - /** - * 辅助色饱和度增强逻辑 - */ let targetHue = hct.hue; let targetChroma = hct.chroma; const palette = theme.palettes[variant]; - if (variant === "primary") { - targetHue = hct.hue; - targetChroma = hct.chroma; - } else if (variant === "secondary") { - targetHue = palette.hue; - targetChroma = Math.max(hct.chroma * 0.7, 45); - } else if (variant === "tertiary") { - targetHue = palette.hue; - targetChroma = Math.max(hct.chroma * 0.8, 60); - } else if (variant === "neutral") { - targetHue = hct.hue; - targetChroma = 15; - } else if (variant === "neutralVariant") { - targetHue = hct.hue; - targetChroma = 20; - } else if (variant === "error") { - targetHue = (hct.hue + 180) % 360; - targetChroma = Math.max(hct.chroma, 80); + switch (variant) { + case "secondary": + targetHue = palette.hue; + targetChroma = Math.max(hct.chroma * 0.7, 45); + break; + case "tertiary": + targetHue = palette.hue; + targetChroma = Math.max(hct.chroma * 0.8, 60); + break; + case "neutral": + targetChroma = 15; + break; + case "neutralVariant": + targetChroma = 20; + break; + case "error": + targetHue = (hct.hue + 180) % 360; + targetChroma = Math.max(hct.chroma, 80); + break; } - // 获取指定属性的颜色 const getColor = (tone: number) => getAccentColor(Hct.from(targetHue, targetChroma, tone).toInt()); /** - * 界面辅助色生成逻辑 + * 生成辅助色 */ const getHelperColor = (tone: number, chroma: number = 4) => getAccentColor(Hct.from(hct.hue, chroma, tone).toInt()); const isPrimary = variant === "primary"; const sourceRgb = getAccentColor(theme.source); + const darkPrimary = isPrimary ? sourceRgb : getColor(80); return { - main: isPrimary ? sourceRgb : getColor(80), + main: darkPrimary, light: { primary: isPrimary ? sourceRgb : getColor(40), background: getHelperColor(98, 2), "surface-container": getHelperColor(94, 4), }, dark: { - primary: isPrimary ? sourceRgb : getColor(80), - background: getAccentColor(Hct.from(hct.hue, 0, 10).toInt()), - "surface-container": getAccentColor(Hct.from(hct.hue, 2, 14).toInt()), + primary: darkPrimary, + background: getHelperColor(10, 0), + "surface-container": getHelperColor(14, 2), }, }; }; From 21bee8e379a87e497054dc586468b27e11625d20 Mon Sep 17 00:00:00 2001 From: Pissofdvpe Date: Thu, 26 Feb 2026 14:57:00 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=90=9Efix(theme/FullPlayer):=20?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E4=B8=BB=E9=A2=98=E7=B3=BB=E7=BB=9F=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E5=BC=95=E8=B5=B7=E7=9A=84=E5=85=A8=E5=B1=8F=E6=92=AD?= =?UTF-8?q?=E6=94=BE=E5=99=A8=20UI=20=E9=A2=9C=E8=89=B2=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 解决由于主题色高保真重构逻辑误伤导致的全屏播放器 UI 颜色暗淡、色彩倾向失效问题: - 在 src/utils/color.ts 的 getThemeSchema 函数中,将全屏播放器 UI 装饰色 main 的逻辑与全局主题色彻底解耦。 - 还原重构前的通透感:将 main 颜色的亮度固定在色彩黄金点 Tone 85,确保其在全屏播放器深色背景下具备极佳的对比度与发光感。 - 恢复色彩识别度:引入饱和度保底补偿机制(Chroma 不低于 48),确保 UI 按钮能如实反映专辑封面的色彩倾向,彻底解决重构后产生的变白、变灰回归问题。 - 在确保全局主题色精准还原的同时,使全屏播放器 UI 的视觉表现完美回归至重构前的正常水平。 --- src/utils/color.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/utils/color.ts b/src/utils/color.ts index 9f0d4aee5..369483bbd 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -83,17 +83,20 @@ const getThemeSchema = (theme: Theme, variant: keyof Theme["palettes"] = "second const isPrimary = variant === "primary"; const sourceRgb = getAccentColor(theme.source); - const darkPrimary = isPrimary ? sourceRgb : getColor(80); return { - main: darkPrimary, + /** + * 全屏播放器 UI 显示逻辑 + * 使用 Tone 85,确保在深色背景下具有极高亮度的同时,保留足够的饱和度空间来体现色彩 + */ + main: getAccentColor(Hct.from(targetHue, Math.max(targetChroma, 48), 85).toInt()), light: { primary: isPrimary ? sourceRgb : getColor(40), background: getHelperColor(98, 2), "surface-container": getHelperColor(94, 4), }, dark: { - primary: darkPrimary, + primary: isPrimary ? sourceRgb : getColor(80), background: getHelperColor(10, 0), "surface-container": getHelperColor(14, 2), }, From 6b7a68f413eb0eaa53761765fe7a8af5e4676ace Mon Sep 17 00:00:00 2001 From: Pissofdvpe Date: Sat, 28 Feb 2026 13:42:07 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9Efix(theme):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=B8=BB=E9=A2=98=E9=85=8D=E8=89=B2=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E5=A4=8D=E8=83=8C=E6=99=AF=E6=9F=93=E8=89=B2?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 getThemeSchema 中将背景色设为纯净中性色,彻底消除开启全局着色后的背景染色感。 - 更新 MONOTONOUS_THEME 预设,确保其背景数值与动态生成的主题保持高度一致(深色模式统一为 #101014)。 - 在 Provider.vue 的监听列表中补全 themeVariant,修复切换配色变体时界面不实时刷新的问题。 - 清理 setColorSchemes 冗余逻辑及未使用的 getHelperColor 辅助函数,保持代码纯净。 --- src/components/Global/Provider.vue | 1 + src/utils/color.ts | 32 ++++++++++-------------------- 2 files changed, 11 insertions(+), 22 deletions(-) diff --git a/src/components/Global/Provider.vue b/src/components/Global/Provider.vue index 5e400c105..af3a7fa9d 100644 --- a/src/components/Global/Provider.vue +++ b/src/components/Global/Provider.vue @@ -293,6 +293,7 @@ const applyThemeBackgroundMode = () => { watch( () => [ settingStore.themeColorType, + settingStore.themeVariant, settingStore.themeFollowCover, settingStore.themeGlobalColor, settingStore.globalFont, diff --git a/src/utils/color.ts b/src/utils/color.ts index 369483bbd..15c86b44d 100644 --- a/src/utils/color.ts +++ b/src/utils/color.ts @@ -18,13 +18,13 @@ export const MONOTONOUS_THEME = { main: { r: 239, g: 239, b: 239 }, light: { primary: { r: 10, g: 10, b: 10 }, - background: { r: 238, g: 238, b: 238 }, - "surface-container": { r: 212, g: 212, b: 212 }, + background: { r: 255, g: 255, b: 255 }, + "surface-container": { r: 246, g: 246, b: 246 }, }, dark: { primary: { r: 239, g: 239, b: 239 }, - background: { r: 31, g: 31, b: 31 }, - "surface-container": { r: 39, g: 39, b: 39 }, + background: { r: 16, g: 16, b: 20 }, + "surface-container": { r: 24, g: 24, b: 28 }, }, }; @@ -75,12 +75,6 @@ const getThemeSchema = (theme: Theme, variant: keyof Theme["palettes"] = "second const getColor = (tone: number) => getAccentColor(Hct.from(targetHue, targetChroma, tone).toInt()); - /** - * 生成辅助色 - */ - const getHelperColor = (tone: number, chroma: number = 4) => - getAccentColor(Hct.from(hct.hue, chroma, tone).toInt()); - const isPrimary = variant === "primary"; const sourceRgb = getAccentColor(theme.source); @@ -92,13 +86,14 @@ const getThemeSchema = (theme: Theme, variant: keyof Theme["palettes"] = "second main: getAccentColor(Hct.from(targetHue, Math.max(targetChroma, 48), 85).toInt()), light: { primary: isPrimary ? sourceRgb : getColor(40), - background: getHelperColor(98, 2), - "surface-container": getHelperColor(94, 4), + background: { r: 255, g: 255, b: 255 }, + "surface-container": { r: 246, g: 246, b: 246 }, }, dark: { primary: isPrimary ? sourceRgb : getColor(80), - background: getHelperColor(10, 0), - "surface-container": getHelperColor(14, 2), + // 使用深邃的中性黑灰 + background: { r: 16, g: 16, b: 20 }, + "surface-container": { r: 24, g: 24, b: 28 }, }, }; }; @@ -139,14 +134,7 @@ export const setColorSchemes = ( // 指定模式颜色数据 const colorModeData = colorData[mode]; const modifiedColorModeData: { [key: string]: string } = {}; - // 是否全局应用 - if (!settingStore.themeGlobalColor && colorModeData) { - // 修改关键颜色 - colorModeData.background = - mode === "dark" ? { r: 16, g: 16, b: 20 } : { r: 246, g: 246, b: 246 }; - colorModeData["surface-container"] = - mode === "dark" ? { r: 24, g: 24, b: 28 } : { r: 255, g: 255, b: 255 }; - } + // 遍历颜色并修改 for (const key in colorModeData) { const color = colorModeData[key];