Merge commit 'a1bc17ccd0b7d1539a6a9ed9eef5555afc058a73' into main
This commit is contained in:
@@ -1,52 +1,130 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, getCurrentInstance } from "vue";
|
||||
import {
|
||||
h,
|
||||
ref,
|
||||
computed,
|
||||
Transition,
|
||||
defineComponent,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import { RouterView } from "vue-router";
|
||||
import backTop from "/@/assets/svg/back_top.svg";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
|
||||
const props = defineProps({
|
||||
fixedHeader: Boolean
|
||||
});
|
||||
const keepAlive: Boolean = ref(
|
||||
getCurrentInstance().appContext.config.globalProperties.$config?.KeepAlive
|
||||
);
|
||||
const instance =
|
||||
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
||||
|
||||
const transition = computed(() => {
|
||||
const transitions = computed(() => {
|
||||
return route => {
|
||||
return route.meta.transition;
|
||||
};
|
||||
});
|
||||
|
||||
const hideTabs = computed(() => {
|
||||
return instance?.sets.hideTabs;
|
||||
});
|
||||
const layout = computed(() => {
|
||||
return instance?.layout.layout === "vertical";
|
||||
});
|
||||
|
||||
const transitionMain = defineComponent({
|
||||
render() {
|
||||
return h(
|
||||
Transition,
|
||||
{
|
||||
name:
|
||||
transitions.value(this.route) &&
|
||||
this.route.meta.transition.enterTransition
|
||||
? "pure-classes-transition"
|
||||
: (transitions.value(this.route) &&
|
||||
this.route.meta.transition.name) ||
|
||||
"fade-transform",
|
||||
enterActiveClass:
|
||||
transitions.value(this.route) &&
|
||||
`animate__animated ${this.route.meta.transition.enterTransition}`,
|
||||
leaveActiveClass:
|
||||
transitions.value(this.route) &&
|
||||
`animate__animated ${this.route.meta.transition.leaveTransition}`,
|
||||
mode: "out-in",
|
||||
appear: true
|
||||
},
|
||||
{
|
||||
default: () => [this.$slots.default()]
|
||||
}
|
||||
);
|
||||
},
|
||||
props: {
|
||||
route: {
|
||||
type: undefined,
|
||||
required: true
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="app-main">
|
||||
<el-scrollbar>
|
||||
<router-view>
|
||||
<template #default="{ Component, route }">
|
||||
<transition
|
||||
:name="
|
||||
transition(route) && route.meta.transition.enterTransition
|
||||
? 'pure-classes-transition'
|
||||
: (transition(route) && route.meta.transition.name) ||
|
||||
'fade-transform'
|
||||
"
|
||||
:enter-active-class="
|
||||
transition(route) &&
|
||||
`animate__animated ${route.meta.transition.enterTransition}`
|
||||
"
|
||||
:leave-active-class="
|
||||
transition(route) &&
|
||||
`animate__animated ${route.meta.transition.leaveTransition}`
|
||||
"
|
||||
mode="out-in"
|
||||
appear
|
||||
>
|
||||
<section
|
||||
:class="[props.fixedHeader ? 'app-main' : 'app-main-nofixed-header']"
|
||||
:style="[
|
||||
hideTabs && layout ? 'padding-top: 48px;' : '',
|
||||
!hideTabs && layout ? 'padding-top: 85px;' : '',
|
||||
hideTabs && !layout ? 'padding-top: 62px' : '',
|
||||
!hideTabs && !layout ? 'padding-top: 98px;' : ''
|
||||
]"
|
||||
>
|
||||
<router-view>
|
||||
<template #default="{ Component, route }">
|
||||
<el-scrollbar v-if="props.fixedHeader">
|
||||
<el-backtop title="回到顶部" target=".app-main .el-scrollbar__wrap">
|
||||
<backTop />
|
||||
</el-backtop>
|
||||
<transitionMain :route="route">
|
||||
<keep-alive
|
||||
v-if="keepAlive"
|
||||
:include="usePermissionStoreHook().cachePageList"
|
||||
>
|
||||
<component :is="Component" :key="route.fullPath" />
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.fullPath"
|
||||
class="main-content"
|
||||
/>
|
||||
</keep-alive>
|
||||
<component v-else :is="Component" :key="route.fullPath" />
|
||||
</transition>
|
||||
</template>
|
||||
</router-view>
|
||||
</el-scrollbar>
|
||||
<component
|
||||
v-else
|
||||
:is="Component"
|
||||
:key="route.fullPath"
|
||||
class="main-content"
|
||||
/>
|
||||
</transitionMain>
|
||||
</el-scrollbar>
|
||||
<div v-else>
|
||||
<transitionMain :route="route">
|
||||
<keep-alive
|
||||
v-if="keepAlive"
|
||||
:include="usePermissionStoreHook().cachePageList"
|
||||
>
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.fullPath"
|
||||
class="main-content"
|
||||
/>
|
||||
</keep-alive>
|
||||
<component
|
||||
v-else
|
||||
:is="Component"
|
||||
:key="route.fullPath"
|
||||
class="main-content"
|
||||
/>
|
||||
</transitionMain>
|
||||
</div>
|
||||
</template>
|
||||
</router-view>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -57,4 +135,14 @@ const transition = computed(() => {
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.app-main-nofixed-header {
|
||||
width: 100%;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
margin: 24px;
|
||||
}
|
||||
</style>
|
||||
|
@@ -78,6 +78,8 @@ function translationEn() {
|
||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
@click="translationCh"
|
||||
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||
><check /></el-icon
|
||||
>简体中文</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
@@ -86,6 +88,8 @@ function translationEn() {
|
||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
@click="translationEn"
|
||||
><el-icon class="check-en" v-show="locale === 'en'"
|
||||
><check /></el-icon
|
||||
>English</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
@@ -107,11 +111,13 @@ function translationEn() {
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<i
|
||||
<el-icon
|
||||
class="el-icon-setting"
|
||||
:title="$t('message.hssystemSet')"
|
||||
@click="onPanel"
|
||||
></i>
|
||||
>
|
||||
<Setting />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -191,8 +197,8 @@ function translationEn() {
|
||||
|
||||
.el-icon-setting {
|
||||
height: 48px;
|
||||
width: 40px;
|
||||
padding: 11px;
|
||||
width: 38px;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
align-items: center;
|
||||
@@ -218,6 +224,18 @@ function translationEn() {
|
||||
color: #606266;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
position: absolute;
|
||||
bottom: 13px;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.logout {
|
||||
|
@@ -1,33 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useEventListener, onClickOutside } from "@vueuse/core";
|
||||
import { onClickOutside } from "@vueuse/core";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
|
||||
let show = ref<Boolean>(false);
|
||||
const target = ref(null);
|
||||
onClickOutside(target, () => {
|
||||
onClickOutside(target, event => {
|
||||
if (event.clientX > target.value.offsetLeft) return;
|
||||
show.value = false;
|
||||
});
|
||||
|
||||
const addEventClick = (): void => {
|
||||
useEventListener("click", closeSidebar);
|
||||
};
|
||||
|
||||
const closeSidebar = (evt: any): void => {
|
||||
const parent = evt.target.closest(".right-panel");
|
||||
if (!parent) {
|
||||
show.value = false;
|
||||
window.removeEventListener("click", closeSidebar);
|
||||
}
|
||||
};
|
||||
|
||||
emitter.on("openPanel", () => {
|
||||
show.value = true;
|
||||
});
|
||||
|
||||
defineExpose({
|
||||
addEventClick
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -37,7 +22,9 @@ defineExpose({
|
||||
<div class="right-panel-items">
|
||||
<div class="project-configuration">
|
||||
<h3>项目配置</h3>
|
||||
<i class="el-icon-close" @click="show = !show"></i>
|
||||
<el-icon title="关闭配置" class="el-icon-close" @click="show = !show">
|
||||
<Close />
|
||||
</el-icon>
|
||||
</div>
|
||||
<div style="border-bottom: 1px solid #dcdfe6"></div>
|
||||
<slot />
|
||||
|
@@ -1,52 +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");
|
||||
|
||||
function toggleClass(flag: boolean, clsName: string, target?: HTMLElement) {
|
||||
const targetEl = target || document.body;
|
||||
let { className } = targetEl;
|
||||
@@ -55,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"
|
||||
@@ -141,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
|
||||
);
|
||||
case "vertical":
|
||||
toggleClass(true, isSelect, unref(verticalRef));
|
||||
debounce(setFalse([horizontalRef]), 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
|
||||
);
|
||||
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')"
|
||||
: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-dark' ? $style.isSelect : ''"
|
||||
ref="horizontalDarkDom"
|
||||
@click="setTheme('horizontal', 'dark')"
|
||||
<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>
|
||||
|
||||
<el-tooltip class="item" content="顶部菜单亮色模式" placement="bottom">
|
||||
<li
|
||||
:class="
|
||||
dataTheme.layout === 'horizontal-light' ? $style.isSelect : ''
|
||||
"
|
||||
ref="horizontalLightDom"
|
||||
@click="setTheme('horizontal', 'light')"
|
||||
>
|
||||
<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>
|
||||
|
||||
@@ -316,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;
|
||||
@@ -356,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%;
|
||||
@@ -387,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,7 +17,11 @@ const toggleClick = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="classes.container" @click="toggleClick">
|
||||
<div
|
||||
:class="classes.container"
|
||||
:title="props.isActive ? '点击折叠' : '点击展开'"
|
||||
@click="toggleClick"
|
||||
>
|
||||
<svg
|
||||
:class="['hamburger', props.isActive ? 'is-active' : '']"
|
||||
viewBox="0 0 1024 1024"
|
||||
|
@@ -15,6 +15,7 @@ import { algorithm } from "/@/utils/algorithm";
|
||||
import screenfull from "../screenfull/index.vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { storageSession } from "/@/utils/storage";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
import { deviceDetection } from "/@/utils/deviceDetection";
|
||||
import globalization from "/@/assets/svg/globalization.svg";
|
||||
import { usePermissionStoreHook } from "/@/store/modules/permission";
|
||||
@@ -117,7 +118,7 @@ onMounted(() => {
|
||||
<template>
|
||||
<div class="horizontal-header">
|
||||
<div class="horizontal-header-left" @click="backHome">
|
||||
<i class="fa fa-optin-monster"></i>
|
||||
<Icon svg :width="35" :height="35" content="team-iconlogo" />
|
||||
<h4>{{ title }}</h4>
|
||||
</div>
|
||||
<el-menu
|
||||
@@ -150,6 +151,8 @@ onMounted(() => {
|
||||
color: locale === 'zh' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
@click="translationCh"
|
||||
><el-icon class="check-zh" v-show="locale === 'zh'"
|
||||
><check /></el-icon
|
||||
>简体中文</el-dropdown-item
|
||||
>
|
||||
<el-dropdown-item
|
||||
@@ -158,6 +161,8 @@ onMounted(() => {
|
||||
color: locale === 'en' ? '#f4f4f5' : '#000'
|
||||
}"
|
||||
@click="translationEn"
|
||||
><el-icon class="check-en" v-show="locale === 'en'"
|
||||
><check /></el-icon
|
||||
>English</el-dropdown-item
|
||||
>
|
||||
</el-dropdown-menu>
|
||||
@@ -179,11 +184,13 @@ onMounted(() => {
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</el-dropdown>
|
||||
<i
|
||||
<el-icon
|
||||
class="el-icon-setting"
|
||||
:title="$t('message.hssystemSet')"
|
||||
@click="onPanel"
|
||||
></i>
|
||||
>
|
||||
<Setting />
|
||||
</el-icon>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -199,6 +206,18 @@ onMounted(() => {
|
||||
color: #606266;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.check-zh {
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 13px;
|
||||
}
|
||||
|
||||
.check-en {
|
||||
position: absolute;
|
||||
bottom: 13px;
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.logout {
|
||||
|
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { getCurrentInstance } from "vue";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
const props = defineProps({
|
||||
collapse: Boolean
|
||||
});
|
||||
@@ -18,8 +19,8 @@ const title =
|
||||
class="sidebar-logo-link"
|
||||
to="/"
|
||||
>
|
||||
<i class="fa fa-optin-monster"></i>
|
||||
<h1 class="sidebar-title">{{ title }}</h1>
|
||||
<Icon svg :width="35" :height="35" content="team-iconlogo" />
|
||||
<span class="sidebar-title">{{ title }}</span>
|
||||
</router-link>
|
||||
<router-link
|
||||
v-else
|
||||
@@ -28,8 +29,8 @@ const title =
|
||||
class="sidebar-logo-link"
|
||||
to="/"
|
||||
>
|
||||
<i class="fa fa-optin-monster"></i>
|
||||
<h1 class="sidebar-title">{{ title }}</h1>
|
||||
<Icon svg :width="35" :height="35" content="team-iconlogo" />
|
||||
<span class="sidebar-title">{{ title }}</span>
|
||||
</router-link>
|
||||
</transition>
|
||||
</div>
|
||||
@@ -39,28 +40,24 @@ const title =
|
||||
.sidebar-logo-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
height: 48px;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
|
||||
.sidebar-logo-link {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
margin-top: 5px;
|
||||
|
||||
.sidebar-title {
|
||||
display: inline-block;
|
||||
margin: 0;
|
||||
color: #1890ff;
|
||||
font-weight: 600;
|
||||
font-size: 20px;
|
||||
margin-top: 16px;
|
||||
margin-top: 10px;
|
||||
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.fa-optin-monster {
|
||||
font-size: 30px;
|
||||
color: #1890ff;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.collapse {
|
||||
|
@@ -1,9 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import path from "path";
|
||||
import { PropType, ref } from "vue";
|
||||
import { PropType, ref, nextTick, getCurrentInstance } from "vue";
|
||||
import { childrenType } from "../../types";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import Icon from "/@/components/ReIcon/src/Icon.vue";
|
||||
|
||||
const instance = getCurrentInstance().appContext.app.config.globalProperties;
|
||||
const menuMode = instance.$storage.layout?.layout === "vertical";
|
||||
const pureApp = useAppStoreHook();
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
type: Object as PropType<childrenType>
|
||||
@@ -19,6 +24,28 @@ const props = defineProps({
|
||||
});
|
||||
|
||||
const onlyOneChild: childrenType = ref(null);
|
||||
// 存放菜单是否存在showTooltip属性标识
|
||||
const hoverMenuMap = new WeakMap();
|
||||
// 存储菜单文本dom元素
|
||||
const menuTextRef = ref(null);
|
||||
|
||||
function hoverMenu(key) {
|
||||
// 如果当前菜单showTooltip属性已存在,退出计算
|
||||
if (hoverMenuMap.get(key)) return;
|
||||
|
||||
nextTick(() => {
|
||||
// 如果文本内容的整体宽度大于其可视宽度,则文本溢出
|
||||
menuTextRef.value?.scrollWidth > menuTextRef.value?.clientWidth
|
||||
? Object.assign(key, {
|
||||
showTooltip: true
|
||||
})
|
||||
: Object.assign(key, {
|
||||
showTooltip: false
|
||||
});
|
||||
|
||||
hoverMenuMap.set(key, true);
|
||||
});
|
||||
}
|
||||
|
||||
function hasOneShowingChild(
|
||||
children: childrenType[] = [],
|
||||
@@ -55,19 +82,51 @@ function resolvePath(routePath) {
|
||||
<el-menu-item
|
||||
:index="resolvePath(onlyOneChild.path)"
|
||||
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||
style="display: flex; align-items: center"
|
||||
>
|
||||
<i
|
||||
:class="
|
||||
onlyOneChild.meta.icon || (props.item.meta && props.item.meta.icon)
|
||||
"
|
||||
/>
|
||||
<el-icon v-show="props.item.meta.icon">
|
||||
<component
|
||||
:is="
|
||||
onlyOneChild.meta.icon || (props.item.meta && props.item.meta.icon)
|
||||
"
|
||||
></component>
|
||||
</el-icon>
|
||||
<template #title>
|
||||
<span>{{ $t(onlyOneChild.meta.title) }}</span>
|
||||
<Icon
|
||||
v-if="onlyOneChild.meta.extraIcon"
|
||||
:svg="onlyOneChild.meta.extraIcon.svg ? true : false"
|
||||
:content="`${onlyOneChild.meta.extraIcon.name}`"
|
||||
/>
|
||||
<div
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '' : '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
overflow: 'hidden'
|
||||
}"
|
||||
>
|
||||
<span v-if="!menuMode">{{ $t(onlyOneChild.meta.title) }}</span>
|
||||
<el-tooltip
|
||||
v-else
|
||||
placement="top"
|
||||
:offset="-10"
|
||||
:disabled="!onlyOneChild.showTooltip"
|
||||
>
|
||||
<template #content> {{ $t(onlyOneChild.meta.title) }} </template>
|
||||
<span
|
||||
ref="menuTextRef"
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '125px' : '',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}"
|
||||
@mouseover="hoverMenu(onlyOneChild)"
|
||||
>
|
||||
{{ $t(onlyOneChild.meta.title) }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<Icon
|
||||
v-if="onlyOneChild.meta.extraIcon"
|
||||
:svg="onlyOneChild.meta.extraIcon.svg ? true : false"
|
||||
:content="`${onlyOneChild.meta.extraIcon.name}`"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</template>
|
||||
@@ -79,8 +138,32 @@ function resolvePath(routePath) {
|
||||
popper-append-to-body
|
||||
>
|
||||
<template #title>
|
||||
<i :class="props.item.meta.icon"></i>
|
||||
<span>{{ $t(props.item.meta.title) }}</span>
|
||||
<el-icon v-show="props.item.meta.icon" :class="props.item.meta.icon">
|
||||
<component :is="props.item.meta && props.item.meta.icon"></component>
|
||||
</el-icon>
|
||||
<span v-if="!menuMode">{{ $t(props.item.meta.title) }}</span>
|
||||
<el-tooltip
|
||||
v-else
|
||||
placement="top"
|
||||
:offset="-10"
|
||||
:disabled="!pureApp.sidebar.opened || !props.item.showTooltip"
|
||||
>
|
||||
<template #content> {{ $t(props.item.meta.title) }} </template>
|
||||
<div
|
||||
ref="menuTextRef"
|
||||
:style="{
|
||||
width: pureApp.sidebar.opened ? '125px' : '',
|
||||
display: 'inline-block',
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis'
|
||||
}"
|
||||
@mouseover="hoverMenu(props.item)"
|
||||
>
|
||||
<span style="overflow: hidden; text-overflow: ellipsis">
|
||||
{{ $t(props.item.meta.title) }}
|
||||
</span>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<Icon
|
||||
v-if="props.item.meta.extraIcon"
|
||||
:svg="props.item.meta.extraIcon.svg ? true : false"
|
||||
|
@@ -68,12 +68,14 @@ onBeforeMount(() => {
|
||||
router
|
||||
:collapse-transition="false"
|
||||
mode="vertical"
|
||||
class="outer-most"
|
||||
@select="menuSelect"
|
||||
>
|
||||
<sidebar-item
|
||||
v-for="route in routeStore.wholeRoutes"
|
||||
:key="route.path"
|
||||
:item="route"
|
||||
class="outer-most"
|
||||
:base-path="route.path"
|
||||
/>
|
||||
</el-menu>
|
||||
|
@@ -482,14 +482,16 @@ onBeforeMount(() => {
|
||||
<router-link :to="item.path" @click="tagOnClick(item)">{{
|
||||
$t(item.meta.title)
|
||||
}}</router-link>
|
||||
<span
|
||||
<el-icon
|
||||
v-if="
|
||||
($route.path === item.path && index !== 0) ||
|
||||
(index === activeIndex && index !== 0)
|
||||
"
|
||||
class="el-icon-close"
|
||||
@click="deleteMenu(item)"
|
||||
></span>
|
||||
>
|
||||
<CloseBold />
|
||||
</el-icon>
|
||||
<div
|
||||
:ref="'schedule' + index"
|
||||
v-if="showModel !== 'card'"
|
||||
@@ -520,15 +522,19 @@ onBeforeMount(() => {
|
||||
<!-- 右侧功能按钮 -->
|
||||
<ul class="right-button">
|
||||
<li>
|
||||
<i
|
||||
<el-icon
|
||||
:title="$t('message.hsrefreshRoute')"
|
||||
class="el-icon-refresh-right rotate"
|
||||
@click="onFresh"
|
||||
></i>
|
||||
>
|
||||
<RefreshRight />
|
||||
</el-icon>
|
||||
</li>
|
||||
<li>
|
||||
<el-dropdown trigger="click" placement="bottom-end">
|
||||
<i class="el-icon-arrow-down"></i>
|
||||
<el-icon>
|
||||
<ArrowDown />
|
||||
</el-icon>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item
|
||||
@@ -628,6 +634,7 @@ onBeforeMount(() => {
|
||||
font-size: 10px;
|
||||
color: #1890ff;
|
||||
cursor: pointer;
|
||||
transform: fontsize3s;
|
||||
|
||||
&:hover {
|
||||
border-radius: 50%;
|
||||
|
@@ -1,32 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { routerArrays } from "./types";
|
||||
export default {
|
||||
computed: {
|
||||
layout() {
|
||||
if (!this.$storage.layout) {
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
this.$storage.layout = { layout: "vertical-dark" };
|
||||
}
|
||||
if (
|
||||
!this.$storage.routesInStorage ||
|
||||
this.$storage.routesInStorage.length === 0
|
||||
) {
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
this.$storage.routesInStorage = routerArrays;
|
||||
}
|
||||
if (!this.$storage.locale) {
|
||||
// eslint-disable-next-line
|
||||
this.$storage.locale = { locale: "zh" };
|
||||
useI18n().locale.value = "zh";
|
||||
}
|
||||
return this.$storage?.layout.layout;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
h,
|
||||
ref,
|
||||
unref,
|
||||
reactive,
|
||||
@@ -34,13 +8,15 @@ import {
|
||||
onMounted,
|
||||
watchEffect,
|
||||
onBeforeMount,
|
||||
defineComponent,
|
||||
getCurrentInstance
|
||||
} from "vue";
|
||||
import { setType } from "./types";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { routerArrays } from "./types";
|
||||
import { emitter } from "/@/utils/mitt";
|
||||
import { useEventListener } from "@vueuse/core";
|
||||
import { storageLocal } from "/@/utils/storage";
|
||||
import backTop from "/@/assets/svg/back_top.svg";
|
||||
import { useAppStoreHook } from "/@/store/modules/app";
|
||||
import fullScreen from "/@/assets/svg/full_screen.svg";
|
||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
|
||||
@@ -53,14 +29,45 @@ import setting from "./components/setting/index.vue";
|
||||
import Vertical from "./components/sidebar/vertical.vue";
|
||||
import Horizontal from "./components/sidebar/horizontal.vue";
|
||||
|
||||
const instance = getCurrentInstance().appContext.app.config.globalProperties;
|
||||
const hiddenSideBar = ref(instance.$config?.HiddenSideBar);
|
||||
const pureSetting = useSettingStoreHook();
|
||||
|
||||
const instance =
|
||||
getCurrentInstance().appContext.app.config.globalProperties.$storage;
|
||||
|
||||
const hiddenSideBar = ref(
|
||||
getCurrentInstance().appContext.config.globalProperties.$config?.HiddenSideBar
|
||||
);
|
||||
// 清空缓存后从serverConfig.json读取默认配置并赋值到storage中
|
||||
const layout = computed(() => {
|
||||
// 路由
|
||||
if (
|
||||
!instance.$storage.routesInStorage ||
|
||||
instance.$storage.routesInStorage.length === 0
|
||||
) {
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
instance.$storage.routesInStorage = routerArrays;
|
||||
}
|
||||
// 国际化
|
||||
if (!instance.$storage.locale) {
|
||||
// eslint-disable-next-line
|
||||
instance.$storage.locale = { locale: instance.$config?.Locale ?? "zh" };
|
||||
useI18n().locale.value = instance.$config?.Locale ?? "zh";
|
||||
}
|
||||
// 导航
|
||||
if (!instance.$storage.layout) {
|
||||
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
|
||||
instance.$storage.layout = {
|
||||
layout: instance.$config?.Layout ?? "vertical",
|
||||
theme: instance.$config?.Theme ?? "default"
|
||||
};
|
||||
}
|
||||
// 灰色模式、色弱模式、隐藏标签页
|
||||
if (!instance.$storage.sets) {
|
||||
// eslint-disable-next-line
|
||||
instance.$storage.sets = {
|
||||
grey: instance.$config?.Grey ?? false,
|
||||
weak: instance.$config?.Weak ?? false,
|
||||
hideTabs: instance.$config?.HideTabs ?? false
|
||||
};
|
||||
}
|
||||
return instance.$storage?.layout.layout;
|
||||
});
|
||||
|
||||
const set: setType = reactive({
|
||||
sidebar: computed(() => {
|
||||
@@ -82,6 +89,10 @@ const set: setType = reactive({
|
||||
withoutAnimation: set.sidebar.withoutAnimation,
|
||||
mobile: set.device === "mobile"
|
||||
};
|
||||
}),
|
||||
|
||||
hideTabs: computed(() => {
|
||||
return instance.$storage?.sets.hideTabs;
|
||||
})
|
||||
});
|
||||
|
||||
@@ -90,11 +101,11 @@ const handleClickOutside = (params: boolean) => {
|
||||
};
|
||||
|
||||
function setTheme(layoutModel: string) {
|
||||
let { layout } = storageLocal.getItem("responsive-layout");
|
||||
let theme = layout.match(/-(.*)/)[1];
|
||||
window.document.body.setAttribute("data-layout", layoutModel);
|
||||
window.document.body.setAttribute("data-theme", theme);
|
||||
instance.layout = { layout: `${layoutModel}-${theme}` };
|
||||
window.document.body.setAttribute("layout", layoutModel);
|
||||
instance.$storage.layout = {
|
||||
layout: `${layoutModel}`,
|
||||
theme: instance.$storage.layout?.theme
|
||||
};
|
||||
}
|
||||
|
||||
// 监听容器
|
||||
@@ -141,6 +152,49 @@ onMounted(() => {
|
||||
onBeforeMount(() => {
|
||||
useEventListener("resize", $_resizeHandler);
|
||||
});
|
||||
|
||||
const layoutHeader = defineComponent({
|
||||
render() {
|
||||
return h(
|
||||
"div",
|
||||
{
|
||||
class: { "fixed-header": set.fixedHeader },
|
||||
style: [
|
||||
set.hideTabs && layout.value.includes("horizontal")
|
||||
? "box-shadow: 0 1px 4px rgb(0 21 41 / 8%);"
|
||||
: ""
|
||||
]
|
||||
},
|
||||
{
|
||||
default: () => [
|
||||
!hiddenSideBar.value && layout.value.includes("vertical")
|
||||
? h(navbar)
|
||||
: h("div"),
|
||||
!hiddenSideBar.value && layout.value.includes("horizontal")
|
||||
? h(Horizontal)
|
||||
: h("div"),
|
||||
h(
|
||||
tag,
|
||||
{},
|
||||
{
|
||||
default: () => [
|
||||
h(
|
||||
"span",
|
||||
{ onClick: onFullScreen },
|
||||
{
|
||||
default: () => [
|
||||
!hiddenSideBar.value ? h(fullScreen) : h(exitScreen)
|
||||
]
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
)
|
||||
]
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -156,20 +210,21 @@ onBeforeMount(() => {
|
||||
/>
|
||||
<Vertical v-show="!hiddenSideBar && layout.includes('vertical')" />
|
||||
<div :class="['main-container', hiddenSideBar ? 'main-hidden' : '']">
|
||||
<div :class="{ 'fixed-header': set.fixedHeader }">
|
||||
<!-- 顶部导航栏 -->
|
||||
<navbar v-show="!hiddenSideBar && layout.includes('vertical')" />
|
||||
<!-- tabs标签页 -->
|
||||
<Horizontal v-show="!hiddenSideBar && layout.includes('horizontal')" />
|
||||
<tag>
|
||||
<span @click="onFullScreen">
|
||||
<fullScreen v-if="!hiddenSideBar" />
|
||||
<exitScreen v-else />
|
||||
</span>
|
||||
</tag>
|
||||
<div v-if="set.fixedHeader">
|
||||
<layout-header />
|
||||
<!-- 主体内容 -->
|
||||
<app-main :fixed-header="set.fixedHeader" />
|
||||
</div>
|
||||
<!-- 主体内容 -->
|
||||
<app-main />
|
||||
<el-scrollbar v-else>
|
||||
<el-backtop
|
||||
title="回到顶部"
|
||||
target=".main-container .el-scrollbar__wrap"
|
||||
><backTop />
|
||||
</el-backtop>
|
||||
<layout-header />
|
||||
<!-- 主体内容 -->
|
||||
<app-main :fixed-header="set.fixedHeader" />
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<!-- 系统设置 -->
|
||||
<setting />
|
||||
|
12
src/layout/theme/auroraGreen-vars.scss
Normal file
12
src/layout/theme/auroraGreen-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 极光绿
|
||||
|
||||
$subMenuActiveText: #fff;
|
||||
$menuBg: #0b1e15;
|
||||
$menuHover: #60ac80;
|
||||
$subMenuBg: #000;
|
||||
$subMenuActiveBg: #60ac80;
|
||||
$navTextColor: #7a80b4;
|
||||
$menuText: #7a80b4;
|
||||
$sidebarLogo: #112f21;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #60ac80;
|
24
src/layout/theme/default-vars.scss
Normal file
24
src/layout/theme/default-vars.scss
Normal file
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
*此scss变量文件作为multipleScopeVars去编译时,会自动移除!default以达到变量提升
|
||||
*同时此scss变量文件作为默认主题变量文件,被其他.scss通过 @import 时,必需 !default
|
||||
*/
|
||||
|
||||
// 暗雅(默认)
|
||||
|
||||
// 菜单选中后字体样式
|
||||
$subMenuActiveText: #fff !default;
|
||||
//菜单背景
|
||||
$menuBg: #001529 !default;
|
||||
// 鼠标覆盖到菜单时的背景
|
||||
$menuHover: #4091f7 !default;
|
||||
// 子菜单背景
|
||||
$subMenuBg: #0f0303 !default;
|
||||
// 有无子集的激活菜单背景
|
||||
$subMenuActiveBg: #4091f7 !default;
|
||||
$navTextColor: #fff !default;
|
||||
$menuText: rgba(254, 254, 254, 0.65) !default;
|
||||
// logo背景颜色
|
||||
$sidebarLogo: #002140 !default;
|
||||
// 鼠标覆盖到菜单时的字体颜色
|
||||
$menuTitleHover: #fff !default;
|
||||
$menuActiveBefore: #4091f7 !default;
|
12
src/layout/theme/dusk-vars.scss
Normal file
12
src/layout/theme/dusk-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 薄暮
|
||||
|
||||
$subMenuActiveText: #fff;
|
||||
$menuBg: #2a0608;
|
||||
$menuHover: #e13c39;
|
||||
$subMenuBg: #000;
|
||||
$subMenuActiveBg: #e13c39;
|
||||
$navTextColor: red;
|
||||
$menuText: rgba(254, 254, 254, 0.651);
|
||||
$sidebarLogo: #42090c;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #e13c39;
|
11
src/layout/theme/light-vars.scss
Normal file
11
src/layout/theme/light-vars.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
// 明亮
|
||||
$subMenuActiveText: #409eff;
|
||||
$menuBg: #fff;
|
||||
$menuHover: #e0ebf6;
|
||||
$subMenuBg: #fff;
|
||||
$subMenuActiveBg: #e0ebf6;
|
||||
$navTextColor: #7a80b4;
|
||||
$menuText: #7a80b4;
|
||||
$sidebarLogo: #fff;
|
||||
$menuTitleHover: #000;
|
||||
$menuActiveBefore: #4091f7;
|
12
src/layout/theme/mingQing-vars.scss
Normal file
12
src/layout/theme/mingQing-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 明青
|
||||
|
||||
$subMenuActiveText: #fff;
|
||||
$menuBg: #032121;
|
||||
$menuHover: #59bfc1;
|
||||
$subMenuBg: #000;
|
||||
$subMenuActiveBg: #59bfc1;
|
||||
$navTextColor: #7a80b4;
|
||||
$menuText: #7a80b4;
|
||||
$sidebarLogo: #053434;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #59bfc1;
|
12
src/layout/theme/pink-vars.scss
Normal file
12
src/layout/theme/pink-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 粉红
|
||||
|
||||
$subMenuActiveText: #fff;
|
||||
$menuBg: #28081a;
|
||||
$menuHover: #d84493;
|
||||
$subMenuBg: #000;
|
||||
$subMenuActiveBg: #d84493;
|
||||
$navTextColor: #7a80b4;
|
||||
$menuText: #7a80b4;
|
||||
$sidebarLogo: #3f0d29;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #d84493;
|
12
src/layout/theme/saucePurple-vars.scss
Normal file
12
src/layout/theme/saucePurple-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 酱紫
|
||||
|
||||
$subMenuActiveText: #fff;
|
||||
$menuBg: #130824;
|
||||
$menuHover: #693ac9;
|
||||
$subMenuBg: #000;
|
||||
$subMenuActiveBg: #693ac9;
|
||||
$navTextColor: #7a80b4;
|
||||
$menuText: #7a80b4;
|
||||
$sidebarLogo: #1f0c38;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #693ac9;
|
12
src/layout/theme/volcano-vars.scss
Normal file
12
src/layout/theme/volcano-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 火山
|
||||
|
||||
$subMenuActiveText: #fff;
|
||||
$menuBg: #2b0e05;
|
||||
$menuHover: #e85f33;
|
||||
$subMenuBg: #0f0603;
|
||||
$subMenuActiveBg: #e85f33;
|
||||
$navTextColor: #fff;
|
||||
$menuText: rgba(254, 254, 254, 0.65);
|
||||
$sidebarLogo: #441708;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #e85f33;
|
12
src/layout/theme/yellow-vars.scss
Normal file
12
src/layout/theme/yellow-vars.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
// 黄色
|
||||
|
||||
$subMenuActiveText: #d25f00;
|
||||
$menuBg: #2b2503;
|
||||
$menuHover: #f6da4d;
|
||||
$subMenuBg: #0f0603;
|
||||
$subMenuActiveBg: #f6da4d;
|
||||
$navTextColor: #fff;
|
||||
$menuText: rgba(254, 254, 254, 0.65);
|
||||
$sidebarLogo: #443b05;
|
||||
$menuTitleHover: #fff;
|
||||
$menuActiveBefore: #f6da4d;
|
@@ -47,6 +47,7 @@ export interface setType {
|
||||
withoutAnimation: boolean;
|
||||
mobile: boolean;
|
||||
};
|
||||
hideTabs: boolean;
|
||||
}
|
||||
|
||||
export type childrenType = {
|
||||
@@ -62,4 +63,10 @@ export type childrenType = {
|
||||
name?: string;
|
||||
};
|
||||
};
|
||||
showTooltip?: boolean;
|
||||
};
|
||||
|
||||
export type themeColorsType = {
|
||||
rgb: string;
|
||||
themeColor: string;
|
||||
};
|
||||
|
Reference in New Issue
Block a user