From f90899d72ab2c3e8883d34a3895c72b20e64f436 Mon Sep 17 00:00:00 2001 From: RuoYi <yzz_ivy@163.com> Date: 星期一, 07 十二月 2020 14:13:02 +0800 Subject: [PATCH] 支持主题风格配置 --- ruoyi-ui/src/layout/components/Sidebar/index.vue | 8 ruoyi-ui/src/store/modules/user.js | 2 ruoyi-ui/src/assets/styles/sidebar.scss | 12 +- ruoyi-ui/src/settings.js | 5 + ruoyi-ui/src/layout/components/Settings/index.vue | 133 ++++++++++++++++++++++---- ruoyi-ui/src/assets/images/login-background.jpg | 0 ruoyi-ui/src/store/modules/settings.js | 3 ruoyi-ui/src/views/login.vue | 2 ruoyi-ui/src/assets/styles/variables.scss | 9 + ruoyi-ui/src/assets/images/dark.svg | 39 +++++++ ruoyi-ui/src/assets/images/light.svg | 39 +++++++ ruoyi-ui/src/assets/images/profile.jpg | 0 ruoyi-ui/src/layout/index.vue | 12 + ruoyi-ui/src/layout/components/Sidebar/Logo.vue | 15 ++ ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue | 3 15 files changed, 242 insertions(+), 40 deletions(-) diff --git a/ruoyi-ui/src/assets/images/dark.svg b/ruoyi-ui/src/assets/images/dark.svg new file mode 100644 index 0000000..36b58b5 --- /dev/null +++ b/ruoyi-ui/src/assets/images/dark.svg @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix> + <feMerge> + <feMergeNode in="shadowMatrixOuter1"></feMergeNode> + <feMergeNode in="SourceGraphic"></feMergeNode> + </feMerge> + </filter> + <rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect> + <filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix> + </filter> + </defs> + <g id="配置面板" width="48" height="40" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="setting-copy-2" width="48" height="40" transform="translate(-1190.000000, -136.000000)"> + <g id="Group-8" width="48" height="40" transform="translate(1167.000000, 0.000000)"> + <g id="Group-5-Copy-5" filter="url(#filter-1)" transform="translate(25.000000, 137.000000)"> + <mask id="mask-3" fill="white"> + <use xlink:href="#path-2"></use> + </mask> + <g id="Rectangle-18"> + <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use> + <use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use> + </g> + <rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect> + <rect id="Rectangle-18" fill="#303648" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect> + </g> + </g> + </g> + </g> +</svg> \ No newline at end of file diff --git a/ruoyi-ui/src/assets/images/light.svg b/ruoyi-ui/src/assets/images/light.svg new file mode 100644 index 0000000..efd52c6 --- /dev/null +++ b/ruoyi-ui/src/assets/images/light.svg @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg width="52px" height="45px" viewBox="0 0 52 45" version="1.1" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink"> + <defs> + <filter x="-9.4%" y="-6.2%" width="118.8%" height="122.5%" filterUnits="objectBoundingBox" id="filter-1"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0" type="matrix" in="shadowBlurOuter1" result="shadowMatrixOuter1"></feColorMatrix> + <feMerge> + <feMergeNode in="shadowMatrixOuter1"></feMergeNode> + <feMergeNode in="SourceGraphic"></feMergeNode> + </feMerge> + </filter> + <rect id="path-2" x="0" y="0" width="48" height="40" rx="4"></rect> + <filter x="-4.2%" y="-2.5%" width="108.3%" height="110.0%" filterUnits="objectBoundingBox" id="filter-4"> + <feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset> + <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur> + <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix> + </filter> + </defs> + <g id="配置面板" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"> + <g id="setting-copy-2" transform="translate(-1254.000000, -136.000000)"> + <g id="Group-8" transform="translate(1167.000000, 0.000000)"> + <g id="Group-5" filter="url(#filter-1)" transform="translate(89.000000, 137.000000)"> + <mask id="mask-3" fill="white"> + <use xlink:href="#path-2"></use> + </mask> + <g id="Rectangle-18"> + <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-2"></use> + <use fill="#F0F2F5" fill-rule="evenodd" xlink:href="#path-2"></use> + </g> + <rect id="Rectangle-18" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="16" height="40"></rect> + <rect id="Rectangle-11" fill="#FFFFFF" mask="url(#mask-3)" x="0" y="0" width="48" height="10"></rect> + </g> + </g> + </g> + </g> +</svg> \ No newline at end of file diff --git a/ruoyi-ui/src/assets/image/login-background.jpg b/ruoyi-ui/src/assets/images/login-background.jpg similarity index 100% rename from ruoyi-ui/src/assets/image/login-background.jpg rename to ruoyi-ui/src/assets/images/login-background.jpg Binary files differ diff --git a/ruoyi-ui/src/assets/image/profile.jpg b/ruoyi-ui/src/assets/images/profile.jpg similarity index 100% rename from ruoyi-ui/src/assets/image/profile.jpg rename to ruoyi-ui/src/assets/images/profile.jpg Binary files differ diff --git a/ruoyi-ui/src/assets/styles/sidebar.scss b/ruoyi-ui/src/assets/styles/sidebar.scss index bd476ab..d870010 100644 --- a/ruoyi-ui/src/assets/styles/sidebar.scss +++ b/ruoyi-ui/src/assets/styles/sidebar.scss @@ -8,6 +8,7 @@ } .sidebar-container { + -webkit-transition: width .28s; transition: width 0.28s; width: $sideBarWidth !important; background-color: $menuBg; @@ -19,6 +20,8 @@ left: 0; z-index: 1001; overflow: hidden; + -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35); + box-shadow: 2px 0 6px rgba(0,21,41,.35); // reset element-ui css .horizontal-collapse-transition { @@ -73,21 +76,20 @@ .submenu-title-noDropdown, .el-submenu__title { &:hover { - background-color: $menuHover !important; + background-color: rgba(0, 0, 0, 0.06) !important; } } - .is-active>.el-submenu__title { + & .theme-dark .is-active > .el-submenu__title { color: $subMenuActiveText !important; } & .nest-menu .el-submenu>.el-submenu__title, & .el-submenu .el-menu-item { min-width: $sideBarWidth !important; - background-color: $subMenuBg !important; &:hover { - background-color: $subMenuHover !important; + background-color: rgba(0, 0, 0, 0.06) !important; } } } @@ -190,7 +192,7 @@ .el-menu-item { &:hover { // you can use $subMenuHover - background-color: $menuHover !important; + background-color: rgba(0, 0, 0, 0.06) !important; } } diff --git a/ruoyi-ui/src/assets/styles/variables.scss b/ruoyi-ui/src/assets/styles/variables.scss index d5f4e9f..f81e445 100644 --- a/ruoyi-ui/src/assets/styles/variables.scss +++ b/ruoyi-ui/src/assets/styles/variables.scss @@ -15,6 +15,11 @@ $menuBg:#304156; $menuHover:#263445; +$sidebarTitle: #ffffff; + +$menuLightBg:#ffffff; +$menuLightHover:#f0f1f5; +$sidebarLightTitle: #001529; $subMenuBg:#1f2d3d; $subMenuHover:#001528; @@ -29,7 +34,11 @@ subMenuActiveText: $subMenuActiveText; menuBg: $menuBg; menuHover: $menuHover; + menuLightBg: $menuLightBg; + menuLightHover: $menuLightHover; subMenuBg: $subMenuBg; subMenuHover: $subMenuHover; sideBarWidth: $sideBarWidth; + sidebarTitle: $sidebarTitle; + sidebarLightTitle: $sidebarLightTitle } diff --git a/ruoyi-ui/src/layout/components/Settings/index.vue b/ruoyi-ui/src/layout/components/Settings/index.vue index 3a9ac4a..7e495b7 100644 --- a/ruoyi-ui/src/layout/components/Settings/index.vue +++ b/ruoyi-ui/src/layout/components/Settings/index.vue @@ -1,12 +1,46 @@ <template> <div class="drawer-container"> <div> - <h3 class="drawer-title">系统布局配置</h3> + <div class="setting-drawer-content"> + <div class="setting-drawer-title"> + <h3 class="drawer-title">主题风格设置</h3> + </div> + <div class="setting-drawer-block-checbox"> + <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-dark')"> + <img src="@/assets/images/dark.svg" alt="dark"> + <div v-if="sideTheme === 'theme-dark'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> + <i aria-label="图标: check" class="anticon anticon-check"> + <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" + focusable="false" class=""> + <path + d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/> + </svg> + </i> + </div> + </div> + <div class="setting-drawer-block-checbox-item" @click="handleTheme('theme-light')"> + <img src="@/assets/images/light.svg" alt="light"> + <div v-if="sideTheme === 'theme-light'" class="setting-drawer-block-checbox-selectIcon" style="display: block;"> + <i aria-label="图标: check" class="anticon anticon-check"> + <svg viewBox="64 64 896 896" data-icon="check" width="1em" height="1em" :fill="theme" aria-hidden="true" + focusable="false" class=""> + <path + d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 0 0-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"/> + </svg> + </i> + </div> + </div> + </div> - <div class="drawer-item"> - <span>主题颜色</span> - <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" /> + <div class="drawer-item"> + <span>主题颜色</span> + <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" /> + </div> </div> + + <el-divider/> + + <h3 class="drawer-title">系统布局配置</h3> <div class="drawer-item"> <span>开启 Tags-Views</span> @@ -36,6 +70,12 @@ return {} }, computed: { + theme() { + return this.$store.state.settings.theme + }, + sideTheme() { + return this.$store.state.settings.sideTheme + }, fixedHeader: { get() { return this.$store.state.settings.fixedHeader @@ -76,33 +116,82 @@ key: 'theme', value: val }) + }, + handleTheme(val) { + this.$store.dispatch('settings/changeSetting', { + key: 'sideTheme', + value: val + }) } } } </script> <style lang="scss" scoped> -.drawer-container { - padding: 24px; - font-size: 14px; - line-height: 1.5; - word-wrap: break-word; + .setting-drawer-content { + .setting-drawer-title { + margin-bottom: 12px; + color: rgba(0, 0, 0, .85); + font-size: 14px; + line-height: 22px; + font-weight: bold; + } - .drawer-title { - margin-bottom: 12px; - color: rgba(0, 0, 0, .85); + .setting-drawer-block-checbox { + display: flex; + justify-content: flex-start; + align-items: center; + margin-top: 10px; + margin-bottom: 20px; + + .setting-drawer-block-checbox-item { + position: relative; + margin-right: 16px; + border-radius: 2px; + cursor: pointer; + + img { + width: 48px; + height: 48px; + } + + .setting-drawer-block-checbox-selectIcon { + position: absolute; + top: 0; + right: 0; + width: 100%; + height: 100%; + padding-top: 15px; + padding-left: 24px; + color: #1890ff; + font-weight: 700; + font-size: 14px; + } + } + } + } + + .drawer-container { + padding: 24px; font-size: 14px; - line-height: 22px; - } + line-height: 1.5; + word-wrap: break-word; - .drawer-item { - color: rgba(0, 0, 0, .65); - font-size: 14px; - padding: 12px 0; - } + .drawer-title { + margin-bottom: 12px; + color: rgba(0, 0, 0, .85); + font-size: 14px; + line-height: 22px; + } - .drawer-switch { - float: right + .drawer-item { + color: rgba(0, 0, 0, .65); + font-size: 14px; + padding: 12px 0; + } + + .drawer-switch { + float: right + } } -} </style> diff --git a/ruoyi-ui/src/layout/components/Sidebar/Logo.vue b/ruoyi-ui/src/layout/components/Sidebar/Logo.vue index 021de8e..afe5fcd 100644 --- a/ruoyi-ui/src/layout/components/Sidebar/Logo.vue +++ b/ruoyi-ui/src/layout/components/Sidebar/Logo.vue @@ -1,13 +1,13 @@ <template> - <div class="sidebar-logo-container" :class="{'collapse':collapse}"> + <div class="sidebar-logo-container" :class="{'collapse':collapse}" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }"> <transition name="sidebarLogoFade"> <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> <img v-if="logo" :src="logo" class="sidebar-logo"> - <h1 v-else class="sidebar-title">{{ title }} </h1> + <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1> </router-link> <router-link v-else key="expand" class="sidebar-logo-link" to="/"> <img v-if="logo" :src="logo" class="sidebar-logo"> - <h1 class="sidebar-title">{{ title }} </h1> + <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.sidebarTitle : variables.sidebarLightTitle }">{{ title }} </h1> </router-link> </transition> </div> @@ -15,6 +15,7 @@ <script> import logoImg from '@/assets/logo/logo.png' +import variables from '@/assets/styles/variables.scss' export default { name: 'SidebarLogo', @@ -24,6 +25,14 @@ required: true } }, + computed: { + variables() { + return variables; + }, + sideTheme() { + return this.$store.state.settings.sideTheme + } + }, data() { return { title: '若依管理系统', diff --git a/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue b/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue index 1dfd793..21f8f6a 100644 --- a/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue +++ b/ruoyi-ui/src/layout/components/Sidebar/SidebarItem.vue @@ -56,6 +56,9 @@ }, methods: { hasOneShowingChild(children = [], parent) { + if (!children) { + children = []; + } const showingChildren = children.filter(item => { if (item.hidden) { return false diff --git a/ruoyi-ui/src/layout/components/Sidebar/index.vue b/ruoyi-ui/src/layout/components/Sidebar/index.vue index 1004f53..0a87943 100644 --- a/ruoyi-ui/src/layout/components/Sidebar/index.vue +++ b/ruoyi-ui/src/layout/components/Sidebar/index.vue @@ -1,12 +1,12 @@ <template> - <div :class="{'has-logo':showLogo}"> + <div :class="{'has-logo':showLogo}" :style="{ backgroundColor: settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }"> <logo v-if="showLogo" :collapse="isCollapse" /> - <el-scrollbar wrap-class="scrollbar-wrapper"> + <el-scrollbar :class="settings.sideTheme" wrap-class="scrollbar-wrapper"> <el-menu :default-active="activeMenu" :collapse="isCollapse" - :background-color="variables.menuBg" - :text-color="variables.menuText" + :background-color="settings.sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg" + :text-color="settings.sideTheme === 'theme-dark' ? variables.menuText : 'rgba(0,0,0,.65)'" :unique-opened="true" :active-text-color="settings.theme" :collapse-transition="false" diff --git a/ruoyi-ui/src/layout/index.vue b/ruoyi-ui/src/layout/index.vue index 4e761ea..c6e9b3b 100644 --- a/ruoyi-ui/src/layout/index.vue +++ b/ruoyi-ui/src/layout/index.vue @@ -1,7 +1,7 @@ <template> - <div :class="classObj" class="app-wrapper"> - <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> - <sidebar class="sidebar-container" /> + <div :class="classObj" class="app-wrapper" :style="{'--current-color': theme}"> + <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/> + <sidebar class="sidebar-container" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBg : variables.menuLightBg }" /> <div :class="{hasTagsView:needTagsView}" class="main-container"> <div :class="{'fixed-header':fixedHeader}"> <navbar /> @@ -20,6 +20,7 @@ import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components' import ResizeMixin from './mixin/ResizeHandler' import { mapState } from 'vuex' +import variables from '@/assets/styles/variables.scss' export default { name: 'Layout', @@ -34,6 +35,8 @@ mixins: [ResizeMixin], computed: { ...mapState({ + theme: state => state.settings.theme, + sideTheme: state => state.settings.sideTheme, sidebar: state => state.app.sidebar, device: state => state.app.device, showSettings: state => state.settings.showSettings, @@ -47,6 +50,9 @@ withoutAnimation: this.sidebar.withoutAnimation, mobile: this.device === 'mobile' } + }, + variables() { + return variables; } }, methods: { diff --git a/ruoyi-ui/src/settings.js b/ruoyi-ui/src/settings.js index ca6d00c..8eb9294 100644 --- a/ruoyi-ui/src/settings.js +++ b/ruoyi-ui/src/settings.js @@ -2,6 +2,11 @@ title: '若依管理系统', /** + * 侧边栏主题 深色主题theme-dark,浅色主题theme-light + */ + sideTheme: 'theme-dark', + + /** * 是否系统布局配置 */ showSettings: false, diff --git a/ruoyi-ui/src/store/modules/settings.js b/ruoyi-ui/src/store/modules/settings.js index 30685e6..a246a3c 100644 --- a/ruoyi-ui/src/store/modules/settings.js +++ b/ruoyi-ui/src/store/modules/settings.js @@ -1,10 +1,11 @@ import variables from '@/assets/styles/element-variables.scss' import defaultSettings from '@/settings' -const { showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings +const { sideTheme, showSettings, tagsView, fixedHeader, sidebarLogo } = defaultSettings const state = { theme: variables.theme, + sideTheme: sideTheme, showSettings: showSettings, tagsView: tagsView, fixedHeader: fixedHeader, diff --git a/ruoyi-ui/src/store/modules/user.js b/ruoyi-ui/src/store/modules/user.js index dd2b6db..91f8253 100644 --- a/ruoyi-ui/src/store/modules/user.js +++ b/ruoyi-ui/src/store/modules/user.js @@ -51,7 +51,7 @@ return new Promise((resolve, reject) => { getInfo(state.token).then(res => { const user = res.user - const avatar = user.avatar == "" ? require("@/assets/image/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; + const avatar = user.avatar == "" ? require("@/assets/images/profile.jpg") : process.env.VUE_APP_BASE_API + user.avatar; if (res.roles && res.roles.length > 0) { // 验证返回的roles是否是一个非空数组 commit('SET_ROLES', res.roles) commit('SET_PERMISSIONS', res.permissions) diff --git a/ruoyi-ui/src/views/login.vue b/ruoyi-ui/src/views/login.vue index a849ebe..574ca0b 100644 --- a/ruoyi-ui/src/views/login.vue +++ b/ruoyi-ui/src/views/login.vue @@ -148,7 +148,7 @@ justify-content: center; align-items: center; height: 100%; - background-image: url("../assets/image/login-background.jpg"); + background-image: url("../assets/images/login-background.jpg"); background-size: cover; } .title { -- Gitblit v1.9.2