|
@@ -1,58 +1,84 @@
|
|
|
<script setup lang="ts">
|
|
|
-import { split } from "lodash-es";
|
|
|
-import panel from "../panel/index.vue";
|
|
|
-import { useRouter } from "vue-router";
|
|
|
-import { emitter } from "/@/utils/mitt";
|
|
|
-import { templateRef } from "@vueuse/core";
|
|
|
-import { debounce } from "/@/utils/debounce";
|
|
|
-import { useAppStoreHook } from "/@/store/modules/app";
|
|
|
-import { storageLocal, storageSession } from "/@/utils/storage";
|
|
|
import {
|
|
|
reactive,
|
|
|
ref,
|
|
|
unref,
|
|
|
watch,
|
|
|
+ computed,
|
|
|
+ nextTick,
|
|
|
useCssModule,
|
|
|
getCurrentInstance
|
|
|
} from "vue";
|
|
|
+import panel from "../panel/index.vue";
|
|
|
+import { useRouter } from "vue-router";
|
|
|
+import { emitter } from "/@/utils/mitt";
|
|
|
+import { templateRef } from "@vueuse/core";
|
|
|
+import { debounce } from "/@/utils/debounce";
|
|
|
+import { themeColorsType } from "../../types";
|
|
|
+import { useAppStoreHook } from "/@/store/modules/app";
|
|
|
+import { storageLocal, storageSession } from "/@/utils/storage";
|
|
|
+import { toggleTheme } from "@zougt/vite-plugin-theme-preprocessor/dist/browser-utils";
|
|
|
|
|
|
const router = useRouter();
|
|
|
const { isSelect } = useCssModule();
|
|
|
-
|
|
|
const instance =
|
|
|
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
|
|
|
|
|
+const instanceConfig =
|
|
|
+ getCurrentInstance().appContext.app.config.globalProperties.$config;
|
|
|
+
|
|
|
+let themeColors = ref<Array<themeColorsType>>([
|
|
|
+ // 暗雅(默认)
|
|
|
+ { rgb: "27, 42, 71", themeColor: "default" },
|
|
|
+ // 明亮
|
|
|
+ { rgb: "255, 255, 255", themeColor: "light" },
|
|
|
+ // 薄暮
|
|
|
+ { rgb: "245, 34, 45", themeColor: "dusk" },
|
|
|
+ // 火山
|
|
|
+ { rgb: "250, 84, 28", themeColor: "volcano" },
|
|
|
+ // 黄色
|
|
|
+ { rgb: "250, 219, 20", themeColor: "yellow" },
|
|
|
+ // 明青
|
|
|
+ { rgb: "19, 194, 194", themeColor: "mingQing" },
|
|
|
+ // 极光绿
|
|
|
+ { rgb: "82, 196, 26", themeColor: "auroraGreen" },
|
|
|
+ // 粉红
|
|
|
+ { rgb: "235, 47, 150", themeColor: "pink" },
|
|
|
+ // 酱紫
|
|
|
+ { rgb: "114, 46, 209", themeColor: "saucePurple" }
|
|
|
+]);
|
|
|
+
|
|
|
+const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
|
|
|
+const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
|
|
|
+
|
|
|
+let layoutTheme =
|
|
|
+ ref(storageLocal.getItem("responsive-layout")) ||
|
|
|
+ ref({
|
|
|
+ layout: instanceConfig?.Layout ?? "vertical",
|
|
|
+ theme: instanceConfig?.Theme ?? "default"
|
|
|
+ });
|
|
|
+
|
|
|
+// body添加layout属性,作用于src/style/sidebar.scss
|
|
|
+if (unref(layoutTheme)) {
|
|
|
+ let layout = unref(layoutTheme).layout;
|
|
|
+ let theme = unref(layoutTheme).theme;
|
|
|
+ toggleTheme({
|
|
|
+ scopeName: `layout-theme-${theme}`
|
|
|
+ });
|
|
|
+ setLayoutModel(layout);
|
|
|
+}
|
|
|
+
|
|
|
// 默认灵动模式
|
|
|
const markValue = ref(storageLocal.getItem("showModel") || "smart");
|
|
|
|
|
|
const logoVal = ref(storageLocal.getItem("logoVal") || "1");
|
|
|
|
|
|
-const localOperate = (key: string, value?: any, model?: string): any => {
|
|
|
- model && model === "set"
|
|
|
- ? storageLocal.setItem(key, value)
|
|
|
- : storageLocal.getItem(key);
|
|
|
-};
|
|
|
-
|
|
|
const settings = reactive({
|
|
|
- greyVal: storageLocal.getItem("greyVal"),
|
|
|
- weekVal: storageLocal.getItem("weekVal"),
|
|
|
- tagsVal: storageLocal.getItem("tagsVal")
|
|
|
+ greyVal: instance.sets.grey,
|
|
|
+ weakVal: instance.sets.weak,
|
|
|
+ tabsVal: instance.sets.hideTabs
|
|
|
});
|
|
|
|
|
|
-settings.greyVal === null
|
|
|
- ? localOperate("greyVal", false, "set")
|
|
|
- : document.querySelector("html")?.setAttribute("class", "html-grey");
|
|
|
-
|
|
|
-settings.weekVal === null
|
|
|
- ? localOperate("weekVal", false, "set")
|
|
|
- : document.querySelector("html")?.setAttribute("class", "html-weakness");
|
|
|
-
|
|
|
-if (settings.tagsVal === null) {
|
|
|
- localOperate("tagsVal", false, "set");
|
|
|
- settings.tagsVal = false;
|
|
|
-}
|
|
|
-window.document.body.setAttribute("data-show-tag", settings.tagsVal);
|
|
|
-
|
|
|
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
|
|
const targetEl = target || document.body;
|
|
|
let { className } = targetEl;
|
|
@@ -61,76 +87,62 @@ function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
|
|
}
|
|
|
|
|
|
// 灰色模式设置
|
|
|
-const greyChange = ({ value }): void => {
|
|
|
+const greyChange = (value): void => {
|
|
|
toggleClass(settings.greyVal, "html-grey", document.querySelector("html"));
|
|
|
- value
|
|
|
- ? localOperate("greyVal", true, "set")
|
|
|
- : localOperate("greyVal", false, "set");
|
|
|
+ instance.sets = {
|
|
|
+ grey: value,
|
|
|
+ weak: instance.sets.weak,
|
|
|
+ hideTabs: instance.sets.hideTabs
|
|
|
+ };
|
|
|
};
|
|
|
|
|
|
// 色弱模式设置
|
|
|
-const weekChange = ({ value }): void => {
|
|
|
+const weekChange = (value): void => {
|
|
|
toggleClass(
|
|
|
- settings.weekVal,
|
|
|
+ settings.weakVal,
|
|
|
"html-weakness",
|
|
|
document.querySelector("html")
|
|
|
);
|
|
|
- value
|
|
|
- ? localOperate("weekVal", true, "set")
|
|
|
- : localOperate("weekVal", false, "set");
|
|
|
+ instance.sets = {
|
|
|
+ grey: instance.sets.grey,
|
|
|
+ weak: value,
|
|
|
+ hideTabs: instance.sets.hideTabs
|
|
|
+ };
|
|
|
};
|
|
|
|
|
|
const tagsChange = () => {
|
|
|
- let showVal = settings.tagsVal;
|
|
|
- showVal
|
|
|
- ? storageLocal.setItem("tagsVal", true)
|
|
|
- : storageLocal.setItem("tagsVal", false);
|
|
|
+ let showVal = settings.tabsVal;
|
|
|
+ instance.sets = {
|
|
|
+ grey: instance.sets.grey,
|
|
|
+ weak: instance.sets.weak,
|
|
|
+ hideTabs: showVal
|
|
|
+ };
|
|
|
emitter.emit("tagViewsChange", showVal);
|
|
|
};
|
|
|
|
|
|
+//初始化项目配置
|
|
|
+nextTick(() => {
|
|
|
+ settings.greyVal &&
|
|
|
+ document.querySelector("html")?.setAttribute("class", "html-grey");
|
|
|
+ settings.weakVal &&
|
|
|
+ document.querySelector("html")?.setAttribute("class", "html-weakness");
|
|
|
+ settings.tabsVal && tagsChange();
|
|
|
+});
|
|
|
+
|
|
|
+// 清空缓存并返回登录页
|
|
|
function onReset() {
|
|
|
storageLocal.clear();
|
|
|
storageSession.clear();
|
|
|
+ toggleClass(false, "html-grey", document.querySelector("html"));
|
|
|
+ toggleClass(false, "html-weakness", document.querySelector("html"));
|
|
|
router.push("/login");
|
|
|
}
|
|
|
|
|
|
-function onChange({ label }) {
|
|
|
+function onChange(label) {
|
|
|
storageLocal.setItem("showModel", label);
|
|
|
emitter.emit("tagViewsShowModel", label);
|
|
|
}
|
|
|
|
|
|
-const verticalDarkDom = templateRef<HTMLElement | null>(
|
|
|
- "verticalDarkDom",
|
|
|
- null
|
|
|
-);
|
|
|
-const verticalLightDom = templateRef<HTMLElement | null>(
|
|
|
- "verticalLightDom",
|
|
|
- null
|
|
|
-);
|
|
|
-const horizontalDarkDom = templateRef<HTMLElement | null>(
|
|
|
- "horizontalDarkDom",
|
|
|
- null
|
|
|
-);
|
|
|
-const horizontalLightDom = templateRef<HTMLElement | null>(
|
|
|
- "horizontalLightDom",
|
|
|
- null
|
|
|
-);
|
|
|
-
|
|
|
-let dataTheme =
|
|
|
- ref(storageLocal.getItem("responsive-layout")) ||
|
|
|
- ref({
|
|
|
- layout: "horizontal-dark"
|
|
|
- });
|
|
|
-
|
|
|
-if (unref(dataTheme)) {
|
|
|
- // 设置主题
|
|
|
- let theme = split(unref(dataTheme).layout, "-")[1];
|
|
|
- window.document.body.setAttribute("data-theme", theme);
|
|
|
- // 设置导航模式
|
|
|
- let layout = split(unref(dataTheme).layout, "-")[0];
|
|
|
- window.document.body.setAttribute("data-layout", layout);
|
|
|
-}
|
|
|
-
|
|
|
// 侧边栏Logo
|
|
|
function logoChange() {
|
|
|
unref(logoVal) === "1"
|
|
@@ -147,155 +159,170 @@ function setFalse(Doms): any {
|
|
|
|
|
|
watch(instance, ({ layout }) => {
|
|
|
switch (layout["layout"]) {
|
|
|
- case "vertical-dark":
|
|
|
- toggleClass(true, isSelect, unref(verticalDarkDom));
|
|
|
- debounce(
|
|
|
- setFalse([verticalLightDom, horizontalDarkDom, horizontalLightDom]),
|
|
|
- 50
|
|
|
- );
|
|
|
- break;
|
|
|
- case "vertical-light":
|
|
|
- toggleClass(true, isSelect, unref(verticalLightDom));
|
|
|
- debounce(
|
|
|
- setFalse([verticalDarkDom, horizontalDarkDom, horizontalLightDom]),
|
|
|
- 50
|
|
|
- );
|
|
|
- break;
|
|
|
- case "horizontal-dark":
|
|
|
- toggleClass(true, isSelect, unref(horizontalDarkDom));
|
|
|
- debounce(
|
|
|
- setFalse([verticalDarkDom, verticalLightDom, horizontalLightDom]),
|
|
|
- 50
|
|
|
- );
|
|
|
+ case "vertical":
|
|
|
+ toggleClass(true, isSelect, unref(verticalRef));
|
|
|
+ debounce(setFalse([horizontalRef]), 50);
|
|
|
break;
|
|
|
- case "horizontal-light":
|
|
|
- toggleClass(true, isSelect, unref(horizontalLightDom));
|
|
|
- debounce(
|
|
|
- setFalse([verticalDarkDom, verticalLightDom, horizontalDarkDom]),
|
|
|
- 50
|
|
|
- );
|
|
|
+ case "horizontal":
|
|
|
+ toggleClass(true, isSelect, unref(horizontalRef));
|
|
|
+ debounce(setFalse([verticalRef]), 50);
|
|
|
break;
|
|
|
}
|
|
|
});
|
|
|
|
|
|
-function setTheme(layout: string, theme: string) {
|
|
|
- dataTheme.value.layout = `${layout}-${theme}`;
|
|
|
- window.document.body.setAttribute("data-layout", layout);
|
|
|
- window.document.body.setAttribute("data-theme", theme);
|
|
|
- instance.layout = { layout: `${layout}-${theme}` };
|
|
|
+// 主题色 激活选择项
|
|
|
+const getThemeColor = computed(() => {
|
|
|
+ return current => {
|
|
|
+ if (
|
|
|
+ current === layoutTheme.value.theme &&
|
|
|
+ layoutTheme.value.theme !== "light"
|
|
|
+ ) {
|
|
|
+ return "#fff";
|
|
|
+ } else if (
|
|
|
+ current === layoutTheme.value.theme &&
|
|
|
+ layoutTheme.value.theme === "light"
|
|
|
+ ) {
|
|
|
+ return "#1d2b45";
|
|
|
+ } else {
|
|
|
+ return "transparent";
|
|
|
+ }
|
|
|
+ };
|
|
|
+});
|
|
|
+
|
|
|
+// 设置导航模式
|
|
|
+function setLayoutModel(layout: string) {
|
|
|
+ layoutTheme.value.layout = layout;
|
|
|
+ window.document.body.setAttribute("layout", layout);
|
|
|
+ instance.layout = { layout, theme: layoutTheme.value.theme };
|
|
|
useAppStoreHook().setLayout(layout);
|
|
|
}
|
|
|
+
|
|
|
+// 设置导航主题色
|
|
|
+function setLayoutThemeColor(theme: string) {
|
|
|
+ layoutTheme.value.theme = theme;
|
|
|
+ toggleTheme({
|
|
|
+ scopeName: `layout-theme-${theme}`
|
|
|
+ });
|
|
|
+ instance.layout = { layout: useAppStoreHook().layout, theme };
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
|
<panel>
|
|
|
<el-divider>主题风格</el-divider>
|
|
|
- <ul class="theme-stley">
|
|
|
- <el-tooltip class="item" content="左侧菜单暗色模式" placement="bottom">
|
|
|
+ <ul class="pure-theme">
|
|
|
+ <el-tooltip class="item" content="左侧菜单模式" placement="bottom">
|
|
|
<li
|
|
|
- :class="dataTheme.layout === 'vertical-dark' ? $style.isSelect : ''"
|
|
|
- ref="verticalDarkDom"
|
|
|
- @click="setTheme('vertical', 'dark')"
|
|
|
+ :class="layoutTheme.layout === 'vertical' ? $style.isSelect : ''"
|
|
|
+ ref="verticalRef"
|
|
|
+ @click="setLayoutModel('vertical')"
|
|
|
>
|
|
|
<div></div>
|
|
|
<div></div>
|
|
|
</li>
|
|
|
</el-tooltip>
|
|
|
|
|
|
- <el-tooltip class="item" content="左侧菜单亮色模式" placement="bottom">
|
|
|
+ <el-tooltip class="item" content="顶部菜单模式" placement="bottom">
|
|
|
<li
|
|
|
- :class="dataTheme.layout === 'vertical-light' ? $style.isSelect : ''"
|
|
|
- ref="verticalLightDom"
|
|
|
- @click="setTheme('vertical', 'light')"
|
|
|
- >
|
|
|
- <div></div>
|
|
|
- <div></div>
|
|
|
- </li>
|
|
|
- </el-tooltip>
|
|
|
-
|
|
|
- <el-tooltip class="item" content="顶部菜单暗色模式" placement="bottom">
|
|
|
- <li
|
|
|
- :class="dataTheme.layout === 'horizontal-dark' ? $style.isSelect : ''"
|
|
|
- ref="horizontalDarkDom"
|
|
|
- @click="setTheme('horizontal', 'dark')"
|
|
|
+ :class="layoutTheme.layout === 'horizontal' ? $style.isSelect : ''"
|
|
|
+ ref="horizontalRef"
|
|
|
+ @click="setLayoutModel('horizontal')"
|
|
|
>
|
|
|
<div></div>
|
|
|
<div></div>
|
|
|
</li>
|
|
|
</el-tooltip>
|
|
|
+ </ul>
|
|
|
|
|
|
- <el-tooltip class="item" content="顶部菜单亮色模式" placement="bottom">
|
|
|
- <li
|
|
|
- :class="
|
|
|
- dataTheme.layout === 'horizontal-light' ? $style.isSelect : ''
|
|
|
- "
|
|
|
- ref="horizontalLightDom"
|
|
|
- @click="setTheme('horizontal', 'light')"
|
|
|
+ <el-divider>主题色</el-divider>
|
|
|
+ <ul class="theme-color">
|
|
|
+ <li
|
|
|
+ v-for="(item, index) in themeColors"
|
|
|
+ :key="index"
|
|
|
+ :style="{ background: `rgb(${item.rgb})` }"
|
|
|
+ @click="setLayoutThemeColor(item.themeColor)"
|
|
|
+ >
|
|
|
+ <el-icon
|
|
|
+ style="margin: 0.1em 0.1em 0 0"
|
|
|
+ :size="17"
|
|
|
+ :color="getThemeColor(item.themeColor)"
|
|
|
>
|
|
|
- <div></div>
|
|
|
- <div></div>
|
|
|
- </li>
|
|
|
- </el-tooltip>
|
|
|
+ <Check />
|
|
|
+ </el-icon>
|
|
|
+ </li>
|
|
|
</ul>
|
|
|
|
|
|
<el-divider>界面显示</el-divider>
|
|
|
<ul class="setting">
|
|
|
<li>
|
|
|
<span>灰色模式</span>
|
|
|
- <vxe-switch
|
|
|
+ <el-switch
|
|
|
v-model="settings.greyVal"
|
|
|
- open-label="开"
|
|
|
- close-label="关"
|
|
|
+ inline-prompt
|
|
|
+ inactive-color="#a6a6a6"
|
|
|
+ active-text="开"
|
|
|
+ inactive-text="关"
|
|
|
@change="greyChange"
|
|
|
- ></vxe-switch>
|
|
|
+ >
|
|
|
+ </el-switch>
|
|
|
</li>
|
|
|
<li>
|
|
|
<span>色弱模式</span>
|
|
|
- <vxe-switch
|
|
|
- v-model="settings.weekVal"
|
|
|
- open-label="开"
|
|
|
- close-label="关"
|
|
|
+ <el-switch
|
|
|
+ v-model="settings.weakVal"
|
|
|
+ inline-prompt
|
|
|
+ inactive-color="#a6a6a6"
|
|
|
+ active-text="开"
|
|
|
+ inactive-text="关"
|
|
|
@change="weekChange"
|
|
|
- ></vxe-switch>
|
|
|
+ >
|
|
|
+ </el-switch>
|
|
|
</li>
|
|
|
<li>
|
|
|
<span>隐藏标签页</span>
|
|
|
- <vxe-switch
|
|
|
- v-model="settings.tagsVal"
|
|
|
- open-label="开"
|
|
|
- close-label="关"
|
|
|
+ <el-switch
|
|
|
+ v-model="settings.tabsVal"
|
|
|
+ inline-prompt
|
|
|
+ inactive-color="#a6a6a6"
|
|
|
+ active-text="开"
|
|
|
+ inactive-text="关"
|
|
|
@change="tagsChange"
|
|
|
- ></vxe-switch>
|
|
|
+ >
|
|
|
+ </el-switch>
|
|
|
</li>
|
|
|
<li>
|
|
|
<span>侧边栏Logo</span>
|
|
|
- <vxe-switch
|
|
|
+ <el-switch
|
|
|
v-model="logoVal"
|
|
|
- open-value="1"
|
|
|
- close-value="-1"
|
|
|
- open-label="开"
|
|
|
- close-label="关"
|
|
|
+ inline-prompt
|
|
|
+ active-value="1"
|
|
|
+ inactive-value="-1"
|
|
|
+ inactive-color="#a6a6a6"
|
|
|
+ active-text="开"
|
|
|
+ inactive-text="关"
|
|
|
@change="logoChange"
|
|
|
- ></vxe-switch>
|
|
|
+ >
|
|
|
+ </el-switch>
|
|
|
</li>
|
|
|
|
|
|
<li>
|
|
|
<span>标签风格</span>
|
|
|
- <vxe-radio-group v-model="markValue" @change="onChange">
|
|
|
- <vxe-radio label="card" content="卡片"></vxe-radio>
|
|
|
- <vxe-radio label="smart" content="灵动"></vxe-radio>
|
|
|
- </vxe-radio-group>
|
|
|
+ <el-radio-group v-model="markValue" size="small" @change="onChange">
|
|
|
+ <el-radio label="card">卡片</el-radio>
|
|
|
+ <el-radio label="smart">灵动</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
</li>
|
|
|
</ul>
|
|
|
|
|
|
<el-divider />
|
|
|
- <vxe-button
|
|
|
- status="danger"
|
|
|
+ <el-button
|
|
|
+ type="danger"
|
|
|
style="width: 90%; margin: 24px 15px"
|
|
|
- content="清空缓存并返回登录页"
|
|
|
- icon="fa fa-sign-out"
|
|
|
@click="onReset"
|
|
|
- ></vxe-button>
|
|
|
+ >
|
|
|
+ <i class="fa fa-sign-out"></i>
|
|
|
+ 清空缓存并返回登录页</el-button
|
|
|
+ >
|
|
|
</panel>
|
|
|
</template>
|
|
|
|
|
@@ -322,10 +349,10 @@ function setTheme(layout: string, theme: string) {
|
|
|
font-weight: 700;
|
|
|
}
|
|
|
|
|
|
-.theme-stley {
|
|
|
+.pure-theme {
|
|
|
margin-top: 25px;
|
|
|
width: 100%;
|
|
|
- height: 180px;
|
|
|
+ height: 100px;
|
|
|
display: flex;
|
|
|
flex-wrap: wrap;
|
|
|
justify-content: space-around;
|
|
@@ -362,28 +389,6 @@ function setTheme(layout: string, theme: string) {
|
|
|
}
|
|
|
|
|
|
&:nth-child(2) {
|
|
|
- div {
|
|
|
- &:nth-child(1) {
|
|
|
- width: 30%;
|
|
|
- height: 100%;
|
|
|
- box-shadow: 0 0 1px #888;
|
|
|
- background: #fff;
|
|
|
- border-radius: 4px 0 0 4px;
|
|
|
- }
|
|
|
-
|
|
|
- &:nth-child(2) {
|
|
|
- width: 70%;
|
|
|
- height: 30%;
|
|
|
- top: 0;
|
|
|
- right: 0;
|
|
|
- background: #fff;
|
|
|
- box-shadow: 0 0 1px #888;
|
|
|
- position: absolute;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- &:nth-child(3) {
|
|
|
div {
|
|
|
&:nth-child(1) {
|
|
|
width: 100%;
|
|
@@ -393,16 +398,29 @@ function setTheme(layout: string, theme: string) {
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- &:nth-child(4) {
|
|
|
- div {
|
|
|
- &:nth-child(1) {
|
|
|
- width: 100%;
|
|
|
- height: 30%;
|
|
|
- background: #fff;
|
|
|
- box-shadow: 0 0 1px #888;
|
|
|
- }
|
|
|
- }
|
|
|
+.theme-color {
|
|
|
+ width: 100%;
|
|
|
+ height: 40px;
|
|
|
+ margin-top: 20px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ li {
|
|
|
+ float: left;
|
|
|
+ width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ margin-top: 8px;
|
|
|
+ margin-right: 8px;
|
|
|
+ font-weight: 700;
|
|
|
+ text-align: center;
|
|
|
+ border-radius: 2px;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &:nth-child(2) {
|
|
|
+ border: 1px solid #ddd;
|
|
|
}
|
|
|
}
|
|
|
}
|