mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-09 13:53:38 +08:00
refactor: theme
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
<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";
|
||||
@@ -99,36 +98,20 @@ function onChange({ 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
|
||||
);
|
||||
const verticalRef = templateRef<HTMLElement | null>("verticalRef", null);
|
||||
const horizontalRef = templateRef<HTMLElement | null>("horizontalRef", null);
|
||||
|
||||
let dataTheme =
|
||||
ref(storageLocal.getItem("responsive-layout")) ||
|
||||
ref({
|
||||
layout: "horizontal-dark"
|
||||
layout: "vertical"
|
||||
});
|
||||
|
||||
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);
|
||||
let layout = unref(dataTheme).layout;
|
||||
window.document.body.setAttribute("layout", layout);
|
||||
}
|
||||
|
||||
// 侧边栏Logo
|
||||
@@ -147,42 +130,21 @@ 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}` };
|
||||
function setTheme(layout: string) {
|
||||
dataTheme.value.layout = `${layout}`;
|
||||
window.document.body.setAttribute("layout", layout);
|
||||
instance.layout = { layout: `${layout}` };
|
||||
useAppStoreHook().setLayout(layout);
|
||||
}
|
||||
</script>
|
||||
@@ -190,23 +152,12 @@ function setTheme(layout: string, theme: string) {
|
||||
<template>
|
||||
<panel>
|
||||
<el-divider>主题风格</el-divider>
|
||||
<ul class="theme-stley">
|
||||
<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')"
|
||||
>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</li>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip class="item" content="左侧菜单亮色模式" placement="bottom">
|
||||
<li
|
||||
:class="dataTheme.layout === 'vertical-light' ? $style.isSelect : ''"
|
||||
ref="verticalLightDom"
|
||||
@click="setTheme('vertical', 'light')"
|
||||
:class="dataTheme.layout === 'vertical' ? $style.isSelect : ''"
|
||||
ref="verticalRef"
|
||||
@click="setTheme('vertical')"
|
||||
>
|
||||
<div></div>
|
||||
<div></div>
|
||||
@@ -215,27 +166,19 @@ function setTheme(layout: string, theme: string) {
|
||||
|
||||
<el-tooltip class="item" content="顶部菜单暗色模式" placement="bottom">
|
||||
<li
|
||||
:class="dataTheme.layout === 'horizontal-dark' ? $style.isSelect : ''"
|
||||
ref="horizontalDarkDom"
|
||||
@click="setTheme('horizontal', 'dark')"
|
||||
:class="dataTheme.layout === 'horizontal' ? $style.isSelect : ''"
|
||||
ref="horizontalRef"
|
||||
@click="setTheme('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')"
|
||||
>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</li>
|
||||
</el-tooltip>
|
||||
<el-divider>主题色</el-divider>
|
||||
<ul>
|
||||
<li>11</li>
|
||||
</ul>
|
||||
|
||||
<el-divider>界面显示</el-divider>
|
||||
@@ -322,10 +265,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 +305,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,17 +314,6 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,7 +16,6 @@ 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 { useAppStoreHook } from "/@/store/modules/app";
|
||||
import fullScreen from "/@/assets/svg/full_screen.svg";
|
||||
import exitScreen from "/@/assets/svg/exit_screen.svg";
|
||||
@@ -83,11 +82,8 @@ 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.layout = { layout: `${layoutModel}` };
|
||||
}
|
||||
|
||||
// 监听容器
|
||||
|
||||
17
src/layout/theme/default-vars.scss
Normal file
17
src/layout/theme/default-vars.scss
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
*此scss变量文件作为multipleScopeVars去编译时,会自动移除!default以达到变量提升
|
||||
*同时此scss变量文件作为默认主题变量文件,被其他.scss通过 @import 时,必需 !default
|
||||
*/
|
||||
|
||||
// 菜单选中后字体样式
|
||||
$subMenuActiveText: #f4f4f5 !default;
|
||||
//菜单背景
|
||||
$menuBg: #1b2a47 !default;
|
||||
// 鼠标覆盖菜单时的背景
|
||||
$menuHover: #2a395b !default;
|
||||
// 子菜单背景
|
||||
$subMenuBg: #1f2d3d !default;
|
||||
// 鼠标覆盖子菜单时的背景
|
||||
$subMenuHover: #001528 !default;
|
||||
$navTextColor: #fff !default;
|
||||
$menuText: #7a80b4;
|
||||
19
src/layout/theme/index.ts
Normal file
19
src/layout/theme/index.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
export const toggleTheme = (scopeName = "theme-default") => {
|
||||
let styleLink: any = document.getElementById("theme-button");
|
||||
if (styleLink) {
|
||||
// 假如存在id为theme-button 的link标签,直接修改其href
|
||||
styleLink.href = `/${scopeName}.css`;
|
||||
// 注:如果是removeCssScopeName:true移除了主题文件的权重类名,就可以不用修改className 操作
|
||||
document.documentElement.className = scopeName;
|
||||
} else {
|
||||
// 不存在的话,则新建一个
|
||||
styleLink = document.createElement("link");
|
||||
styleLink.type = "text/css";
|
||||
styleLink.rel = "stylesheet";
|
||||
styleLink.id = "theme-button";
|
||||
styleLink.href = `/${scopeName}.css`;
|
||||
// 注:如果是removeCssScopeName:true移除了主题文件的权重类名,就可以不用修改className 操作
|
||||
document.documentElement.className = scopeName;
|
||||
document.head.append(styleLink);
|
||||
}
|
||||
};
|
||||
7
src/layout/theme/light-vars.scss
Normal file
7
src/layout/theme/light-vars.scss
Normal file
@@ -0,0 +1,7 @@
|
||||
$subMenuActiveText: #409eff;
|
||||
$menuBg: #fff;
|
||||
$menuHover: #e0ebf6;
|
||||
$subMenuBg: #fff;
|
||||
$subMenuHover: #e0ebf6;
|
||||
$navTextColor: #7a80b4;
|
||||
$menuText: #7a80b4;
|
||||
@@ -37,6 +37,9 @@ import {
|
||||
ElBacktop
|
||||
} from "element-plus";
|
||||
|
||||
// https://element-plus.org/zh-CN/component/icon.html
|
||||
import { Menu } from "@element-plus/icons";
|
||||
|
||||
const components = [
|
||||
ElTag,
|
||||
ElAffix,
|
||||
@@ -71,7 +74,8 @@ const components = [
|
||||
ElRadioGroup,
|
||||
ElDescriptions,
|
||||
ElDescriptionsItem,
|
||||
ElBacktop
|
||||
ElBacktop,
|
||||
Menu
|
||||
];
|
||||
|
||||
const plugins = [ElLoading];
|
||||
|
||||
@@ -21,9 +21,7 @@ export const useAppStore = defineStore({
|
||||
: true,
|
||||
withoutAnimation: false
|
||||
},
|
||||
layout:
|
||||
storageLocal.getItem("responsive-layout")?.layout.match(/(.*)-/)[1] ??
|
||||
"vertical",
|
||||
layout: storageLocal.getItem("responsive-layout")?.layout ?? "vertical",
|
||||
device: deviceDetection() ? "mobile" : "desktop"
|
||||
}),
|
||||
getters: {
|
||||
|
||||
@@ -1,17 +1,8 @@
|
||||
@import "../layout/theme/default-vars.scss";
|
||||
|
||||
@mixin merge-style(
|
||||
// 菜单选中后字体样式
|
||||
$subMenuActiveText,
|
||||
//菜单背景
|
||||
$menuBg,
|
||||
// 鼠标覆盖菜单时的背景
|
||||
$menuHover,
|
||||
// 子菜单背景
|
||||
$subMenuBg,
|
||||
// 鼠标覆盖子菜单时的背景
|
||||
$subMenuHover,
|
||||
// vertical模式下主体内容距离网页文档左侧的距离
|
||||
$sideBarWidth,
|
||||
$navTextColor
|
||||
$sideBarWidth
|
||||
) {
|
||||
$menuText: #7a80b4;
|
||||
$menuActiveText: #7a80b4;
|
||||
@@ -72,7 +63,7 @@
|
||||
|
||||
.sidebar-container {
|
||||
transition: width 0.28s;
|
||||
width: $sideBarWidth;
|
||||
width: $sideBarWidth !important;
|
||||
background-color: $menuBg;
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
@@ -211,14 +202,14 @@
|
||||
display: flex;
|
||||
min-width: 280px;
|
||||
align-items: center;
|
||||
color: $navTextColor;
|
||||
color: $navTextColor !important;
|
||||
justify-content: flex-end;
|
||||
|
||||
.screen-full {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: $menuHover;
|
||||
background: $menuHover !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,13 +273,13 @@
|
||||
|
||||
.el-menu-item,
|
||||
.el-sub-menu__title {
|
||||
color: $menuText;
|
||||
color: $menuText !important;
|
||||
}
|
||||
|
||||
.submenu-title-noDropdown,
|
||||
.el-sub-menu__title {
|
||||
height: 60px;
|
||||
background: $menuBg;
|
||||
background: $menuBg !important;
|
||||
|
||||
&:hover {
|
||||
background-color: $menuHover !important;
|
||||
@@ -529,7 +520,7 @@
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin-left: 0 !important;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.sidebar-container {
|
||||
@@ -554,10 +545,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
body[data-layout="vertical"] {
|
||||
body[layout="vertical"] {
|
||||
$sideBarWidth: 210px;
|
||||
@include merge-style($sideBarWidth);
|
||||
|
||||
.hideSidebar {
|
||||
.fixed-header {
|
||||
width: calc(100% - 54px) !important;
|
||||
width: calc(100% - 54px);
|
||||
transition: width 0.28s;
|
||||
}
|
||||
|
||||
@@ -566,7 +560,7 @@ body[data-layout="vertical"] {
|
||||
}
|
||||
|
||||
.main-container {
|
||||
margin-left: 54px !important;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.submenu-title-noDropdown {
|
||||
@@ -605,36 +599,39 @@ body[data-layout="vertical"] {
|
||||
}
|
||||
}
|
||||
|
||||
body[data-layout="horizontal"] {
|
||||
body[layout="horizontal"] {
|
||||
$sideBarWidth: 0;
|
||||
@include merge-style($sideBarWidth);
|
||||
|
||||
.fixed-header {
|
||||
width: 100% !important;
|
||||
width: 100%;
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// vertical模式下不隐藏标签页
|
||||
body[data-layout="vertical"][data-show-tag="false"] {
|
||||
body[layout="vertical"][data-show-tag="false"] {
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
// vertical模式下隐藏标签页
|
||||
body[data-layout="vertical"][data-show-tag="true"] {
|
||||
body[layout="vertical"][data-show-tag="true"] {
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 48px;
|
||||
}
|
||||
}
|
||||
|
||||
// horizontal模式下不隐藏标签页
|
||||
body[data-layout="horizontal"][data-show-tag="false"] {
|
||||
body[layout="horizontal"][data-show-tag="false"] {
|
||||
.fixed-header + .app-main {
|
||||
padding-top: 98px;
|
||||
}
|
||||
}
|
||||
|
||||
// horizontal模式下隐藏标签页
|
||||
body[data-layout="horizontal"][data-show-tag="true"] {
|
||||
body[layout="horizontal"][data-show-tag="true"] {
|
||||
.fixed-header {
|
||||
box-shadow: 0 1px 4px rgb(0 21 41 / 8%);
|
||||
}
|
||||
@@ -643,87 +640,3 @@ body[data-layout="horizontal"][data-show-tag="true"] {
|
||||
padding-top: 62px;
|
||||
}
|
||||
}
|
||||
|
||||
// vertical模式下暗色主题
|
||||
body[data-layout="vertical"][data-theme="dark"] {
|
||||
$subMenuActiveText: #f4f4f5;
|
||||
$menuBg: #1b2a47;
|
||||
$menuHover: #2a395b;
|
||||
$subMenuBg: #1f2d3d;
|
||||
$subMenuHover: #001528;
|
||||
$sideBarWidth: 210px;
|
||||
$navTextColor: #fff;
|
||||
|
||||
@include merge-style(
|
||||
$subMenuActiveText,
|
||||
$menuBg,
|
||||
$menuHover,
|
||||
$subMenuBg,
|
||||
$subMenuHover,
|
||||
$sideBarWidth,
|
||||
$navTextColor
|
||||
);
|
||||
}
|
||||
|
||||
// vertical模式下亮色主题
|
||||
body[data-layout="vertical"][data-theme="light"] {
|
||||
$subMenuActiveText: #409eff;
|
||||
$menuBg: #fff;
|
||||
$menuHover: #e0ebf6;
|
||||
$subMenuBg: #fff;
|
||||
$subMenuHover: #e0ebf6;
|
||||
$sideBarWidth: 210px;
|
||||
$navTextColor: #7a80b4;
|
||||
|
||||
@include merge-style(
|
||||
$subMenuActiveText,
|
||||
$menuBg,
|
||||
$menuHover,
|
||||
$subMenuBg,
|
||||
$subMenuHover,
|
||||
$sideBarWidth,
|
||||
$navTextColor
|
||||
);
|
||||
}
|
||||
|
||||
// horizontal模式下暗色主题
|
||||
body[data-layout="horizontal"][data-theme="dark"] {
|
||||
$subMenuActiveText: #f4f4f5;
|
||||
$menuBg: #1b2a47;
|
||||
$menuHover: #2a395b;
|
||||
$subMenuBg: #1f2d3d;
|
||||
$subMenuHover: #001528;
|
||||
$sideBarWidth: 0;
|
||||
$navTextColor: #fff;
|
||||
|
||||
@include merge-style(
|
||||
$subMenuActiveText,
|
||||
$menuBg,
|
||||
$menuHover,
|
||||
$subMenuBg,
|
||||
$subMenuHover,
|
||||
$sideBarWidth,
|
||||
$navTextColor
|
||||
);
|
||||
}
|
||||
|
||||
// horizontal模式下亮色主题
|
||||
body[data-layout="horizontal"][data-theme="light"] {
|
||||
$subMenuActiveText: #409eff;
|
||||
$menuBg: #fff;
|
||||
$menuHover: #e0ebf6;
|
||||
$subMenuBg: #fff;
|
||||
$subMenuHover: #e0ebf6;
|
||||
$sideBarWidth: 0;
|
||||
$navTextColor: #7a80b4;
|
||||
|
||||
@include merge-style(
|
||||
$subMenuActiveText,
|
||||
$menuBg,
|
||||
$menuHover,
|
||||
$subMenuBg,
|
||||
$subMenuHover,
|
||||
$sideBarWidth,
|
||||
$navTextColor
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user