From 03a9c034015c0db7f3262b0e47f672e67ff5ed07 Mon Sep 17 00:00:00 2001 From: "Ray.Hao" <1490493387@qq.com> Date: Thu, 18 Jun 2026 23:39:31 +0800 Subject: [PATCH] =?UTF-8?q?refactor(layout):=20=E4=BC=98=E5=8C=96=E5=90=8E?= =?UTF-8?q?=E5=8F=B0=E5=B8=83=E5=B1=80=E6=A0=B7=E5=BC=8F=E4=B8=8E=E4=B8=BB?= =?UTF-8?q?=E9=A2=98=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 优化顶部工具栏、通知入口和页签操作按钮的图标颜色继承 - 调整混合布局菜单激活态与暗黑模式下的视觉表现 - 重构设置面板分组与底部操作区,精简无效配置文案 - 统一列表页公共布局样式,优化表格和页面容器边界 - 优化控制台卡片、图表和暗黑模式背景表现 - 移除布局中重复的页签高度覆盖和无用 mixin --- src/components/NoticeDropdown/index.vue | 11 +- src/lang/package/en.json | 3 + src/lang/package/zh-cn.json | 2 + src/layouts/DoubleLayout.vue | 9 - src/layouts/LeftLayout.vue | 7 - src/layouts/MixLayout.vue | 63 ++++-- src/layouts/TopLayout.vue | 8 +- src/layouts/components/LayoutSettings.vue | 264 +++++++++++++--------- src/layouts/components/LayoutTagsView.vue | 99 ++++---- src/layouts/components/LayoutToolbar.vue | 120 +++++----- src/styles/element-plus-overrides.scss | 21 +- src/styles/mixins.scss | 4 - src/styles/page.scss | 21 +- src/styles/theme.scss | 2 +- src/views/dashboard/index.vue | 3 +- 15 files changed, 357 insertions(+), 280 deletions(-) diff --git a/src/components/NoticeDropdown/index.vue b/src/components/NoticeDropdown/index.vue index fef3c117..ae87b6d9 100644 --- a/src/components/NoticeDropdown/index.vue +++ b/src/components/NoticeDropdown/index.vue @@ -122,6 +122,7 @@ function handleVisibleChange(visible: boolean) { justify-content: center; width: 100%; height: 100%; + color: inherit; } &__trigger { @@ -130,6 +131,7 @@ function handleVisibleChange(visible: boolean) { justify-content: center; width: 100%; height: 100%; + color: inherit; } &__icon { @@ -139,17 +141,20 @@ function handleVisibleChange(visible: boolean) { justify-content: center; width: 28px; height: 28px; + color: currentColor; border-radius: 6px; } &__bell { - color: var(--el-text-color-regular); + --color: currentColor; + + color: currentColor; } &__pulse { position: absolute; - top: 4px; - right: 5px; + top: 3px; + right: 4px; width: 6px; height: 6px; background: var(--el-color-danger); diff --git a/src/lang/package/en.json b/src/lang/package/en.json index 3622a607..835f9467 100644 --- a/src/lang/package/en.json +++ b/src/lang/package/en.json @@ -67,6 +67,7 @@ "theme": "Theme", "interface": "Interface", "navigation": "Navigation", + "assist": "Assist", "themePalette": "Color System", "customColors": "Custom Colors", "customPalette": "Custom", @@ -102,6 +103,8 @@ "sidebarColorScheme": "Sidebar Color Scheme", "showWatermark": "Show Watermark", "pageSwitchingAnimation": "Page Switching Animation", + "grayMode": "Gray Mode", + "colorWeak": "Color Weak", "none": "None", "fade": "Fade", "fade-slide": "Fade Slide", diff --git a/src/lang/package/zh-cn.json b/src/lang/package/zh-cn.json index ab4c3703..6b978574 100644 --- a/src/lang/package/zh-cn.json +++ b/src/lang/package/zh-cn.json @@ -104,6 +104,8 @@ "showAppLogo": "显示Logo", "showWatermark": "显示水印", "pageSwitchingAnimation": "页面切换动画", + "grayMode": "灰色模式", + "colorWeak": "色弱模式", "none": "无动画", "fade": "淡入淡出", "fade-slide": "平滑切换", diff --git a/src/layouts/DoubleLayout.vue b/src/layouts/DoubleLayout.vue index 60961310..3c21cc24 100644 --- a/src/layouts/DoubleLayout.vue +++ b/src/layouts/DoubleLayout.vue @@ -51,7 +51,6 @@
diff --git a/src/layouts/MixLayout.vue b/src/layouts/MixLayout.vue index b20d9ec0..fe3aca3f 100644 --- a/src/layouts/MixLayout.vue +++ b/src/layouts/MixLayout.vue @@ -66,7 +66,7 @@ -
+
@@ -171,27 +171,43 @@ const useMenuColors = computed( .el-menu-item { position: relative; height: 100%; - padding: 0 12px; + padding: 0 14px; line-height: $navbar-height; - border-bottom: none; + border-bottom: none !important; border-radius: 0; transition: color 0.16s ease, - background-color 0.16s ease, - border-color 0.16s ease; + opacity 0.16s ease; + + &::after { + position: absolute; + right: 12px; + bottom: 0; + left: 12px; + height: 2px; + content: ""; + background: var(--el-color-primary); + border-radius: 999px 999px 0 0; + opacity: 0; + transform: scaleX(0.4); + transition: + opacity 0.16s ease, + transform 0.16s ease; + } &:hover { - background-color: var(--menu-hover) !important; + color: var(--el-color-primary) !important; + background-color: transparent !important; } &.is-active { color: var(--el-color-primary) !important; - background-color: color-mix( - in srgb, - var(--el-color-primary) 10%, - var(--el-bg-color-overlay) - ) !important; - border-bottom: 2px solid var(--el-color-primary); + background-color: transparent !important; + } + + &.is-active::after { + opacity: 1; + transform: scaleX(1); } } } @@ -289,23 +305,20 @@ const useMenuColors = computed( } } -:deep(.hasTagsView) { - .app-main { - @include app-main-height-with-tags; - } -} - :global(html.dark), :global(html.sidebar-color-blue) { .layout__header-menu { :deep(.el-menu--horizontal) { - .el-menu-item.is-active { - color: var(--menu-active-text) !important; - background-color: color-mix( - in srgb, - var(--el-color-primary) 18%, - var(--menu-background) - ) !important; + .el-menu-item { + &:hover { + color: color-mix(in srgb, var(--el-color-primary) 24%, var(--el-color-white)) !important; + background-color: transparent !important; + } + + &.is-active { + color: color-mix(in srgb, var(--el-color-primary) 38%, var(--el-color-white)) !important; + background-color: transparent !important; + } } } } diff --git a/src/layouts/TopLayout.vue b/src/layouts/TopLayout.vue index 7d236888..38122b3e 100644 --- a/src/layouts/TopLayout.vue +++ b/src/layouts/TopLayout.vue @@ -16,7 +16,7 @@
-
+
@@ -149,10 +149,4 @@ const isLogoCollapsed = computed(() => width.value < 768); overflow-y: auto; } } - -.hasTagsView { - :deep(.app-main) { - @include app-main-height-with-tags; - } -} diff --git a/src/layouts/components/LayoutSettings.vue b/src/layouts/components/LayoutSettings.vue index 52ec34f4..c0349fa2 100644 --- a/src/layouts/components/LayoutSettings.vue +++ b/src/layouts/components/LayoutSettings.vue @@ -8,10 +8,10 @@ >
- {{ t("settings.theme") }} +
{{ t("settings.theme") }}
-
- +
+ {{ t("login.light") }} @@ -24,9 +24,9 @@
-
-
- {{ t("settings.themePalette") }} +
+
+ {{ t("settings.themePalette") }}
@@ -331,19 +329,23 @@ const drawerVisible = computed({ set: (value) => (settingsStore.settingsVisible = value), }); -const getPaletteColors = (colors: ThemeColorMap) => colorOptions.map((item) => colors[item.name]); +function getPaletteColors(colors: ThemeColorMap) { + return colorOptions.map((item) => colors[item.name]); +} -const getPaletteName = (palette: ThemePalettePreset) => { +function getPaletteName(palette: ThemePalettePreset) { const key = paletteI18nKeys[palette.id]; return key ? t(`settings.themePalettes.${key}.name`) : palette.name; -}; +} -const getPaletteDescription = (palette: ThemePalettePreset) => { +function getPaletteDescription(palette: ThemePalettePreset) { const key = paletteI18nKeys[palette.id]; return key ? t(`settings.themePalettes.${key}.description`) : palette.description; -}; +} -const getColorLabel = (name: ThemeColorName) => t(`settings.themeColorNames.${name}`); +function getColorLabel(name: ThemeColorName) { + return t(`settings.themeColorNames.${name}`); +} const activePaletteName = computed(() => settingsStore.activeThemePalette @@ -351,32 +353,47 @@ const activePaletteName = computed(() => : t("settings.customPalette") ); -const toggleCustomColors = () => { +/** + * 展开或收起自定义颜色 + */ +function toggleCustomColors(): void { isCustomColorsOpen.value = !isCustomColorsOpen.value; -}; +} -const handleThemeColorChange = (name: ThemeColorName, color: string | null) => { +/** + * 更新单个主题色 + */ +function handleThemeColorChange(name: ThemeColorName, color: string | null): void { if (!color) return; settingsStore.updateThemeColor(name, color); -}; +} -const changeSidebarColor = (val: string | number | boolean | undefined) => { - if (val !== SidebarColor.CLASSIC_BLUE && val !== SidebarColor.MINIMAL_WHITE) return; +/** + * 切换侧边栏配色 + */ +function setSidebarColor(value: string | number | boolean | undefined): void { + if (value !== SidebarColor.CLASSIC_BLUE && value !== SidebarColor.MINIMAL_WHITE) return; - settingsStore.sidebarColorScheme = val; -}; + settingsStore.sidebarColorScheme = value; +} -const handleLayoutChange = (layout: LayoutMode) => { +/** + * 切换导航布局 + */ +function handleLayoutChange(layout: LayoutMode): void { if (settingsStore.layout === layout) return; settingsStore.layout = layout; -}; +} -const handleCopySettings = async () => { +/** + * 复制当前 settings 默认配置片段 + */ +async function copyCurrentSettings(): Promise { try { copyLoading.value = true; - const configCode = generateSettingsCode(); + const configCode = buildDefaultsCode(); await navigator.clipboard.writeText(configCode); @@ -389,26 +406,36 @@ const handleCopySettings = async () => { } finally { copyLoading.value = false; } -}; - -const handleResetSettings = async () => { - resetLoading.value = true; +} +/** + * 恢复所有设置为默认值 + */ +async function resetSettingsToDefault(): Promise { try { + await ElMessageBox.confirm(t("settings.confirmReset"), t("settings.resetConfig"), { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning", + }); + + resetLoading.value = true; settingsStore.resetSettings(); sidebarColor.value = settingsStore.sidebarColorScheme; ElMessage.success(t("settings.resetSuccess")); } catch { - ElMessage.error("重置配置失败"); + // 用户取消时不提示 } finally { resetLoading.value = false; } -}; +} -// 这里只生成 defaults,避免复制出来的代码和 src/settings.ts 的真实结构对不上。 -const generateSettingsCode = (): string => { +/** + * 生成 src/settings.ts 中 defaults 的配置片段 + */ +function buildDefaultsCode(): string { const themeColorsCode = JSON.stringify(settingsStore.themeColors, null, 4) .replace(/"([^"]+)":/g, "$1:") .replace(/^/gm, " "); @@ -445,11 +472,11 @@ const generateSettingsCode = (): string => { showSettings: ${settings.showSettings}, watermarkContent: ${settings.watermarkContent}, } as const;`; -}; +} -const handleCloseDrawer = () => { +function handleCloseDrawer(): void { settingsStore.settingsVisible = false; -}; +}