提交 | 用户 | 时间
820397 1 <script lang="ts" setup>
H 2 import { ElMessage } from 'element-plus'
3 import { useClipboard, useCssVar } from '@vueuse/core'
4
5 import { CACHE_KEY, useCache } from '@/hooks/web/useCache'
6 import { useDesign } from '@/hooks/web/useDesign'
7
8 import { setCssVar, trim } from '@/utils'
9 import { colorIsDark, hexToRGB, lighten } from '@/utils/color'
10 import { useAppStore } from '@/store/modules/app'
11 import { ThemeSwitch } from '@/layout/components/ThemeSwitch'
12 import ColorRadioPicker from './components/ColorRadioPicker.vue'
13 import InterfaceDisplay from './components/InterfaceDisplay.vue'
14 import LayoutRadioPicker from './components/LayoutRadioPicker.vue'
15
16 defineOptions({ name: 'Setting' })
17
18 const { t } = useI18n()
19 const appStore = useAppStore()
20
21 const { getPrefixCls } = useDesign()
22 const prefixCls = getPrefixCls('setting')
23 const layout = computed(() => appStore.getLayout)
24 const drawer = ref(false)
25
26 // 主题色相关
27 const systemTheme = ref(appStore.getTheme.elColorPrimary)
28
29 const setSystemTheme = (color: string) => {
30   setCssVar('--el-color-primary', color)
31   appStore.setTheme({ elColorPrimary: color })
32   const leftMenuBgColor = useCssVar('--left-menu-bg-color', document.documentElement)
33   setMenuTheme(trim(unref(leftMenuBgColor)))
34 }
35
36 // 头部主题相关
37 const headerTheme = ref(appStore.getTheme.topHeaderBgColor || '')
38
39 const setHeaderTheme = (color: string) => {
40   const isDarkColor = colorIsDark(color)
41   const textColor = isDarkColor ? '#fff' : 'inherit'
42   const textHoverColor = isDarkColor ? lighten(color!, 6) : '#f6f6f6'
43   const topToolBorderColor = isDarkColor ? color : '#eee'
44   setCssVar('--top-header-bg-color', color)
45   setCssVar('--top-header-text-color', textColor)
46   setCssVar('--top-header-hover-color', textHoverColor)
47   appStore.setTheme({
48     topHeaderBgColor: color,
49     topHeaderTextColor: textColor,
50     topHeaderHoverColor: textHoverColor,
51     topToolBorderColor
52   })
53   if (unref(layout) === 'top') {
54     setMenuTheme(color)
55   }
56 }
57
58 // 菜单主题相关
59 const menuTheme = ref(appStore.getTheme.leftMenuBgColor || '')
60
61 const setMenuTheme = (color: string) => {
62   const primaryColor = useCssVar('--el-color-primary', document.documentElement)
63   const isDarkColor = colorIsDark(color)
64   const theme: Recordable = {
65     // 左侧菜单边框颜色
66     leftMenuBorderColor: isDarkColor ? 'inherit' : '#eee',
67     // 左侧菜单背景颜色
68     leftMenuBgColor: color,
69     // 左侧菜单浅色背景颜色
70     leftMenuBgLightColor: isDarkColor ? lighten(color!, 6) : color,
71     // 左侧菜单选中背景颜色
72     leftMenuBgActiveColor: isDarkColor
73       ? 'var(--el-color-primary)'
74       : hexToRGB(unref(primaryColor), 0.1),
75     // 左侧菜单收起选中背景颜色
76     leftMenuCollapseBgActiveColor: isDarkColor
77       ? 'var(--el-color-primary)'
78       : hexToRGB(unref(primaryColor), 0.1),
79     // 左侧菜单字体颜色
80     leftMenuTextColor: isDarkColor ? '#bfcbd9' : '#333',
81     // 左侧菜单选中字体颜色
82     leftMenuTextActiveColor: isDarkColor ? '#fff' : 'var(--el-color-primary)',
83     // logo字体颜色
84     logoTitleTextColor: isDarkColor ? '#fff' : 'inherit',
85     // logo边框颜色
86     logoBorderColor: isDarkColor ? color : '#eee'
87   }
88   appStore.setTheme(theme)
89   appStore.setCssVarTheme()
90 }
91 if (layout.value === 'top' && !appStore.getIsDark) {
92   headerTheme.value = '#fff'
93   setHeaderTheme('#fff')
94 }
95
96 // 监听layout变化,重置一些主题色
97 watch(
98   () => layout.value,
99   (n) => {
100     if (n === 'top' && !appStore.getIsDark) {
101       headerTheme.value = '#fff'
102       setHeaderTheme('#fff')
103     } else {
104       setMenuTheme(unref(menuTheme))
105     }
106   }
107 )
108
109 // 拷贝
110 const copyConfig = async () => {
111   const { copy, copied, isSupported } = useClipboard({
112     source: `
113       // 面包屑
114       breadcrumb: ${appStore.getBreadcrumb},
115       // 面包屑图标
116       breadcrumbIcon: ${appStore.getBreadcrumbIcon},
117       // 折叠图标
118       hamburger: ${appStore.getHamburger},
119       // 全屏图标
120       screenfull: ${appStore.getScreenfull},
121       // 尺寸图标
122       size: ${appStore.getSize},
123       // 多语言图标
124       locale: ${appStore.getLocale},
125       // 消息图标
126       message: ${appStore.getMessage},
127       // 标签页
128       tagsView: ${appStore.getTagsView},
3e359e 129       // 标签页
H 130       tagsViewImmerse: ${appStore.getTagsViewImmerse},
820397 131       // 标签页图标
3e359e 132       tagsViewIcon: ${appStore.getTagsViewIcon},
820397 133       // logo
H 134       logo: ${appStore.getLogo},
135       // 菜单手风琴
136       uniqueOpened: ${appStore.getUniqueOpened},
137       // 固定header
138       fixedHeader: ${appStore.getFixedHeader},
139       // 页脚
140       footer: ${appStore.getFooter},
141       // 灰色模式
142       greyMode: ${appStore.getGreyMode},
143       // layout布局
144       layout: '${appStore.getLayout}',
145       // 暗黑模式
146       isDark: ${appStore.getIsDark},
147       // 组件尺寸
148       currentSize: '${appStore.getCurrentSize}',
149       // 主题相关
150       theme: {
151         // 主题色
152         elColorPrimary: '${appStore.getTheme.elColorPrimary}',
153         // 左侧菜单边框颜色
154         leftMenuBorderColor: '${appStore.getTheme.leftMenuBorderColor}',
155         // 左侧菜单背景颜色
156         leftMenuBgColor: '${appStore.getTheme.leftMenuBgColor}',
157         // 左侧菜单浅色背景颜色
158         leftMenuBgLightColor: '${appStore.getTheme.leftMenuBgLightColor}',
159         // 左侧菜单选中背景颜色
160         leftMenuBgActiveColor: '${appStore.getTheme.leftMenuBgActiveColor}',
161         // 左侧菜单收起选中背景颜色
162         leftMenuCollapseBgActiveColor: '${appStore.getTheme.leftMenuCollapseBgActiveColor}',
163         // 左侧菜单字体颜色
164         leftMenuTextColor: '${appStore.getTheme.leftMenuTextColor}',
165         // 左侧菜单选中字体颜色
166         leftMenuTextActiveColor: '${appStore.getTheme.leftMenuTextActiveColor}',
167         // logo字体颜色
168         logoTitleTextColor: '${appStore.getTheme.logoTitleTextColor}',
169         // logo边框颜色
170         logoBorderColor: '${appStore.getTheme.logoBorderColor}',
171         // 头部背景颜色
172         topHeaderBgColor: '${appStore.getTheme.topHeaderBgColor}',
173         // 头部字体颜色
174         topHeaderTextColor: '${appStore.getTheme.topHeaderTextColor}',
175         // 头部悬停颜色
176         topHeaderHoverColor: '${appStore.getTheme.topHeaderHoverColor}',
177         // 头部边框颜色
178         topToolBorderColor: '${appStore.getTheme.topToolBorderColor}'
179       }
180     `
181   })
182   if (!isSupported) {
183     ElMessage.error(t('setting.copyFailed'))
184   } else {
185     await copy()
186     if (unref(copied)) {
187       ElMessage.success(t('setting.copySuccess'))
188     }
189   }
190 }
191
192 // 清空缓存
193 const clear = () => {
194   const { wsCache } = useCache()
195   wsCache.delete(CACHE_KEY.LAYOUT)
196   wsCache.delete(CACHE_KEY.THEME)
197   wsCache.delete(CACHE_KEY.IS_DARK)
198   window.location.reload()
199 }
200 </script>
201
202 <template>
203   <div
204     :class="prefixCls"
205     class="fixed right-0 top-[45%] h-40px w-40px cursor-pointer bg-[var(--el-color-primary)] text-center leading-40px"
206     @click="drawer = true"
207   >
208     <Icon color="#fff" icon="ep:setting" />
209   </div>
210
211   <ElDrawer v-model="drawer" :z-index="4000" direction="rtl" size="350px">
212     <template #header>
213       <span class="text-16px font-700">{{ t('setting.projectSetting') }}</span>
214     </template>
215
216     <div class="text-center">
217       <!-- 主题 -->
218       <ElDivider>{{ t('setting.theme') }}</ElDivider>
219       <ThemeSwitch />
220
221       <!-- 布局 -->
222       <ElDivider>{{ t('setting.layout') }}</ElDivider>
223       <LayoutRadioPicker />
224
225       <!-- 系统主题 -->
226       <ElDivider>{{ t('setting.systemTheme') }}</ElDivider>
227       <ColorRadioPicker
228         v-model="systemTheme"
229         :schema="[
230           '#409eff',
231           '#009688',
232           '#536dfe',
233           '#ff5c93',
234           '#ee4f12',
235           '#0096c7',
236           '#9c27b0',
237           '#ff9800'
238         ]"
239         @change="setSystemTheme"
240       />
241
242       <!-- 头部主题 -->
243       <ElDivider>{{ t('setting.headerTheme') }}</ElDivider>
244       <ColorRadioPicker
245         v-model="headerTheme"
246         :schema="[
247           '#fff',
248           '#151515',
249           '#5172dc',
250           '#e74c3c',
251           '#24292e',
252           '#394664',
253           '#009688',
254           '#383f45'
255         ]"
256         @change="setHeaderTheme"
257       />
258
259       <!-- 菜单主题 -->
260       <template v-if="layout !== 'top'">
261         <ElDivider>{{ t('setting.menuTheme') }}</ElDivider>
262         <ColorRadioPicker
263           v-model="menuTheme"
264           :schema="[
265             '#fff',
266             '#001529',
267             '#212121',
268             '#273352',
269             '#191b24',
270             '#383f45',
271             '#001628',
272             '#344058'
273           ]"
274           @change="setMenuTheme"
275         />
276       </template>
277     </div>
278
279     <!-- 界面显示 -->
280     <ElDivider>{{ t('setting.interfaceDisplay') }}</ElDivider>
281     <InterfaceDisplay />
282
283     <ElDivider />
284     <div>
285       <ElButton class="w-full" type="primary" @click="copyConfig">{{ t('setting.copy') }}</ElButton>
286     </div>
287     <div class="mt-5px">
288       <ElButton class="w-full" type="danger" @click="clear">
289         {{ t('setting.clearAndReset') }}
290       </ElButton>
291     </div>
292   </ElDrawer>
293 </template>
294
295 <style lang="scss" scoped>
296 $prefix-cls: #{$namespace}-setting;
297
298 .#{$prefix-cls} {
299   border-radius: 6px 0 0 6px;
3e359e 300   z-index: 1200;/*修正没有z-index会被表格层覆盖,值不要超过4000*/
820397 301 }
H 302 </style>