diff --git a/frontend/admin/src/App.vue b/frontend/admin/src/App.vue
index fd0442f9e..6baf3ade6 100644
--- a/frontend/admin/src/App.vue
+++ b/frontend/admin/src/App.vue
@@ -22,6 +22,7 @@ import config from '../package.json';
import bus from '@/utils/bus';
import { useMediaStore } from '@/store/module/media';
import { useThemeConfigStore } from '@/store/module/themeConfig';
+import { filterThemeCssText } from '@/utils/theme.js';
defineOptions({ name: 'app' });
@@ -69,7 +70,9 @@ function onOpenSetingsDrawer() {
function getLayoutThemeConfig() {
if (Local.get('themeConfigPrev')) {
themeConfigStore.setThemeConfig(Local.get('themeConfigPrev'));
- document.documentElement.style.cssText = Local.get('themeConfigStyle');
+ // 恢复时过滤主色浅/深阶(历史脏数据清洗):这些变量由样式表 color-mix 动态计算,
+ // 行内持久化会压过 dark.scss 暗色档,导致深色模式表头/浅底仍为浅色
+ document.documentElement.style.cssText = filterThemeCssText(Local.get('themeConfigStyle'));
} else {
Local.set('themeConfigPrev', themeConfigStore.themeConfig);
}
diff --git a/frontend/admin/src/layout/navBars/breadcrumb/setings.vue b/frontend/admin/src/layout/navBars/breadcrumb/setings.vue
index a6656f462..72f49935f 100644
--- a/frontend/admin/src/layout/navBars/breadcrumb/setings.vue
+++ b/frontend/admin/src/layout/navBars/breadcrumb/setings.vue
@@ -176,12 +176,12 @@
-
+
{{ $t('message.layout.fiveTitle') }}
@@ -243,7 +243,7 @@ import { ref, computed, nextTick, onMounted } from 'vue';
import ClipboardJS from 'clipboard';
import { ElMessage } from 'element-plus';
import { Local } from '@/utils/storage.js';
-import { useChangeColor } from '@/utils/theme.js';
+import { filterThemeCssText } from '@/utils/theme.js';
import config from '../../../../package.json';
import { themeList } from './theme';
import bus from '@/utils/bus';
@@ -279,16 +279,9 @@ function onLayoutMobileResize(res) {
// 全局主题
function onColorPickerChange() {
- // if (!getThemeConfig.value.primary) return;
- // 颜色加深
- // document.documentElement.style.setProperty('--prev-color-primary', getThemeConfig.value.primary);
- // 颜色变浅
- for (let i = 1; i <= 9; i++) {
- document.documentElement.style.setProperty(
- `--prev-color-primary-light-${i}`,
- `${useChangeColor().getLightColor(getThemeConfig.value.primary, i / 10)}`,
- );
- }
+ // 主色浅色阶不再写行内样式:app.scss 的 color-mix 表达式引用 --prev-color-primary,
+ // 换肤只改主色即可全档自动重算;此前行内写死向白混色,会压过 dark.scss 的深色档,
+ // 导致深色模式下表头/选中行/标签浅底仍是刺眼浅蓝
setLocalThemeConfig();
}
@@ -455,8 +448,14 @@ function onMenuBgColorChange() {
// 深色模式
function onAddDarkChange() {
const body = document.documentElement;
- if (getThemeConfig.value.isIsDark) body.setAttribute('data-theme', 'dark');
+ const isDark = getThemeConfig.value.isIsDark;
+ if (isDark) body.setAttribute('data-theme', 'dark');
else body.setAttribute('data-theme', '');
+ // Element Plus 官方深色变量表挂在 html.dark 上(main.js 引入的 dark/css-vars.css),同步切换
+ body.classList.toggle('dark', isDark);
+ // vxe-table / vxe-pc-ui 自带深色主题挂 data-vxe-ui-theme 属性(树形表格等 vxe 组件),同步切换
+ if (isDark) body.setAttribute('data-vxe-ui-theme', 'dark');
+ else body.removeAttribute('data-vxe-ui-theme');
setLocalThemeConfig();
}
@@ -485,7 +484,8 @@ function setLocalThemeConfig() {
// 存储布局配置全局主题样式(html根标签)
function setLocalThemeConfigStyle() {
- Local.set('themeConfigStyle', document.documentElement.style.cssText);
+ // 过滤主色浅/深阶:由样式表 color-mix 动态计算,行内持久化会压过深色暗色档
+ Local.set('themeConfigStyle', filterThemeCssText(document.documentElement.style.cssText));
}
// 布局配置弹窗打开
diff --git a/frontend/admin/src/layout/navBars/breadcrumb/theme.js b/frontend/admin/src/layout/navBars/breadcrumb/theme.js
index e60d7df34..03405b8aa 100644
--- a/frontend/admin/src/layout/navBars/breadcrumb/theme.js
+++ b/frontend/admin/src/layout/navBars/breadcrumb/theme.js
@@ -11,7 +11,6 @@ export const themeList = {
'--prev-bg-columnsMenuBarColor': '#fff',
'--prev-MenuActiveColor': '#0256FF',
'--prev-tag-active-color': '#0256FF',
- '--prev-color-primary-light-9': '#e5eeff',
'--prev-bg-columnsMenuActiveColor': '#fff',
},
'theme-2': {
@@ -28,7 +27,6 @@ export const themeList = {
'--prev-MenuActiveColor': '#0256FF',
'--prev-bg-columnsMenuActiveBgColor': '#0256FF',
'--prev-tag-active-color': '#0256FF',
- '--prev-color-primary-light-9': '#e5eeff',
},
'theme-3': {
'--prev-bg-menuBar': '#282c34',
@@ -42,9 +40,7 @@ export const themeList = {
'--prev-bg-columnsMenuBarColor': '#fff',
'--prev-bg-columnsMenuActiveColor': '#fff',
'--prev-MenuActiveColor': '#41b584',
- '--prev-color-primary-light-9': '#ecf8f3',
'--prev-tag-active-color': '#41b584',
- '--prev-color-primary-light-9': '#ecf8f3',
},
'theme-4': {
'--prev-bg-menuBar': '#ffffff',
@@ -60,7 +56,6 @@ export const themeList = {
'--prev-MenuActiveColor': '#41b584',
'--prev-tag-active-color': '#41b584',
- '--prev-color-primary-light-9': '#ecf8f3',
},
'theme-5': {
'--prev-bg-menuBar': '#282c34',
@@ -74,7 +69,6 @@ export const themeList = {
'--prev-bg-columnsMenuBarColor': '#fff',
'--prev-bg-columnsMenuActiveColor': '#fff',
'--prev-MenuActiveColor': '#6954f0',
- '--prev-color-primary-light-9': '#f0eefe',
'--prev-tag-active-color': '#6954f0',
},
'theme-6': {
@@ -89,7 +83,6 @@ export const themeList = {
'--prev-bg-columnsMenuBarColor': '#515a6e',
'--prev-bg-columnsMenuActiveColor': '#fff',
'--prev-MenuActiveColor': '#6954f0',
- '--prev-color-primary-light-9': '#f0eefe',
'--prev-tag-active-color': '#6954f0',
},
'theme-7': {
@@ -117,7 +110,6 @@ export const themeList = {
'--prev-bg-columnsMenuBar': '#fff',
'--prev-bg-columnsMenuBarColor': '#515a6e',
'--prev-bg-columnsMenuActiveColor': '#fff',
- '--prev-color-primary-light-9': '#feedeb',
'--prev-MenuActiveColor': '#f34d37',
'--prev-tag-active-color': '#f34d37',
},
@@ -134,6 +126,5 @@ export const themeList = {
'--prev-bg-columnsMenuActiveColor': '#fff',
'--prev-tag-active-color': '#0256FF',
'--prev-MenuActiveColor': '#0256FF',
- '--prev-color-primary-light-9': '#e5eeff',
},
};
diff --git a/frontend/admin/src/main.js b/frontend/admin/src/main.js
index 8fe548fca..904600c74 100644
--- a/frontend/admin/src/main.js
+++ b/frontend/admin/src/main.js
@@ -27,6 +27,9 @@ import timeOptions from '@/libs/timeOptions';
import ElementPlus, { ElMessage } from 'element-plus';
import zhCn from 'element-plus/es/locale/lang/zh-cn';
import 'element-plus/dist/index.css';
+// Element Plus 官方深色变量表(挂 html.dark,由 setings.vue 的 onAddDarkChange 切换);
+// 须在 @/theme/index.scss 之前引入,保证同特异性时项目主题层(dark.scss 重桥接)后加载胜出
+import 'element-plus/theme-chalk/dark/css-vars.css';
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
// element-ui 字体图标类名兼容层(CSS mask 方案,自动生成)
import './styles/el-icon-compat.css';
diff --git a/frontend/admin/src/theme/dark.scss b/frontend/admin/src/theme/dark.scss
index 1cb102046..392bb4d63 100644
--- a/frontend/admin/src/theme/dark.scss
+++ b/frontend/admin/src/theme/dark.scss
@@ -7,6 +7,8 @@
--prev-bg-topBarColor: #dadada !important;
--prev-bg-columnsMenuBar: #191919 !important;
--prev-bg-columnsMenuBarColor: #dadada !important;
+ /* 换肤(setLocalTheme)会按主题行内写入浅色 hover 底(#e5eeff/#ecf8f3 等),深色下需压制 */
+ --prev-bg-menu-hover-ba-color: rgba(255, 255, 255, 0.1) !important;
--prev-bg-main-color: #1f1f1f !important;
--prev-bg-color: rgba(0, 0, 0, 0.3) !important;
--prev-bg-white: #191919 !important;
@@ -24,6 +26,20 @@
--prev-border-color-lighter: #333333 !important;
--prev-border-color-extra-light: #333333 !important;
+ /* 主色浅色阶暗色档:与 app.scss 浅色档同算法(color-mix),混色底由白色换成暗底
+ #141414(Element Plus 官方深色变量同款底色)。表头(app.scss 的
+ --el-table-header-bg-color)、选中行、标签浅底等引用方自动跟随;
+ 行内主色换肤时 color-mix 同样自动重算,无需 JS 参与 */
+ --prev-color-primary-light-1: color-mix(in srgb, var(--prev-color-primary) 90%, #141414);
+ --prev-color-primary-light-2: color-mix(in srgb, var(--prev-color-primary) 80%, #141414);
+ --prev-color-primary-light-3: color-mix(in srgb, var(--prev-color-primary) 70%, #141414);
+ --prev-color-primary-light-4: color-mix(in srgb, var(--prev-color-primary) 60%, #141414);
+ --prev-color-primary-light-5: color-mix(in srgb, var(--prev-color-primary) 50%, #141414);
+ --prev-color-primary-light-6: color-mix(in srgb, var(--prev-color-primary) 40%, #141414);
+ --prev-color-primary-light-7: color-mix(in srgb, var(--prev-color-primary) 30%, #141414);
+ --prev-color-primary-light-8: color-mix(in srgb, var(--prev-color-primary) 20%, #141414);
+ --prev-color-primary-light-9: color-mix(in srgb, var(--prev-color-primary) 10%, #141414);
+
// menu
.layout-aside {
border-right: 1px solid var(--prev-border-color-lighter) !important;
@@ -112,4 +128,63 @@
.el-calendar {
border: 1px solid var(--prev-border-color-lighter);
}
+
+ // 底部固定提交卡:浅色为白色毛玻璃,深色换黑色毛玻璃(style.scss 同规则带 !important,
+ // 此处块内选择器特异性更高,可覆盖)
+ .fixed-card {
+ background-color: rgba(25, 25, 25, 0.6) !important;
+ }
+
+ // AI 对话工作台:会话面板底改不透明层次色。
+ // 浅色档 --prev-bg-color 是实色,深色档是 rgba(0,0,0,0.3) 半透明,
+ // 面板用半透明底会随下垫内容/页面底色变化产生观感分层
+ .conversation-panel {
+ background-color: #202020;
+ }
+
+ // form-create 上传占位框(elm-frame/elm-upload 组件默认 #fff 底 + #c0ccda 边)
+ ._fc-frame ._fc-upload-btn,
+ ._fc-frame ._fc-files,
+ ._fc-upload ._fc-upload-btn,
+ ._fc-upload ._fc-files {
+ background-color: var(--prev-bg-white) !important;
+ border-color: var(--prev-border-color-base) !important;
+ }
+}
+
+/* Element Plus 官方深色变量重桥接
+------------------------------- */
+/* main.js 引入的官方 dark/css-vars.css 挂在 html.dark(特异性 0,1,1)上,会:
+ 1. 把主色系接管为 EP 默认蓝 #409eff,与项目主色(默认 #0256FF)漂移;
+ 2. 把 --el-bg-color 系接管为 #141414 体系,与本项目 #191919 深色体系并存两种黑。
+ 此处以同特异性 html[data-theme='dark'] 重桥接回 --prev-* 体系(本文件后于官方
+ 文件加载,同特异性按源顺序胜出);未列出的官方深色值(语义色 light 阶、遮罩、
+ 阴影、fill-color/-lighter 等)保持官方值兜底 */
+html[data-theme='dark'] {
+ /* 背景体系:统一回 #191919(卡片/弹层/表格行底/输入框内底) */
+ --el-bg-color: var(--prev-bg-white);
+ --el-bg-color-overlay: var(--prev-bg-white);
+ --el-fill-color-blank: var(--prev-bg-white);
+ --el-fill-color-light: var(--prev-color-hover);
+
+ /* 文本体系 */
+ --el-text-color-primary: var(--prev-color-text-primary);
+ --el-text-color-regular: var(--prev-color-text-regular);
+ --el-text-color-secondary: var(--prev-color-text-secondary);
+ --el-text-color-placeholder: var(--prev-color-text-placeholder);
+
+ /* 边框体系 */
+ --el-border-color: var(--prev-border-color-base);
+ --el-border-color-light: var(--prev-border-color-light);
+ --el-border-color-lighter: var(--prev-border-color-lighter);
+ --el-border-color-extra-light: var(--prev-border-color-extra-light);
+
+ /* 主色系:浅色阶向暗底 #141414 混色(同 EP 官方深色算法),保持项目主色不漂移 */
+ --el-color-primary: var(--prev-color-primary);
+ --el-color-primary-light-3: color-mix(in srgb, var(--prev-color-primary) 70%, #141414);
+ --el-color-primary-light-5: color-mix(in srgb, var(--prev-color-primary) 50%, #141414);
+ --el-color-primary-light-7: color-mix(in srgb, var(--prev-color-primary) 30%, #141414);
+ --el-color-primary-light-8: color-mix(in srgb, var(--prev-color-primary) 20%, #141414);
+ --el-color-primary-light-9: color-mix(in srgb, var(--prev-color-primary) 10%, #141414);
+ --el-color-primary-dark-2: color-mix(in srgb, var(--prev-color-primary) 80%, #000000);
}
diff --git a/frontend/admin/src/utils/theme.js b/frontend/admin/src/utils/theme.js
index 36343ba4d..5f7ec9447 100644
--- a/frontend/admin/src/utils/theme.js
+++ b/frontend/admin/src/utils/theme.js
@@ -1,5 +1,27 @@
import { ElMessage } from 'element-plus';
+/**
+ * 过滤主题行内样式中的主色浅/深阶变量
+ *
+ * 主色浅色阶/深色阶由样式表 color-mix 表达式动态计算(亮色档在 theme/app.scss,
+ * 暗色档在 theme/dark.scss),引用 --prev-color-primary,换肤时自动重算。
+ * 这类变量不允许持久化为行内样式:行内样式优先级最高,会压过深色模式的暗色档,
+ * 导致深色下表头/选中行/标签浅底仍是刺眼浅色(2026-09 深色模式适配遗留问题)。
+ * @param {string} cssText document.documentElement.style.cssText
+ * @returns {string} 过滤后的 cssText
+ */
+export function filterThemeCssText(cssText) {
+ if (!cssText) return '';
+ const dynamicVarRe = /^--(prev|el)-color-primary-(light|dark)-\d+$/;
+ return cssText
+ .split(';')
+ .filter((item) => {
+ const name = (item.split(':')[0] || '').trim();
+ return name && !dynamicVarRe.test(name);
+ })
+ .join(';');
+}
+
/**
* 颜色转换函数
* @method hexToRgb hex 颜色转 rgb 颜色