From dd783136229da9e291b518df93227111f4216ad0 Mon Sep 17 00:00:00 2001
From: xiaoming <1923740402@qq.com>
Date: Sun, 14 Jan 2024 23:21:43 +0800
Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=95=B4=E4=BD=93?=
=?UTF-8?q?=E9=A3=8E=E6=A0=BC=E8=87=AA=E9=80=82=E5=BA=94=E6=93=8D=E4=BD=9C?=
=?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=B5=85=E8=89=B2=E3=80=81=E6=B7=B1=E8=89=B2?=
=?UTF-8?q?=E3=80=81=E8=87=AA=E5=8A=A8=E4=B8=BB=E9=A2=98=E5=8A=9F=E8=83=BD?=
=?UTF-8?q?=EF=BC=8C=E8=AE=A9=E5=B9=B3=E5=8F=B0=E5=85=85=E6=BB=A1=E7=8E=B0?=
=?UTF-8?q?=E4=BB=A3=E6=B0=94=E6=81=AF=20(#869)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: 添加整体风格自适应操作系统浅色、深色、自动主题功能,让平台更加现代化
* chore: update
---
README.md | 2 +-
public/logo.svg | 2 +-
public/platform-config.json | 1 +
src/assets/login/avatar.svg | 2 +-
src/assets/svg/system.svg | 1 +
.../src/assets/iconfont/iconfont.svg | 2 +-
src/components/ReSegmented/src/index.tsx | 8 ++-
src/components/ReSegmented/src/type.ts | 2 +
src/layout/components/setting/index.vue | 72 ++++++++++++++++---
src/layout/hooks/useDataThemeChange.ts | 10 ++-
src/layout/hooks/useLayout.ts | 3 +-
src/layout/index.vue | 5 +-
src/style/dark.scss | 4 +-
src/style/element-plus.scss | 4 +-
src/utils/responsive.ts | 3 +-
src/views/components/message/index.vue | 2 +-
src/views/login/index.vue | 4 +-
types/global.d.ts | 3 +
18 files changed, 100 insertions(+), 30 deletions(-)
create mode 100644 src/assets/svg/system.svg
diff --git a/README.md b/README.md
index a23525165..ef41363cb 100644
--- a/README.md
+++ b/README.md
@@ -47,7 +47,7 @@
-暗黑模式
+暗色风格
diff --git a/public/logo.svg b/public/logo.svg
index a44a847b9..a63d2b1ab 100644
--- a/public/logo.svg
+++ b/public/logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/platform-config.json b/public/platform-config.json
index 454941ff0..fd89ee1c0 100644
--- a/public/platform-config.json
+++ b/public/platform-config.json
@@ -9,6 +9,7 @@
"Layout": "vertical",
"Theme": "light",
"DarkMode": false,
+ "OverallStyle": "light",
"Grey": false,
"Weak": false,
"HideTabs": false,
diff --git a/src/assets/login/avatar.svg b/src/assets/login/avatar.svg
index a44a847b9..a63d2b1ab 100644
--- a/src/assets/login/avatar.svg
+++ b/src/assets/login/avatar.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/assets/svg/system.svg b/src/assets/svg/system.svg
new file mode 100644
index 000000000..9ad39a56e
--- /dev/null
+++ b/src/assets/svg/system.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/ReFlowChart/src/assets/iconfont/iconfont.svg b/src/components/ReFlowChart/src/assets/iconfont/iconfont.svg
index 052ed338d..358bd5186 100644
--- a/src/components/ReFlowChart/src/assets/iconfont/iconfont.svg
+++ b/src/components/ReFlowChart/src/assets/iconfont/iconfont.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/components/ReSegmented/src/index.tsx b/src/components/ReSegmented/src/index.tsx
index 41c08af18..d8d536186 100644
--- a/src/components/ReSegmented/src/index.tsx
+++ b/src/components/ReSegmented/src/index.tsx
@@ -115,7 +115,13 @@ export default defineComponent({
onClick={event => handleChange({ option, index }, event)}
>
-
+
{option.icon && !isFunction(option.label) ? (
{
};
});
-/** 当网页为暗黑模式时不显示亮白色切换选项 */
+/** 当网页整体为暗色风格时不显示亮白色主题配色切换选项 */
const showThemeColors = computed(() => {
return themeColor => {
return themeColor === "light" && isDark.value ? false : true;
@@ -162,13 +165,24 @@ const getThemeColor = computed(() => {
const themeOptions = computed>(() => {
return [
{
- label: "亮色",
+ label: "浅色",
icon: dayIcon,
+ theme: "light",
+ tip: "清新启航,点亮舒适的工作界面",
iconAttrs: { fill: isDark.value ? "#fff" : "#000" }
},
{
- label: "暗色",
+ label: "深色",
icon: darkIcon,
+ theme: "dark",
+ tip: "月光序曲,沉醉于夜的静谧雅致",
+ iconAttrs: { fill: isDark.value ? "#fff" : "#000" }
+ },
+ {
+ label: "自动",
+ icon: systemIcon,
+ theme: "system",
+ tip: "同步时光,界面随晨昏自然呼应",
iconAttrs: { fill: isDark.value ? "#fff" : "#000" }
}
];
@@ -177,10 +191,12 @@ const themeOptions = computed>(() => {
const markOptions: Array = [
{
label: "灵动",
+ tip: "灵动标签,添趣生辉",
value: "smart"
},
{
label: "卡片",
+ tip: "卡片标签,高效浏览",
value: "card"
}
];
@@ -195,7 +211,8 @@ function setLayoutModel(layout: string) {
darkMode: $storage.layout?.darkMode,
sidebarStatus: $storage.layout?.sidebarStatus,
epThemeColor: $storage.layout?.epThemeColor,
- themeColor: layoutTheme.value.theme
+ themeColor: $storage.layout?.themeColor,
+ overallStyle: $storage.layout?.overallStyle
};
useAppStoreHook().setLayout(layout);
}
@@ -220,9 +237,34 @@ watch($storage, ({ layout }) => {
}
});
+const mediaQueryList = window.matchMedia("(prefers-color-scheme: dark)");
+
+/** 根据操作系统主题设置平台整体风格 */
+function updateTheme() {
+ if (overallStyle.value !== "system") return;
+ if (mediaQueryList.matches) {
+ dataTheme.value = true;
+ } else {
+ dataTheme.value = false;
+ }
+ dataThemeChange(overallStyle.value);
+}
+
+function removeMatchMedia() {
+ mediaQueryList.removeEventListener("change", updateTheme);
+}
+
+/** 监听操作系统主题改变 */
+function watchSystemThemeChange() {
+ updateTheme();
+ removeMatchMedia();
+ mediaQueryList.addEventListener("change", updateTheme);
+}
+
onBeforeMount(() => {
/* 初始化项目配置 */
nextTick(() => {
+ watchSystemThemeChange();
settings.greyVal &&
document.querySelector("html")?.setAttribute("class", "html-grey");
settings.weakVal &&
@@ -231,6 +273,8 @@ onBeforeMount(() => {
settings.hideFooter && hideFooterChange();
});
});
+
+onUnmounted(() => removeMatchMedia);
@@ -238,12 +282,17 @@ onBeforeMount(() => {
整体风格
{
+ theme.index === 1 && theme.index !== 2
+ ? (dataTheme = true)
+ : (dataTheme = false);
+ overallStyle = theme.option.theme;
+ dataThemeChange(theme.option.theme);
+ theme.index === 2 && watchSystemThemeChange();
}
"
/>
@@ -272,7 +321,7 @@ onBeforeMount(() => {
{
v-if="device !== 'mobile'"
ref="horizontalRef"
v-tippy="{
- content: '顶部菜单',
+ content: '顶部菜单,简洁概览',
zIndex: 41000
}"
:class="layoutTheme.layout === 'horizontal' ? 'is-select' : ''"
@@ -298,7 +347,7 @@ onBeforeMount(() => {
v-if="device !== 'mobile'"
ref="mixRef"
v-tippy="{
- content: '混合菜单',
+ content: '混合菜单,灵活多变',
zIndex: 41000
}"
:class="layoutTheme.layout === 'mix' ? 'is-select' : ''"
@@ -311,6 +360,7 @@ onBeforeMount(() => {
页签风格
();
const dataTheme = ref($storage?.layout?.darkMode);
+ const overallStyle = ref($storage?.layout?.overallStyle);
const body = document.documentElement as HTMLElement;
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
@@ -64,7 +65,8 @@ export function useDataThemeChange() {
darkMode: dataTheme.value,
sidebarStatus: $storage.layout?.sidebarStatus,
epThemeColor: $storage.layout?.epThemeColor,
- themeColor: isClick ? theme : storageThemeColor
+ themeColor: isClick ? theme : storageThemeColor,
+ overallStyle: overallStyle.value
};
if (theme === "default" || theme === "light") {
@@ -94,8 +96,9 @@ export function useDataThemeChange() {
}
};
- /** 亮色、暗色整体风格切换 */
- function dataThemeChange() {
+ /** 浅色、深色整体风格切换 */
+ function dataThemeChange(overall?: string) {
+ overallStyle.value = overall;
if (useEpThemeStoreHook().epTheme === "light" && dataTheme.value) {
setLayoutThemeColor("default", false);
} else {
@@ -130,6 +133,7 @@ export function useDataThemeChange() {
return {
body,
dataTheme,
+ overallStyle,
layoutTheme,
themeColors,
onReset,
diff --git a/src/layout/hooks/useLayout.ts b/src/layout/hooks/useLayout.ts
index 5e4fb32e3..8e6981ce7 100644
--- a/src/layout/hooks/useLayout.ts
+++ b/src/layout/hooks/useLayout.ts
@@ -28,7 +28,8 @@ export function useLayout() {
darkMode: $config?.DarkMode ?? false,
sidebarStatus: $config?.SidebarStatus ?? true,
epThemeColor: $config?.EpThemeColor ?? "#409EFF",
- themeColor: $config?.Theme ?? "light"
+ themeColor: $config?.Theme ?? "light",
+ overallStyle: $config?.OverallStyle ?? "light"
};
}
/** 灰色模式、色弱模式、隐藏标签页 */
diff --git a/src/layout/index.vue b/src/layout/index.vue
index 727168b1a..88aa60b95 100644
--- a/src/layout/index.vue
+++ b/src/layout/index.vue
@@ -73,7 +73,8 @@ function setTheme(layoutModel: string) {
darkMode: $storage.layout?.darkMode,
sidebarStatus: $storage.layout?.sidebarStatus,
epThemeColor: $storage.layout?.epThemeColor,
- themeColor: $storage.layout?.themeColor
+ themeColor: $storage.layout?.themeColor,
+ overallStyle: $storage.layout?.overallStyle
};
}
@@ -119,7 +120,7 @@ onMounted(() => {
});
onBeforeMount(() => {
- useDataThemeChange().dataThemeChange();
+ useDataThemeChange().dataThemeChange($storage.layout?.overallStyle);
});
const layoutHeader = defineComponent({
diff --git a/src/style/dark.scss b/src/style/dark.scss
index 98ffd8030..8ef6a2e14 100644
--- a/src/style/dark.scss
+++ b/src/style/dark.scss
@@ -1,6 +1,6 @@
@use "element-plus/theme-chalk/src/dark/css-vars.scss" as *;
-/* 暗黑模式适配 */
+/* 整体暗色风格适配 */
html.dark {
$border-style: #303030;
$color-white: #fff;
@@ -126,7 +126,7 @@ html.dark {
}
}
- /* 克隆并自定义 ElMessage 样式,不会影响 ElMessage 原本样式,在 src/utils/message.ts 中调用自定义样式 ElMessage 方法即可,非暗黑模式在 src/style/element-plus.scss 文件进行了适配 */
+ /* 克隆并自定义 ElMessage 样式,不会影响 ElMessage 原本样式,在 src/utils/message.ts 中调用自定义样式 ElMessage 方法即可,整体浅色风格在 src/style/element-plus.scss 文件进行了适配 */
.pure-message {
background-color: rgb(36 37 37) !important;
background-image: initial !important;
diff --git a/src/style/element-plus.scss b/src/style/element-plus.scss
index a55b664aa..be70a2a4e 100644
--- a/src/style/element-plus.scss
+++ b/src/style/element-plus.scss
@@ -116,7 +116,7 @@
}
}
-/* 克隆并自定义 ElMessage 样式,不会影响 ElMessage 原本样式,在 src/utils/message.ts 中调用自定义样式 ElMessage 方法即可,暗黑模式在 src/style/dark.scss 文件进行了适配 */
+/* 克隆并自定义 ElMessage 样式,不会影响 ElMessage 原本样式,在 src/utils/message.ts 中调用自定义样式 ElMessage 方法即可,整体暗色风格在 src/style/dark.scss 文件进行了适配 */
.pure-message {
padding: 10px 13px !important;
background: #fff !important;
@@ -189,7 +189,7 @@
}
}
-/* 仿 el-scrollbar 滚动条样式,支持大多数浏览器,如Chrome、Edge、Firefox、Safari等。暗黑模式在 src/style/dark.scss 文件进行了适配 */
+/* 仿 el-scrollbar 滚动条样式,支持大多数浏览器,如Chrome、Edge、Firefox、Safari等。整体暗色风格在 src/style/dark.scss 文件进行了适配 */
.pure-scrollbar {
/* Firefox */
scrollbar-width: thin; /* 可选值为 'auto', 'thin', 'none' */
diff --git a/src/utils/responsive.ts b/src/utils/responsive.ts
index b5e77986e..e216bc300 100644
--- a/src/utils/responsive.ts
+++ b/src/utils/responsive.ts
@@ -19,7 +19,8 @@ export const injectResponsiveStorage = (app: App, config: PlatformConfigs) => {
darkMode: config.DarkMode ?? false,
sidebarStatus: config.SidebarStatus ?? true,
epThemeColor: config.EpThemeColor ?? "#409EFF",
- themeColor: config.Theme ?? "light" // 主题色(对应项目配置中的主题色,与theme不同的是它不会受到亮色、暗色整体风格切换的影响,只会在手动点击主题色时改变)
+ themeColor: config.Theme ?? "light", // 主题色(对应项目配置中的主题色,与theme不同的是它不会受到浅色、深色整体风格切换的影响,只会在手动点击主题色时改变)
+ overallStyle: config.OverallStyle ?? "light" // 整体风格(浅色:light、深色:dark、自动:system)
},
// 项目配置-界面显示
configure: Storage.getData("configure", nameSpace) ?? {
diff --git a/src/views/components/message/index.vue b/src/views/components/message/index.vue
index 58f6c364b..6631d11de 100644
--- a/src/views/components/message/index.vue
+++ b/src/views/components/message/index.vue
@@ -117,7 +117,7 @@ defineOptions({
类似 Ant Design 风格的消息提示,点击弹出提示信息(基于 ElMessage
样式改版,不会影响 ElMessage
- 原本样式,使用和打包大小成本极低并适配暗黑模式)
+ 原本样式,使用和打包大小成本极低并适配整体暗色风格)
diff --git a/src/views/login/index.vue b/src/views/login/index.vue
index e0e721d3e..6fe4bd23a 100644
--- a/src/views/login/index.vue
+++ b/src/views/login/index.vue
@@ -56,8 +56,8 @@ const currentPage = computed(() => {
const { t } = useI18n();
const { initStorage } = useLayout();
initStorage();
-const { dataTheme, dataThemeChange } = useDataThemeChange();
-dataThemeChange();
+const { dataTheme, overallStyle, dataThemeChange } = useDataThemeChange();
+dataThemeChange(overallStyle.value);
const { title, getDropdownItemStyle, getDropdownItemClass } = useNav();
const { locale, translationCh, translationEn } = useTranslationLang();
diff --git a/types/global.d.ts b/types/global.d.ts
index 76e70dcd6..f2d298593 100644
--- a/types/global.d.ts
+++ b/types/global.d.ts
@@ -83,6 +83,7 @@ declare global {
Layout?: string;
Theme?: string;
DarkMode?: boolean;
+ OverallStyle?: string;
Grey?: boolean;
Weak?: boolean;
HideTabs?: boolean;
@@ -127,6 +128,7 @@ declare global {
sidebarStatus?: boolean;
epThemeColor?: string;
themeColor?: string;
+ overallStyle?: string;
showLogo?: boolean;
showModel?: string;
mapConfigure?: {
@@ -154,6 +156,7 @@ declare global {
sidebarStatus?: boolean;
epThemeColor?: string;
themeColor?: string;
+ overallStyle?: string;
};
configure: {
grey?: boolean;