feat: 尝试增加主题切换功能

This commit is contained in:
fit2cloud-chenyw 2021-09-02 14:28:15 +08:00
parent a9fd56ac67
commit ad2e93c63e
14 changed files with 99 additions and 484 deletions

1
.gitignore vendored
View File

@ -51,6 +51,7 @@ pnpm-debug.log*
*.classpath
*.project
.settings/
.lh
package-lock.json

View File

@ -1,145 +0,0 @@
<template>
<div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
<div class="rightPanel-background" />
<div class="rightPanel">
<!-- <div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">-->
<!-- <i :class="show?'el-icon-close':'el-icon-setting'" />-->
<!-- </div>-->
<div class="rightPanel-items">
<slot />
</div>
</div>
</div>
</template>
<script>
import { addClass, removeClass } from '@/utils'
export default {
name: 'RightPanel',
props: {
clickNotClose: {
default: false,
type: Boolean
},
buttonTop: {
default: 250,
type: Number
}
},
data() {
return {
show: false
}
},
computed: {
theme() {
return this.$store.state.settings.theme
}
},
watch: {
show(value) {
if (value && !this.clickNotClose) {
this.addEventClick()
}
if (value) {
addClass(document.body, 'showRightPanel')
} else {
removeClass(document.body, 'showRightPanel')
}
}
},
mounted() {
this.insertToBody()
},
beforeDestroy() {
const elx = this.$refs.rightPanel
elx.remove()
},
methods: {
addEventClick() {
window.addEventListener('click', this.closeSidebar)
},
closeSidebar(evt) {
const parent = evt.target.closest('.rightPanel')
if (!parent) {
this.show = false
window.removeEventListener('click', this.closeSidebar)
}
},
insertToBody() {
const elx = this.$refs.rightPanel
const body = document.querySelector('body')
body.insertBefore(elx, body.firstChild)
}
}
}
</script>
<style>
.showRightPanel {
overflow: hidden;
position: relative;
width:100%;
}
</style>
<style lang="scss" scoped>
.rightPanel-background {
position: fixed;
top: 0;
left: 0;
opacity: 0;
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
background: rgba(0, 0, 0, .2);
z-index: -1;
}
.rightPanel {
width: 100%;
max-width: 260px;
height: 100vh;
position: fixed;
top: 0;
right: 0;
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
transition: all .25s cubic-bezier(.7, .3, .1, 1);
transform: translate(100%);
background: #fff;
z-index: 40000;
}
.show {
transition: all .3s cubic-bezier(.7, .3, .1, 1);
.rightPanel-background {
z-index: 20000;
opacity: 1;
width: 100%;
height: 100%;
}
.rightPanel {
transform: translate(0);
}
}
.handle-button {
width: 48px;
height: 48px;
position: absolute;
left: -48px;
text-align: center;
font-size: 24px;
border-radius: 6px 0 0 6px !important;
z-index: 0;
pointer-events: auto;
cursor: pointer;
color: #fff;
line-height: 48px;
i {
font-size: 24px;
line-height: 48px;
}
}
</style>

View File

@ -1,107 +0,0 @@
<template>
<div class="drawer-container">
<div>
<h3 class="drawer-title">{{ $t('settings.title') }}</h3>
<div class="drawer-item">
<span>{{ $t('settings.theme') }}</span>
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
</div>
<div class="drawer-item">
<span>{{ $t('settings.fixedHeader') }}</span>
<el-switch v-model="fixedHeader" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>{{ $t('settings.sidebarLogo') }}</span>
<el-switch v-model="sidebarLogo" class="drawer-switch" />
</div>
</div>
</div>
</template>
<script>
import ThemePicker from '@/components/ThemePicker'
export default {
name: 'Settings',
components: { ThemePicker },
data() {
return {}
},
computed: {
fixedHeader: {
get() {
return this.$store.state.settings.fixedHeader
},
set(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'fixedHeader',
value: val
})
}
},
sidebarLogo: {
get() {
return this.$store.state.settings.sidebarLogo
},
set(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'sidebarLogo',
value: val
})
}
},
lang() {
return this.$store.getters.language
}
},
methods: {
themeChange(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'theme',
value: val
})
}
}
}
</script>
<style lang="scss" scoped>
.drawer-container {
padding: 24px;
font-size: 14px;
line-height: 1.5;
word-wrap: break-word;
.drawer-title {
margin-bottom: 12px;
color: rgba(0, 0, 0, .85);
font-size: 14px;
line-height: 22px;
}
.drawer-item {
color: rgba(0, 0, 0, .65);
font-size: 14px;
padding: 12px 0;
}
.drawer-switch {
float: right
}
.job-link{
display: block;
position: absolute;
width: 100%;
left: 0;
bottom: 0;
}
}
</style>

