menu.js
import Vue from "vue";
const store = Vue.observable({
themeList: [{
name: "default",
color: "#6c97e5",
shadow: "#6c97e599"
},
{
name: "caring",
color: "#3c62ac",
shadow: "#3c62ac99"
}
],
theme: "default",
init() {
const theme = "default";
store.changeTheme(theme);
},
changeTheme(theme) {
store.theme = theme;
changeElementUITheme();
},
});
export default store;
const version = require("element-ui/package.json").version;
const originalColor = "#409EFF";
let chalk = "";
const changeElementUITheme = async () => {
document.querySelector("body").setAttribute("theme", store.theme);
const theme = store.themeList.find((theme) => theme.name === store.theme);
const oldVal = chalk ? theme.color : originalColor;
const themeCluster = getThemeCluster(theme.color.replace("#", ""));
const originalCluster = getThemeCluster(oldVal.replace("#", ""));
const getHandler = (id) => {
return () => {
const originalCluster = getThemeCluster(originalColor.replace("#", ""));
const newStyle = updateStyle(chalk, originalCluster, themeCluster);
let styleTag = document.getElementById(id);
if (!styleTag) {
styleTag = document.createElement("style");
styleTag.setAttribute("id", id);
document.head.appendChild(styleTag);
}
styleTag.innerText = newStyle;
};
};
if (!chalk) {
const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`;
await getCSSString(url);
}
const chalkHandler = getHandler("chalk-style");
chalkHandler();
const styles = [].slice.call(document.querySelectorAll("style")).filter((style) => {
const text = style.innerText;
return new RegExp(oldVal, "i").test(text) && !/Chalk Variables/.test(text);
});
styles.forEach((style) => {
const {
innerText
} = style;
if (typeof innerText !== "string") {
return;
}
style.innerText = updateStyle(innerText, originalCluster, themeCluster);
});
};
const updateStyle = (style, oldCluster, newCluster) => {
let newStyle = style;
oldCluster.forEach((color, index) => {
newStyle = newStyle.replace(new RegExp(color, "ig"), newCluster[index]);
});
return newStyle;
};
const getCSSString = (url) => {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
chalk = xhr.responseText.replace(/@font-face{[^}]+}/, "");
resolve();
}
};
xhr.open("GET", url);
xhr.send();
});
};
const getThemeCluster = (theme) => {
const tintColor = (color, tint) => {
let red = parseInt(color.slice(0, 2), 16);
let green = parseInt(color.slice(2, 4), 16);
let blue = parseInt(color.slice(4, 6), 16);
if (tint === 0) {
// when primary color is in its rgb space
return [red, green, blue].join(",");
} else {
red += Math.round(tint * (255 - red));
green += Math.round(tint * (255 - green));
blue += Math.round(tint * (255 - blue));
red = red.toString(16);
green = green.toString(16);
blue = blue.toString(16);
return `#${red}${green}${blue}`;
}
};
const shadeColor = (color, shade) => {
let red = parseInt(color.slice(0, 2), 16);
let green = parseInt(color.slice(2, 4), 16);
let blue = parseInt(color.slice(4, 6), 16);
red = Math.round((1 - shade) * red);
green = Math.round((1 - shade) * green);
blue = Math.round((1 - shade) * blue);
red = red.toString(16);
green = green.toString(16);
blue = blue.toString(16);
return `#${red}${green}${blue}`;
};
const clusters = [theme];
for (let i = 0; i <= 9; i++) {
clusters.push(tintColor(theme, Number((i / 10).toFixed(2))));
}
clusters.push(shadeColor(theme, 0.1));
return clusters;
};
scss
[theme="default"] {
--main-background: linear-gradient(135deg, #4379E5, #67a2ff 36%, #6690ec 61%, #2c3479 100%);
--main-tag-background: linear-gradient(135deg, #749aff, #5f8fdb 35%, #6b88d2 73%, #414a9e);
--meun-text-height: 35px;
--meun-text-active-height: 30px;
--meun-active-color: #647EC9;
--tags-view-container-background: transparent;
--tags-view-border: none;
--tags-view-active-border: none;
--z-header-background-color: #fff;
--app-wrapper-bgColor: #eaeef4;
--ZmoreSearch-label-fontSize: 12px;
--ZmoreSearch-el-input-height: 26px;
--el-submenu__title-fonSize: 13px;
--el-menu-item--height: 35px;
--el-menu-item-is-active-height: 35px;
--svg-icon-fontSize: 13px;
--app-main-height: calc(100vh - 60px);
--setHeadTableMain-height: calc(100% - 60px);
--app-minWidth: 1440px;
--el-table__body-wrapper-height: calc(100% - 60px);
--table-list--table-height:500px;
--one-height:26px;
}
[theme="caring"] {
--main-background: linear-gradient(135deg, #3656b2 1%, #184f8c 30%, #1d4293 63%, #111b71 100%);
;
--main-tag-background: #3c62ac;
--meun-text-height: 35px;
--meun-text-active-height: 30px;
--main-background-color: #3c62ac;
--main-font-color: #3c62ac;
--main-border-color: #3c62ac;
--meun-active-color: #2d4570;
--tags-view-container-background: white;
--tags-view-border: 1px solid #c7c8cc;
--tags-view-active-border: none;
--z-header-background-color: #3c62ac;
--app-wrapper-bgColor: #fff;
--ZmoreSearch-label-fontSize: 18px;
--ZmoreSearch-el-input-height: 40px;
--input-fontSize: 16px;
--button-border-color: #575655;
--button-height: 32px;
--color-disabled-text: #000000;
--tags-view-item: 16px;
--el-submenu__title-fonSize: 16px;
--el-menu-item--height: 50px;
--el-menu-item-is-active-height: 45px;
--svg-icon-fontSize: 20px;
--app-main-height: calc(100vh - 90px);
--button-height--inline: 40px;
--setHeadTableMain-height: calc(100% - 150px);
--app-minWidth: unset;
--el-table__body-wrapper-height: calc(100% - 83px);
--table-list--table-height:700px;
--one-height:26px;
.app-main {
min-width: unset !important;
}
.contextmenu {
font-size: var(--input-fontSize) !important;
}
// 侧边栏菜单
.selectMenu {
.el-input__prefix {
top: 5px !important;
}
}
}
APP.vue
<template>
<div id="app" :theme="theme">
<router-view v-if="isRouterAlive" />
</div>
</template>
<script>
import menuStore from "@/store/menu";
export default {
name: 'App',
computed: {
theme() {
return menuStore.theme;
},
},
}
</script>
<style>
@import './assets/styles/theme.scss';
</style>
按钮切换
changeMode() {
if (this.theme != 'caring') {
menuStore.changeTheme('caring');
} else {
menuStore.changeTheme('default');
}
this.$eventBus.$emit('clickCareMode')
},
通过切换根节点模式 theme 修改引入ui库样式以及自定义样式