diff --git a/src/layout/components/setting/index.vue b/src/layout/components/setting/index.vue index 59482dc85..16e2117a7 100644 --- a/src/layout/components/setting/index.vue +++ b/src/layout/components/setting/index.vue @@ -23,6 +23,24 @@ + + 主题风格 + + ("firstTheme", null); + const secondTheme = templateRef("secondTheme", null); + + const dataTheme = ref(storageLocal.getItem("data-theme") || "dark"); + if (dataTheme) { + storageLocal.setItem("data-theme", unref(dataTheme)); + window.document.body.setAttribute("data-theme", unref(dataTheme)); + } + + // dark主题 + function onDark() { + storageLocal.setItem("data-theme", "dark"); + window.document.body.setAttribute("data-theme", "dark"); + toggleClass(true, isSelect, unref(firstTheme)); + toggleClass(false, isSelect, unref(secondTheme)); + } + + // light主题 + function onLight() { + storageLocal.setItem("data-theme", "light"); + window.document.body.setAttribute("data-theme", "light"); + toggleClass(false, isSelect, unref(firstTheme)); + toggleClass(true, isSelect, unref(secondTheme)); + } + return { ...toRefs(settings), localOperate, @@ -128,7 +173,10 @@ export default { tagsChange, onReset, markValue, - onChange + onChange, + onDark, + onLight, + dataTheme }; } }; @@ -141,11 +189,71 @@ export default { display: flex; justify-content: space-between; align-items: center; - margin: 16px; + margin: 25px; } } :deep(.el-divider__text) { font-size: 16px; font-weight: 700; } +.theme-stley { + margin-top: 25px; + width: 100%; + height: 60px; + display: flex; + justify-content: space-around; + li { + width: 30%; + height: 100%; + background: #f0f2f5; + position: relative; + overflow: hidden; + cursor: pointer; + background-color: #f0f2f5; + border-radius: 4px; + box-shadow: 0 1px 2.5px 0 rgb(0 0 0 / 18%); + &:nth-child(1) { + div { + &:nth-child(1) { + width: 30%; + height: 100%; + background: #1b2a47; + } + &:nth-child(2) { + width: 70%; + height: 30%; + top: 0; + right: 0; + background-color: #fff; + box-shadow: 0 0 1px #888888; + position: absolute; + } + } + } + + &:nth-child(2) { + div { + &:nth-child(1) { + width: 30%; + height: 100%; + box-shadow: 0 0 1px #888888; + background-color: #fff; + border-radius: 4px 0 0 4px; + } + &:nth-child(2) { + width: 70%; + height: 30%; + top: 0; + right: 0; + background-color: #fff; + box-shadow: 0 0 1px #888888; + position: absolute; + } + } + } + } +} +.is-select { + border: 2px solid #0960bd; +} diff --git a/src/layout/components/sidebar/index.vue b/src/layout/components/sidebar/index.vue index 63c980e60..655f1d7bb 100644 --- a/src/layout/components/sidebar/index.vue +++ b/src/layout/components/sidebar/index.vue @@ -3,10 +3,7 @@ { let parentPath = route.path.slice(0, route.path.lastIndexOf("/")); - dynamicRouteTags(route.path, parentPath); + dynamicRouteTags(route.path, parentPath, route); }); setTimeout(() => { diff --git a/src/layout/components/tag/tagsHook.ts b/src/layout/components/tag/tagsHook.ts index 8544cb9cf..ba9f16ffb 100644 --- a/src/layout/components/tag/tagsHook.ts +++ b/src/layout/components/tag/tagsHook.ts @@ -90,7 +90,7 @@ export function useDynamicRoutesHook() { * @param value any 当前删除tag路由 * @param current objct 当前激活路由对象 */ - const deleteDynamicTag = async (obj: any, current: object): Promise => { + const deleteDynamicTag = async (obj: any, current: any): Promise => { let valueIndex: number = dynamic.dRoutes.findIndex((item: any) => { return item.path === obj.path; }); diff --git a/src/layout/index.vue b/src/layout/index.vue index b8a46bcbf..438a21a91 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -48,6 +48,7 @@ import { toggleClass, removeClass } from "/@/utils/operate"; let hiddenMainContainer = "hidden-main-container"; import options from "/@/settings"; import { useRouter, useRoute } from "vue-router"; +import { storageLocal } from "/@/utils/storage"; interface setInter { sidebar: any; diff --git a/src/plugins/element-plus/index.ts b/src/plugins/element-plus/index.ts index 2aa3cf7bc..45d63ef5b 100644 --- a/src/plugins/element-plus/index.ts +++ b/src/plugins/element-plus/index.ts @@ -23,6 +23,9 @@ import { ElForm, ElFormItem, ElLoading, + ElPopover, + ElPopper, + ElTooltip, } from "element-plus"; const components = [ @@ -48,6 +51,9 @@ const components = [ ElInput, ElForm, ElFormItem, + ElPopover, + ElPopper, + ElTooltip, ]; const plugins = [ElLoading]; diff --git a/src/style/element-ui.scss b/src/style/element-ui.scss index cde8e4098..8b59ae100 100644 --- a/src/style/element-ui.scss +++ b/src/style/element-ui.scss @@ -15,7 +15,6 @@ display: none; } - .el-dialog { transform: none; left: 0; @@ -38,7 +37,7 @@ // dropdown .el-dropdown-menu { a { - display: block + display: block; } } @@ -46,3 +45,12 @@ .el-range-separator { box-sizing: content-box; } + +.el-loading-mask { + z-index: -1; +} + +// el-tooltip,的权重 +.is-dark { + z-index: 99999 !important; +} diff --git a/src/style/index.scss b/src/style/index.scss index 02bdc3b95..1a5cc324c 100644 --- a/src/style/index.scss +++ b/src/style/index.scss @@ -1,4 +1,3 @@ -@import "./variables.scss"; @import "./mixin.scss"; @import "./transition.scss"; @import "./element-ui.scss"; @@ -123,10 +122,6 @@ ul { -o-filter: invert(80%); } -.el-loading-mask { - z-index: -1; -} - .pc-spacing { margin: 10px; } diff --git a/src/style/sidebar.scss b/src/style/sidebar.scss index c353c2a7d..78b83318b 100644 --- a/src/style/sidebar.scss +++ b/src/style/sidebar.scss @@ -1,4 +1,19 @@ -#app { +// 暗色主题 +body[data-theme="dark"] { + $menuText: #7a80b4; + $menuActiveText: #7a80b4; + $subMenuActiveText: #f4f4f5; + $sideBarWidth: 210px; + + //菜单背景 + $menuBg: #1b2a47; + // 鼠标覆盖菜单时的背景 + $menuHover: #2a395b; + // 子菜单背景 + $subMenuBg: #1f2d3d; + // 鼠标覆盖子菜单时的背景 + $subMenuHover: #001528; + .main-container { min-height: 100%; transition: margin-left 0.28s; @@ -61,16 +76,33 @@ // width: 100% !important; } + .el-menu-item, + .el-submenu__title { + color: $menuText; + } + + .el-menu { + background-color: transparent; + } + // menu hover .submenu-title-noDropdown, .el-submenu__title { &:hover { background-color: $menuHover !important; } + background: $menuBg; } .is-active > .el-submenu__title, - .is-active > .el-submenu__title i { + .is-active.submenu-title-noDropdown { + color: $subMenuActiveText !important; + i { + color: $subMenuActiveText !important; + } + } + + .is-active { transition: color 0.3s; color: $subMenuActiveText !important; } @@ -130,6 +162,51 @@ } } + // 菜单折叠 + .el-menu--vertical { + .el-menu--popup { + background-color: $subMenuBg !important; + .el-menu-item { + color: $menuText; + background-color: $subMenuBg; + &:hover { + background-color: $subMenuHover; + } + } + } + & > .el-menu { + i { + margin-right: 16px; + } + } + + .is-active > .el-submenu__title, + .is-active.submenu-title-noDropdown { + color: $subMenuActiveText !important; + i { + color: $subMenuActiveText !important; + } + } + + .is-active { + transition: color 0.3s; + color: $subMenuActiveText !important; + } + + .nest-menu .el-submenu > .el-submenu__title, + .el-menu-item { + &:hover { + // you can use $subMenuHover + background-color: $menuHover !important; + } + } + } + + .el-scrollbar__wrap { + overflow: auto; + height: 100%; + } + .el-menu--collapse .el-menu .el-submenu { min-width: $sideBarWidth !important; } @@ -162,43 +239,243 @@ } } -// when menu collapsed -.el-menu--vertical { - & > .el-menu { - i { - margin-right: 16px; +// 亮色主题 +body[data-theme="light"] { + $menuText: #7a80b4; + $menuActiveText: #7a80b4; + $subMenuActiveText: #409eff; + $sideBarWidth: 210px; + + //菜单背景 + $menuBg: #fff; + // 鼠标覆盖菜单时的背景 + $menuHover: #e0ebf6; + // 子菜单背景 + $subMenuBg: #fff; + // 鼠标覆盖子菜单时的背景 + $subMenuHover: #e0ebf6; + + .main-container { + min-height: 100%; + transition: margin-left 0.28s; + margin-left: $sideBarWidth; + position: relative; + } + + .sidebar-container { + transition: width 0.28s; + width: $sideBarWidth !important; + background-color: $menuBg; + height: 100%; + position: fixed; + font-size: 0px; + top: 0; + bottom: 0; + left: 0; + z-index: 1001; + overflow: hidden; + box-shadow: 0 0 1px #888888; + + // reset element-plus css + .horizontal-collapse-transition { + transition: 0s width ease-in-out, 0s padding-left ease-in-out, + 0s padding-right ease-in-out; + } + + .scrollbar-wrapper { + overflow-x: hidden !important; + } + + .el-scrollbar__bar.is-vertical { + right: 0px; + } + + .el-scrollbar { + height: 100%; + } + + &.has-logo { + .el-scrollbar { + height: calc(100% - 50px); + } + } + + .is-horizontal { + display: none; + } + + a { + display: inline-block; + width: 100%; + overflow: hidden; + } + + .el-menu { + border: none; + height: 100%; + // background-color: $menuBg !important; + // width: 100% !important; + } + + .el-menu-item, + .el-submenu__title { + color: $menuText; + } + + .el-menu { + background-color: transparent; + } + + // menu hover + .submenu-title-noDropdown, + .el-submenu__title { + &:hover { + background-color: $menuHover !important; + } + background: $menuBg; + } + + .is-active > .el-submenu__title, + .is-active.submenu-title-noDropdown { + color: $subMenuActiveText !important; + i { + color: $subMenuActiveText !important; + } + } + + .is-active { + transition: color 0.3s; + color: $subMenuActiveText !important; + } + + & .nest-menu .el-submenu > .el-submenu__title, + & .el-submenu .el-menu-item { + font-size: 12px; + min-width: $sideBarWidth !important; + background-color: $subMenuBg !important; + + &:hover { + background-color: $subMenuHover !important; + } } } - .nest-menu .el-submenu > .el-submenu__title, - .el-menu-item { - &:hover { - // you can use $subMenuHover - background-color: $menuHover !important; + .hideSidebar { + .sidebar-container { + width: 54px !important; + } + + .main-container { + margin-left: 54px; + } + + .submenu-title-noDropdown { + padding: 0 !important; + position: relative; + + .el-tooltip { + padding: 0 !important; + } + } + + .el-submenu { + overflow: hidden; + & > .el-submenu__title { + .el-submenu__icon-arrow { + display: none; + } + } + } + + .el-menu--collapse { + margin-left: -5px; //需优化的地方 + .el-submenu { + & > .el-submenu__title { + & > span { + height: 0; + width: 0; + overflow: hidden; + visibility: hidden; + display: inline-block; + } + } + } } } - // the scroll bar appears when the subMenu is too long - > .el-menu--popup { - max-height: 100vh; - overflow-y: auto; - - &::-webkit-scrollbar-track-piece { - background: #d3dce6; + // 菜单折叠 + .el-menu--vertical { + .el-menu--popup { + background-color: $subMenuBg !important; + .el-menu-item { + color: $menuText; + background-color: $subMenuBg; + &:hover { + background-color: $subMenuHover; + } + } + } + & > .el-menu { + i { + margin-right: 16px; + } } - &::-webkit-scrollbar { - width: 6px; + .is-active > .el-submenu__title, + .is-active.submenu-title-noDropdown { + color: $subMenuActiveText !important; + i { + color: $subMenuActiveText !important; + } } - &::-webkit-scrollbar-thumb { - background: #99a9bf; - border-radius: 20px; + .is-active { + transition: color 0.3s; + color: $subMenuActiveText !important; + } + + .nest-menu .el-submenu > .el-submenu__title, + .el-menu-item { + &:hover { + // you can use $subMenuHover + background-color: $menuHover !important; + } + } + } + + .el-scrollbar__wrap { + overflow: auto; + height: 100%; + } + + .el-menu--collapse .el-menu .el-submenu { + min-width: $sideBarWidth !important; + } + + // mobile responsive + .mobile { + .main-container { + margin-left: 0px; + } + + .sidebar-container { + transition: transform 0.28s; + width: $sideBarWidth !important; + } + + &.hideSidebar { + .sidebar-container { + pointer-events: none; + transition-duration: 0.3s; + transform: translate3d(-$sideBarWidth, 0, 0); + } + } + } + + .withoutAnimation { + .main-container, + .sidebar-container { + transition: none; } } } - -.el-scrollbar__wrap { - overflow: auto; - height: 100%; -} diff --git a/src/style/variables.scss b/src/style/variables.scss deleted file mode 100644 index 874fc16f1..000000000 --- a/src/style/variables.scss +++ /dev/null @@ -1,39 +0,0 @@ -// sidebar -$menuText: #7a80b4; -$menuActiveText: #7a80b4; -$subMenuActiveText: #409eff; - -// dark样式 -//菜单背景 -// $menuBg: #1b2a47; -// // 鼠标覆盖菜单时的背景 -// $menuHover: #2a395b; - -// 子菜单背景 -// $subMenuBg: #1f2d3d; -// // 鼠标覆盖子菜单时的背景 -// $subMenuHover: #001528; - -// night样式 -//菜单背景 -$menuBg: #fff; -// 鼠标覆盖菜单时的背景 -$menuHover: #e0ebf6; - -// 子菜单背景 -$subMenuBg: #fff; -// 鼠标覆盖子菜单时的背景 -$subMenuHover: #e0ebf6; - -$sideBarWidth: 210px; - -:export { - menuText: $menuText; - menuActiveText: $menuActiveText; - subMenuActiveText: $subMenuActiveText; - menuBg: $menuBg; - menuHover: $menuHover; - subMenuBg: $subMenuBg; - subMenuHover: $subMenuHover; - sideBarWidth: $sideBarWidth; -} diff --git a/src/utils/operate/index.ts b/src/utils/operate/index.ts index 21aef1a6f..f6b9f8ec4 100644 --- a/src/utils/operate/index.ts +++ b/src/utils/operate/index.ts @@ -1,30 +1,38 @@ export const hasClass = (ele: Element, cls: string): any => { - return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)')) -} + return !!ele.className.match(new RegExp("(\\s|^)" + cls + "(\\s|$)")); +}; export const addClass = (ele: Element, cls: string, extracls?: string): any => { - if (!hasClass(ele, cls)) ele.className += (' ' + cls) + if (!hasClass(ele, cls)) ele.className += " " + cls; if (extracls) { - if (!hasClass(ele, extracls)) ele.className += ' ' + extracls + if (!hasClass(ele, extracls)) ele.className += " " + extracls; } -} +}; -export const removeClass = (ele: Element, cls: string, extracls?: string): any => { +export const removeClass = ( + ele: Element, + cls: string, + extracls?: string +): any => { if (hasClass(ele, cls)) { - const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)') - ele.className = ele.className.replace(reg, ' ').trim() + const reg = new RegExp("(\\s|^)" + cls + "(\\s|$)"); + ele.className = ele.className.replace(reg, " ").trim(); } if (extracls) { if (hasClass(ele, extracls)) { - const regs = new RegExp('(\\s|^)' + extracls + '(\\s|$)') - ele.className = ele.className.replace(regs, ' ').trim() + const regs = new RegExp("(\\s|^)" + extracls + "(\\s|$)"); + ele.className = ele.className.replace(regs, " ").trim(); } } -} +}; -export const toggleClass = (flag: boolean, clsName: string, target?: HTMLElement): any => { - const targetEl = target || document.body - let { className } = targetEl - className = className.replace(clsName, "") - targetEl.className = flag ? `${className} ${clsName} ` : className -} +export const toggleClass = ( + flag: boolean, + clsName: string, + target?: HTMLElement +): any => { + const targetEl = target || document.body; + let { className } = targetEl; + className = className.replace(clsName, ""); + targetEl.className = flag ? `${className} ${clsName} ` : className; +};