View File

@ -10,7 +10,6 @@
<script>
const version = require('element-ui/package.json').version // element-ui version from node_modules
const ORIGINAL_THEME = '#409EFF' // default color
import Cookies from 'js-cookie'
export default {
data() {
return {
@ -31,8 +30,13 @@ export default {
immediate: true
},
async theme(val) {
Cookies.set('theme', val, { expires: 365 })
const oldVal = this.chalk ? this.theme : Cookies.get('theme') ? Cookies.get('theme') : ORIGINAL_THEME
this.switch(val)
}
},
methods: {
async switch(val) {
const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
if (typeof val !== 'string') return
const themeCluster = this.getThemeCluster(val.replace('#', ''))
const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
@ -73,10 +77,7 @@ export default {
})
this.$emit('change', val)
}
},
methods: {
},
updateStyle(style, oldCluster, newCluster) {
let newStyle = style
oldCluster.forEach((color, index) => {

View File

@ -1245,7 +1245,15 @@ export default {
loginImage: '登录页面右侧图片',
loginTitle: '登录页面标题',
title: '系统名称',
advice_size: '建议图片大小'
advice_size: '建议图片大小',
theme: '头部背景',
topMenuActiveColor: '主题颜色',
topMenuTextColor: '字体颜色',
topMenuTextActiveColor: '字体选中颜色'
},
auth: {
authConfig: '权限配置',

View File

@ -17,9 +17,9 @@ export default {
}
},
computed: {
theme() {
/* theme() {
return this.$store.state.settings.theme
},
}, */
licValidate() {
return this.$store.state.lic.validate
},

View File

@ -1,140 +0,0 @@
<template>
<div class="drawer-container">
<div>
<h3 class="drawer-title">系统布局设置</h3>
<div class="drawer-item">
<span>主题颜色</span>
<theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
</div>
<!-- <div class="drawer-item">
<span>显示标签</span>
<el-switch v-model="tagsView" class="drawer-switch" />
</div>
<div class="drawer-item">
<span>固定头部</span>
<el-switch v-model="fixedHeader" class="drawer-switch" />
</div> -->
<div class="drawer-item">
<span>显示LOGO</span>
<el-switch v-model="sidebarLogo" class="drawer-switch" />
</div>
<!-- <div class="drawer-item">
<span>菜单UniqueOpened</span>
<el-switch v-model="uniqueOpened" class="drawer-switch" />
</div> -->
<div class="drawer-item">
<span>展开菜单</span>
<el-switch v-model="toggleSideBar" class="drawer-switch" />
</div>
</div>
</div>
</template>
<script>
import ThemePicker from '@/components/ThemePicker'
export default {
components: { ThemePicker },
data() {
return {
showMenu: true
}
},
computed: {
// fixedHeader: {
// get() {
// return this.$store.state.settings.fixedHeader
// },
// set(val) {
// this.$store.dispatch('settings/changeSetting', {
// key: 'fixedHeader',
// value: val
// })
// }
// },
// tagsView: {
// get() {
// return this.$store.state.settings.tagsView
// },
// set(val) {
// this.$store.dispatch('settings/changeSetting', {
// key: 'tagsView',
// value: val
// })
// }
// },
sidebarLogo: {
get() {
return this.$store.state.settings.sidebarLogo
},
set(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'sidebarLogo',
value: val
})
}
},
toggleSideBar: {
get() {
return this.showMenu
},
set(val) {
this.showMenu = !this.showMenu
this.$store.dispatch('app/toggleSideBar')
}
}
// uniqueOpened: {
// get() {
// return this.$store.state.settings.uniqueOpened
// },
// set(val) {
// this.$store.dispatch('settings/changeSetting', {
// key: 'uniqueOpened',
// value: val
// })
// }
// }
},
methods: {
themeChange(val) {
this.$store.dispatch('settings/changeSetting', {
key: 'theme',
value: val
})
}
}
}
</script>
<style lang="scss" scoped>
.drawer-container {
padding: 24px;
font-size: 14px;
line-height: 1.5;
word-wrap: break-word;
.drawer-title {
margin-bottom: 12px;
color: rgba(0, 0, 0, .85);
font-size: 14px;
line-height: 22px;
}
.drawer-item {
color: rgba(0, 0, 0, .65);
font-size: 14px;
padding: 12px 0;
}
.drawer-switch {
float: right
}
}
</style>

View File

@ -53,8 +53,7 @@ export default {
width: 100%;
height: 50px;
line-height: 50px;
// background: #2b2f3a;
background-color: $menuBg;
background-color: $topBarBg;
text-align: center;
overflow: hidden;

View File

@ -4,10 +4,7 @@
<el-menu
:default-active="activeMenu"
:collapse="isCollapse"
:background-color="variables.menuBg"
:unique-opened="false"
:active-text-color="variables.menuActiveText"
:collapse-transition="false"
mode="vertical"
>

View File

@ -1,15 +1,13 @@
<template>
<div class="top-nav" :style="{'background-color': '#f1f3f8'}">
<div class="top-nav">
<div v-loading="!axiosFinished" class="log">
<!-- <img v-if="!logoUrl" src="@/assets/DataEase-color.png" width="140" alt="" style="padding-top: 10px;">-->
<svg-icon v-if="!logoUrl && axiosFinished" icon-class="DataEase" custom-class="top-nav-logo-icon" />
<img v-if="logoUrl && axiosFinished" :src="logoUrl" width="140" alt="" style="padding-top: 10px;">
</div>
<el-menu
:active-text-color="variables.topMenuActiveText"
:default-active="activeMenu"
mode="horizontal"
:style="{'background-color': '#f1f3f8', 'margin-left': '260px', 'position': 'absolute'}"
:style="{'margin-left': '260px', 'position': 'absolute'}"
@select="handleSelect"
>
<div v-for="item in permission_routes" :key="item.path" class="nav-item">
@ -24,17 +22,7 @@
<div class="right-menu">
<template>
<!-- <el-tooltip content="项目文档" effect="dark" placement="bottom">-->
<!-- <doc class="right-menu-item hover-effect" />-->
<!-- </el-tooltip>-->
<!-- <el-tooltip content="全屏缩放" effect="dark" placement="bottom">-->
<!-- <screenfull id="screenfull" class="right-menu-item hover-effect" />-->
<!-- </el-tooltip>-->
<!-- <el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
<size-select id="size-select" class="right-menu-item hover-effect" />
</el-tooltip> -->
<notification class="right-menu-item hover-effect" />
<lang-select class="right-menu-item hover-effect" />
<div style="height: 100%;padding: 0 8px;" class="right-menu-item hover-effect">
@ -61,9 +49,7 @@
<router-link to="/person-pwd/index">
<el-dropdown-item>{{ $t('user.change_password') }}</el-dropdown-item>
</router-link>
<!-- <a href="https://de-docs.fit2cloud.com/" target="_blank">-->
<!-- <el-dropdown-item>{{ $t('commons.help_documentation') }} </el-dropdown-item>-->
<!-- </a>-->
<router-link to="/about/index">
<el-dropdown-item>{{ $t('commons.about_us') }}</el-dropdown-item>
</router-link>
@ -74,6 +60,7 @@
</el-dropdown>
</div>
</div>
</template>
<script>
@ -82,19 +69,16 @@ import AppLink from './Sidebar/Link'
import variables from '@/styles/variables.scss'
import { isExternal } from '@/utils/validate'
import Notification from '@/components/Notification'
// import Screenfull from '@/components/Screenfull'
// import SizeSelect from '@/components/SizeSelect'
// import bus from '@/utils/bus'
import LangSelect from '@/components/LangSelect'
import { getSysUI } from '@/utils/auth'
export default {
name: 'Topbar',
components: {
AppLink,
// Screenfull,
// SizeSelect,
Notification,
LangSelect
// Doc
},
data() {
return {
@ -140,13 +124,7 @@ export default {
this.initCurrentRoutes()
},
created() {
this.$store.dispatch('user/getUI').then(() => {
this.uiInfo = getSysUI()
if (this.uiInfo['ui.logo'] && this.uiInfo['ui.logo'].paramValue) {
this.logoUrl = '/system/ui/image/' + this.uiInfo['ui.logo'].paramValue
}
this.axiosFinished = true
})
this.loadUiInfo()
},
methods: {
// store
@ -236,6 +214,22 @@ export default {
async logout() {
await this.$store.dispatch('user/logout')
this.$router.push(`/login?redirect=${this.$route.fullPath}`)
},
loadUiInfo() {
this.$store.dispatch('user/getUI').then(() => {
this.uiInfo = getSysUI()
if (this.uiInfo['ui.logo'] && this.uiInfo['ui.logo'].paramValue) {
this.logoUrl = '/system/ui/image/' + this.uiInfo['ui.logo'].paramValue
}
if (this.uiInfo['ui.theme'] && this.uiInfo['ui.theme'].paramValue) {
const val = this.uiInfo['ui.theme'].paramValue
this.$store.dispatch('settings/changeSetting', {
key: 'theme',
value: val
})
}
this.axiosFinished = true
})
}
}

View File

@ -15,9 +15,7 @@
.sidebar-container {
transition: width 0.28s;
// width: $sideBarWidth !important;
background-color: $menuBg;
// width: 260px;
background-color: $leftMenuBg;
height: $contentHeight;
position: fixed;
font-size: 0px;
@ -74,7 +72,7 @@
width: 100% !important;
.is-active {
background-color: $menuHover;
background-color: $leftMenuActive;
}
}
@ -82,21 +80,21 @@
.submenu-title-noDropdown,
.el-submenu__title {
&:hover {
background-color: $menuHover !important;
background-color: $leftMenuHovor !important;
}
}
.is-active > .el-submenu__title {
color: $menuActiveText !important;
color: $leftMenuTextActive !important;
}
& .nest-menu .el-submenu > .el-submenu__title,
& .el-submenu .el-menu-item {
min-width: $sideBarWidth !important;
background-color: $subMenuBg !important;
background-color: $leftMenuBg !important;
&:hover {
background-color: $menuHover !important;
background-color: $leftMenuHovor !important;
}
}
}
@ -198,8 +196,7 @@
.nest-menu .el-submenu > .el-submenu__title,
.el-menu-item {
&:hover {
// you can use $subMenuHover
background-color: $menuHover !important;
background-color: $leftMenuHovor !important;
}
}

View File

@ -2,7 +2,7 @@
// margin-left: $sideBarWidth;
width: 100%;
// background-color: #304156;
// background-color: $--color-primary;
background-color: $topBarBg;
position: fixed;
top: 0;
left: 0;
@ -17,7 +17,8 @@
font-size: 24px;
font-weight: bold;
// color: rgb(191, 203, 217);
color: rgba(255, 255, 255, 0.87);
// color: rgba(255, 255, 255, 0.87);
color: $topBarBg;
float: left;
img {
@ -30,30 +31,30 @@
float: left;
border: none !important;
// background-color: #304156;
// background-color: $--color-primary;
background-color: $topBarBg;
.nav-item {
display: inline-block;
.el-menu-item:not(.is-active) {
// color: rgb(191, 203, 217);
color: $menuText;
color: $topBarMenuText;
&:hover {
background-color: $menuHover !important;
background-color: $topBarMenuHovor !important;
// color: $subMenuActiveText !important;
}
&:focus {
background-color: $subMenuHover !important;
color: $subMenuActiveText !important;
background-color: $topBarMenuHovor !important;
color: $topBarMenuText !important;
}
}
.is-active {
background-color: $subMenuHover !important;
color: $subMenuActiveText !important;
background-color: $topBarMenuActive !important;
color: $topBarMenuTextActive !important;
}
}
}

View File

@ -3,7 +3,10 @@
* So I modified the default color and you can modify it to your liking.
**/
/* theme color */
$--color-primary: #0a7be0;
$--color-success: #67C23A;
$--color-warning: #E6A23C;
@ -12,50 +15,49 @@ $--color-danger: #F56C6C;
$--button-font-weight: 400;
// $--color-text-regular: #1f2d3d;
$--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5;
$--table-border: 1px solid #dfe6ec;
/* icon font path, required */
$--font-path: "~element-ui/lib/theme-chalk/fonts";
@import "~element-ui/packages/theme-chalk/src/index";
@import "~fit2cloud-ui/src/styles/common/variables";
// topBar
$topBarBg: #f1f3f8;
$topBarMenuHovor: rgba(158,158,158,.2);
$topBarMenuActive: $--color-primary;
$topBarMenuText: #1e212a;
$topBarMenuTextActive: #f4f4f5;
// sidebar
$menuText: #1e212a;
$menuActiveText: #0a7be0;
$topMenuActiveText: #f4f4f5;
$subMenuActiveText: #f4f4f5; //https://github.com/ElemeFE/element/issues/12951
$leftMenuBg: #ffffff;
$leftMenuActive: #ebf4fd;
$leftMenuHovor: rgba(158,158,158,.2);
$leftMenuText: #1e212a;
$leftMenuTextActive: $--color-primary;
// $menuBg:#304156;
$menuBg: #ffffff;
// $menuHover:#263445;
$menuHover: rgba(158, 158, 158, 0.2);
$subMenuBg: #ffffff;
// $subMenuHover:#001528;
$subMenuHover: #0a7be0;
$colorBg: rgba(10, 123, 224, .1);
$colorBg: rgba(10, 123, 224, .1);
$sideBarWidth: 210px;
$topBarHeight: 56px;
$contentHeight: calc(100vh - 56px);
// the :export directive is the magic sauce for webpack
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
:export {
theme: $--color-primary;
menuText: $menuText;
menuActiveText: $menuActiveText;
topMenuActiveText: $topMenuActiveText;
subMenuActiveText: $subMenuActiveText;
menuBg: $menuBg;
menuHover: $menuHover;
subMenuBg: $subMenuBg;
subMenuHover: $subMenuHover;
sideBarWidth: $sideBarWidth;
topBarBg: $topBarBg;
topBarMenuHovor: $topBarMenuHovor;
topBarMenuActive: $topBarMenuActive;
topBarMenuText: $topBarMenuText;
topBarMenuTextActive: $topBarMenuTextActive;
leftMenuBg: $leftMenuBg;
leftMenuActive: $leftMenuActive;
leftMenuHovor: $leftMenuHovor;
leftMenuText: $leftMenuText;
leftMenuTextActive: $leftMenuTextActive;
}

View File

@ -1,12 +1,12 @@
<template>
<layout-content v-if="!noLayout" v-loading="$store.getters.loadingMap[$store.getters.currentPath]" :header="header" :back-name="backName">
<async-component v-if="showAsync" :url="url" @execute-axios="executeAxios" @on-add-languanges="addLanguages" @on-plugin-layout="setLayoutInfo" />
<async-component v-if="showAsync" :url="url" @execute-axios="executeAxios" @on-add-languanges="addLanguages" @on-plugin-layout="setLayoutInfo" @plugin-call-back="pluginCallBack" />
<div v-else>
<h1>未知组件无法展示</h1>
</div>
</layout-content>
<div v-else>
<async-component v-if="showAsync" :url="url" @execute-axios="executeAxios" @on-add-languanges="addLanguages" @on-plugin-layout="setLayoutInfo" />
<async-component v-if="showAsync" :url="url" @execute-axios="executeAxios" @on-add-languanges="addLanguages" @on-plugin-layout="setLayoutInfo" @plugin-call-back="pluginCallBack" />
<div v-else>
<h1>未知组件无法展示</h1>
</div>
@ -18,6 +18,7 @@
import LayoutContent from '@/components/business/LayoutContent'
import AsyncComponent from '@/components/AsyncComponent'
import i18n from '@/lang'
import bus from '@/utils/bus'
import { execute } from '@/api/system/dynamic'
export default {
name: 'Dynamic',
@ -85,6 +86,12 @@ export default {
const { header, backName } = param
this.header = header
this.backName = backName
},
pluginCallBack(param) {
// console.log(param)
const { eventName, eventParam } = param
bus.$emit(eventName, eventParam)
}
}
}