From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目
---
src/layout/components/Setting/src/Setting.vue | 303 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 303 insertions(+), 0 deletions(-)
diff --git a/src/layout/components/Setting/src/Setting.vue b/src/layout/components/Setting/src/Setting.vue
new file mode 100644
index 0000000..92ecf41
--- /dev/null
+++ b/src/layout/components/Setting/src/Setting.vue
@@ -0,0 +1,303 @@
+<script lang="ts" setup>
+import { ElMessage } from 'element-plus'
+import { useClipboard, useCssVar } from '@vueuse/core'
+
+import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
+import { useDesign } from '@/hooks/web/useDesign'
+
+import { setCssVar, trim } from '@/utils'
+import { colorIsDark, hexToRGB, lighten } from '@/utils/color'
+import { useAppStore } from '@/store/modules/app'
+import { ThemeSwitch } from '@/layout/components/ThemeSwitch'
+import ColorRadioPicker from './components/ColorRadioPicker.vue'
+import InterfaceDisplay from './components/InterfaceDisplay.vue'
+import LayoutRadioPicker from './components/LayoutRadioPicker.vue'
+
+defineOptions({ name: 'Setting' })
+
+const { t } = useI18n()
+const appStore = useAppStore()
+
+const { getPrefixCls } = useDesign()
+const prefixCls = getPrefixCls('setting')
+const layout = computed(() => appStore.getLayout)
+const drawer = ref(false)
+
+// 涓婚鑹茬浉鍏�
+const systemTheme = ref(appStore.getTheme.elColorPrimary)
+
+const setSystemTheme = (color: string) => {
+ setCssVar('--el-color-primary', color)
+ appStore.setTheme({ elColorPrimary: color })
+ const leftMenuBgColor = useCssVar('--left-menu-bg-color', document.documentElement)
+ setMenuTheme(trim(unref(leftMenuBgColor)))
+}
+
+// 澶撮儴涓婚鐩稿叧
+const headerTheme = ref(appStore.getTheme.topHeaderBgColor || '')
+
+const setHeaderTheme = (color: string) => {
+ const isDarkColor = colorIsDark(color)
+ const textColor = isDarkColor ? '#fff' : 'inherit'
+ const textHoverColor = isDarkColor ? lighten(color!, 6) : '#f6f6f6'
+ const topToolBorderColor = isDarkColor ? color : '#eee'
+ setCssVar('--top-header-bg-color', color)
+ setCssVar('--top-header-text-color', textColor)
+ setCssVar('--top-header-hover-color', textHoverColor)
+ appStore.setTheme({
+ topHeaderBgColor: color,
+ topHeaderTextColor: textColor,
+ topHeaderHoverColor: textHoverColor,
+ topToolBorderColor
+ })
+ if (unref(layout) === 'top') {
+ setMenuTheme(color)
+ }
+}
+
+// 鑿滃崟涓婚鐩稿叧
+const menuTheme = ref(appStore.getTheme.leftMenuBgColor || '')
+
+const setMenuTheme = (color: string) => {
+ const primaryColor = useCssVar('--el-color-primary', document.documentElement)
+ const isDarkColor = colorIsDark(color)
+ const theme: Recordable = {
+ // 宸︿晶鑿滃崟杈规棰滆壊
+ leftMenuBorderColor: isDarkColor ? 'inherit' : '#eee',
+ // 宸︿晶鑿滃崟鑳屾櫙棰滆壊
+ leftMenuBgColor: color,
+ // 宸︿晶鑿滃崟娴呰壊鑳屾櫙棰滆壊
+ leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
+ // 宸︿晶鑿滃崟閫変腑鑳屾櫙棰滆壊
+ leftMenuBgActiveColor: isDarkColor
+ ? 'var(--el-color-primary)'
+ : hexToRGB(unref(primaryColor), 0.1),
+ // 宸︿晶鑿滃崟鏀惰捣閫変腑鑳屾櫙棰滆壊
+ leftMenuCollapseBgActiveColor: isDarkColor
+ ? 'var(--el-color-primary)'
+ : hexToRGB(unref(primaryColor), 0.1),
+ // 宸︿晶鑿滃崟瀛椾綋棰滆壊
+ leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
+ // 宸︿晶鑿滃崟閫変腑瀛椾綋棰滆壊
+ leftMenuTextActiveColor: isDarkColor ? '#fff' : 'var(--el-color-primary)',
+ // logo瀛椾綋棰滆壊
+ logoTitleTextColor: isDarkColor ? '#fff' : 'inherit',
+ // logo杈规棰滆壊
+ logoBorderColor: isDarkColor ? color : '#eee'
+ }
+ appStore.setTheme(theme)
+ appStore.setCssVarTheme()
+}
+if (layout.value === 'top' && !appStore.getIsDark) {
+ headerTheme.value = '#fff'
+ setHeaderTheme('#fff')
+}
+
+// 鐩戝惉layout鍙樺寲锛岄噸缃竴浜涗富棰樿壊
+watch(
+ () => layout.value,
+ (n) => {
+ if (n === 'top' && !appStore.getIsDark) {
+ headerTheme.value = '#fff'
+ setHeaderTheme('#fff')
+ } else {
+ setMenuTheme(unref(menuTheme))
+ }
+ }
+)
+
+// 鎷疯礉
+const copyConfig = async () => {
+ const { copy, copied, isSupported } = useClipboard({
+ legacy: true,
+ source: `
+ // 闈㈠寘灞�
+ breadcrumb: ${appStore.getBreadcrumb},
+ // 闈㈠寘灞戝浘鏍�
+ breadcrumbIcon: ${appStore.getBreadcrumbIcon},
+ // 鎶樺彔鍥炬爣
+ hamburger: ${appStore.getHamburger},
+ // 鍏ㄥ睆鍥炬爣
+ screenfull: ${appStore.getScreenfull},
+ // 灏哄鍥炬爣
+ size: ${appStore.getSize},
+ // 澶氳瑷�鍥炬爣
+ locale: ${appStore.getLocale},
+ // 娑堟伅鍥炬爣
+ message: ${appStore.getMessage},
+ // 鏍囩椤�
+ tagsView: ${appStore.getTagsView},
+ // 鏍囩椤�
+ tagsViewImmerse: ${appStore.getTagsViewImmerse},
+ // 鏍囩椤靛浘鏍�
+ tagsViewIcon: ${appStore.getTagsViewIcon},
+ // logo
+ logo: ${appStore.getLogo},
+ // 鑿滃崟鎵嬮鐞�
+ uniqueOpened: ${appStore.getUniqueOpened},
+ // 鍥哄畾header
+ fixedHeader: ${appStore.getFixedHeader},
+ // 椤佃剼
+ footer: ${appStore.getFooter},
+ // 鐏拌壊妯″紡
+ greyMode: ${appStore.getGreyMode},
+ // layout甯冨眬
+ layout: '${appStore.getLayout}',
+ // 鏆楅粦妯″紡
+ isDark: ${appStore.getIsDark},
+ // 缁勪欢灏哄
+ currentSize: '${appStore.getCurrentSize}',
+ // 涓婚鐩稿叧
+ theme: {
+ // 涓婚鑹�
+ elColorPrimary: '${appStore.getTheme.elColorPrimary}',
+ // 宸︿晶鑿滃崟杈规棰滆壊
+ leftMenuBorderColor: '${appStore.getTheme.leftMenuBorderColor}',
+ // 宸︿晶鑿滃崟鑳屾櫙棰滆壊
+ leftMenuBgColor: '${appStore.getTheme.leftMenuBgColor}',
+ // 宸︿晶鑿滃崟娴呰壊鑳屾櫙棰滆壊
+ leftMenuBgLightColor: '${appStore.getTheme.leftMenuBgLightColor}',
+ // 宸︿晶鑿滃崟閫変腑鑳屾櫙棰滆壊
+ leftMenuBgActiveColor: '${appStore.getTheme.leftMenuBgActiveColor}',
+ // 宸︿晶鑿滃崟鏀惰捣閫変腑鑳屾櫙棰滆壊
+ leftMenuCollapseBgActiveColor: '${appStore.getTheme.leftMenuCollapseBgActiveColor}',
+ // 宸︿晶鑿滃崟瀛椾綋棰滆壊
+ leftMenuTextColor: '${appStore.getTheme.leftMenuTextColor}',
+ // 宸︿晶鑿滃崟閫変腑瀛椾綋棰滆壊
+ leftMenuTextActiveColor: '${appStore.getTheme.leftMenuTextActiveColor}',
+ // logo瀛椾綋棰滆壊
+ logoTitleTextColor: '${appStore.getTheme.logoTitleTextColor}',
+ // logo杈规棰滆壊
+ logoBorderColor: '${appStore.getTheme.logoBorderColor}',
+ // 澶撮儴鑳屾櫙棰滆壊
+ topHeaderBgColor: '${appStore.getTheme.topHeaderBgColor}',
+ // 澶撮儴瀛椾綋棰滆壊
+ topHeaderTextColor: '${appStore.getTheme.topHeaderTextColor}',
+ // 澶撮儴鎮仠棰滆壊
+ topHeaderHoverColor: '${appStore.getTheme.topHeaderHoverColor}',
+ // 澶撮儴杈规棰滆壊
+ topToolBorderColor: '${appStore.getTheme.topToolBorderColor}'
+ }
+ `
+ })
+ if (!isSupported) {
+ ElMessage.error(t('setting.copyFailed'))
+ } else {
+ await copy()
+ if (unref(copied)) {
+ ElMessage.success(t('setting.copySuccess'))
+ }
+ }
+}
+
+// 娓呯┖缂撳瓨
+const clear = () => {
+ const { wsCache } = useCache()
+ wsCache.delete(CACHE_KEY.LAYOUT)
+ wsCache.delete(CACHE_KEY.THEME)
+ wsCache.delete(CACHE_KEY.IS_DARK)
+ window.location.reload()
+}
+</script>
+
+<template>
+ <div
+ :class="prefixCls"
+ class="fixed right-0 top-[45%] h-40px w-40px cursor-pointer bg-[var(--el-color-primary)] text-center leading-40px"
+ @click="drawer = true"
+ >
+ <Icon color="#fff" icon="ep:setting" />
+ </div>
+
+ <ElDrawer v-model="drawer" :z-index="4000" direction="rtl" size="350px">
+ <template #header>
+ <span class="text-16px font-700">{{ t('setting.projectSetting') }}</span>
+ </template>
+
+ <div class="text-center">
+ <!-- 涓婚 -->
+ <ElDivider>{{ t('setting.theme') }}</ElDivider>
+ <ThemeSwitch />
+
+ <!-- 甯冨眬 -->
+ <ElDivider>{{ t('setting.layout') }}</ElDivider>
+ <LayoutRadioPicker />
+
+ <!-- 绯荤粺涓婚 -->
+ <ElDivider>{{ t('setting.systemTheme') }}</ElDivider>
+ <ColorRadioPicker
+ v-model="systemTheme"
+ :schema="[
+ '#409eff',
+ '#009688',
+ '#536dfe',
+ '#ff5c93',
+ '#ee4f12',
+ '#0096c7',
+ '#9c27b0',
+ '#ff9800'
+ ]"
+ @change="setSystemTheme"
+ />
+
+ <!-- 澶撮儴涓婚 -->
+ <ElDivider>{{ t('setting.headerTheme') }}</ElDivider>
+ <ColorRadioPicker
+ v-model="headerTheme"
+ :schema="[
+ '#fff',
+ '#151515',
+ '#5172dc',
+ '#e74c3c',
+ '#24292e',
+ '#394664',
+ '#009688',
+ '#383f45'
+ ]"
+ @change="setHeaderTheme"
+ />
+
+ <!-- 鑿滃崟涓婚 -->
+ <template v-if="layout !== 'top'">
+ <ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
+ <ColorRadioPicker
+ v-model="menuTheme"
+ :schema="[
+ '#fff',
+ '#001529',
+ '#212121',
+ '#273352',
+ '#191b24',
+ '#383f45',
+ '#001628',
+ '#344058'
+ ]"
+ @change="setMenuTheme"
+ />
+ </template>
+ </div>
+
+ <!-- 鐣岄潰鏄剧ず -->
+ <ElDivider>{{ t('setting.interfaceDisplay') }}</ElDivider>
+ <InterfaceDisplay />
+
+ <ElDivider />
+ <div>
+ <ElButton class="w-full" type="primary" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
+ </div>
+ <div class="mt-5px">
+ <ElButton class="w-full" type="danger" @click="clear">
+ {{ t('setting.clearAndReset') }}
+ </ElButton>
+ </div>
+ </ElDrawer>
+</template>
+
+<style lang="scss" scoped>
+$prefix-cls: #{$namespace}-setting;
+
+.#{$prefix-cls} {
+ z-index: 1200; /* 淇娌℃湁z-index浼氳琛ㄦ牸灞傝鐩�,鍊间笉瑕佽秴杩�4000 */
+ border-radius: 6px 0 0 6px;
+}
+</style>
--
Gitblit v1.8.0