Demo:支持夜间模式

This commit is contained in:
wanglin2 2023-07-24 10:12:53 +08:00
parent 4ee458c509
commit d5e4044fb2
17 changed files with 348 additions and 31 deletions

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="container"> <div class="container" :class="{ isDark: isDark }">
<template v-if="show"> <template v-if="show">
<Toolbar v-if="!isZenMode"></Toolbar> <Toolbar v-if="!isZenMode"></Toolbar>
<Edit></Edit> <Edit></Edit>
@ -26,9 +26,15 @@ export default {
}, },
computed: { computed: {
...mapState({ ...mapState({
isZenMode: state => state.localConfig.isZenMode isZenMode: state => state.localConfig.isZenMode,
isDark: state => state.isDark
}) })
}, },
watch: {
isDark() {
this.setBodyDark()
}
},
async created() { async created() {
this.initLocalConfig() this.initLocalConfig()
const loading = this.$loading({ const loading = this.$loading({
@ -38,6 +44,7 @@ export default {
await this.getUserMindMapData() await this.getUserMindMapData()
this.show = true this.show = true
loading.close() loading.close()
this.setBodyDark()
}, },
methods: { methods: {
...mapActions(['getUserMindMapData']), ...mapActions(['getUserMindMapData']),
@ -56,12 +63,110 @@ export default {
...config ...config
}) })
} }
},
setBodyDark() {
this.isDark
? document.body.classList.add('isDark')
: document.body.classList.remove('isDark')
} }
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less">
.container { .container {}
body {
&.isDark {
.el-input__inner {
background-color: #363b3f;
border-color: hsla(0, 0%, 100%, 0.1);
color: hsla(0, 0%, 100%, 0.9);
}
.el-input.is-disabled .el-input__inner {
background-color: #363b3f;
border-color: hsla(0, 0%, 100%, 0.1);
color: hsla(0,0%,100%,.3);
}
/* el-select */
.el-select-dropdown {
background-color: #36393d;
border-color: hsla(0, 0%, 100%, 0.1);
.el-select-dropdown__item {
color: hsla(0, 0%, 100%, 0.6);
}
.el-select-dropdown__item.selected {
color: #409eff;
}
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
background-color: hsla(0, 0%, 100%, 0.05);
}
}
.el-select .el-input.is-disabled .el-input__inner:hover {
border-color: hsla(0, 0%, 100%, 0.1);
}
/* el-popper*/
.el-popper {
background-color: #36393d;
border-color: hsla(0, 0%, 100%, 0.1);
}
.el-popper[x-placement^='bottom'] .popper__arrow {
background-color: #36393d;
}
.el-popper[x-placement^='bottom'] .popper__arrow::after {
border-bottom-color: #36393d;
}
.el-popper[x-placement^=top] .popper__arrow {
background-color: #36393d;
}
.el-popper[x-placement^=top] .popper__arrow::after {
border-top-color: #36393d;
}
/* el-tabs */
.el-tabs__item {
color: hsla(0, 0%, 100%, 0.6);
&:hover,
&.is-active {
color: #409EFF;
}
}
.el-tabs__nav-wrap::after {
background-color: hsla(0, 0%, 100%, 0.6);
}
/* el-slider */
.el-slider__runway {
background-color: hsla(0, 0%, 100%, 0.6);
}
/* el-radio-group */
.el-radio-group {
.el-radio-button__inner {
background-color: #36393d;
color: hsla(0, 0%, 100%, 0.6);
}
.el-radio-button__orig-radio:checked+.el-radio-button__inner {
color: #FFF;
background-color: #409EFF;
}
}
}
} }
</style> </style>

View File

@ -1,6 +1,6 @@
<template> <template>
<Sidebar ref="sidebar" :title="$t('baseStyle.title')"> <Sidebar ref="sidebar" :title="$t('baseStyle.title')">
<div class="sidebarContent" v-if="data"> <div class="sidebarContent" :class="{ isDark: isDark }" v-if="data">
<!-- 背景 --> <!-- 背景 -->
<div class="title noTop">{{ $t('baseStyle.background') }}</div> <div class="title noTop">{{ $t('baseStyle.background') }}</div>
<div class="row"> <div class="row">
@ -711,7 +711,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['activeSidebar', 'localConfig']), ...mapState(['activeSidebar', 'localConfig', 'isDark']),
lineStyleList() { lineStyleList() {
return lineStyleList[this.$i18n.locale] || lineStyleList.zh return lineStyleList[this.$i18n.locale] || lineStyleList.zh
@ -922,6 +922,20 @@ export default {
padding: 20px; padding: 20px;
padding-top: 10px; padding-top: 10px;
&.isDark {
.title {
color: #fff;
}
.row {
.rowItem {
.name {
color: hsla(0,0%,100%,.6);
}
}
}
}
.title { .title {
font-size: 16px; font-size: 16px;
font-family: PingFangSC-Medium, PingFang SC; font-family: PingFangSC-Medium, PingFang SC;

View File

@ -1,5 +1,5 @@
<template> <template>
<div> <div class="colorContainer" :class="{ isDark: isDark }">
<div class="colorList"> <div class="colorList">
<span <span
class="colorItem" class="colorItem"
@ -22,6 +22,7 @@
<script> <script>
import { colorList } from '@/config' import { colorList } from '@/config'
import { mapState } from 'vuex'
/** /**
* @Author: 王林 * @Author: 王林
@ -42,6 +43,9 @@ export default {
selectColor: '' selectColor: ''
} }
}, },
computed: {
...mapState(['isDark']),
},
watch: { watch: {
color() { color() {
this.selectColor = this.color this.selectColor = this.color
@ -73,6 +77,14 @@ export default {
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.colorContainer {
&.isDark {
.moreColor {
color: hsla(0, 0%, 100%, 0.6);
}
}
}
.colorList { .colorList {
width: 240px; width: 240px;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="countContainer"> <div class="countContainer" :class="{ isDark: isDark }">
<div class="item"> <div class="item">
<span class="name">{{ $t('count.words') }}</span> <span class="name">{{ $t('count.words') }}</span>
<span class="value">{{ words }}</span> <span class="value">{{ words }}</span>
@ -12,6 +12,8 @@
</template> </template>
<script> <script>
import { mapState } from 'vuex'
/** /**
* @Author: 王林 * @Author: 王林
* @Date: 2021-06-24 22:53:10 * @Date: 2021-06-24 22:53:10
@ -29,6 +31,9 @@ export default {
num: 0 num: 0
} }
}, },
computed: {
...mapState(['isDark']),
},
created() { created() {
this.$bus.$on('data_change', this.onDataChange) this.$bus.$on('data_change', this.onDataChange)
}, },
@ -82,6 +87,14 @@ export default {
font-size: 12px; font-size: 12px;
display: flex; display: flex;
&.isDark {
background: #262a2e;
.item {
color: hsla(0,0%,100%,.6);
}
}
.item { .item {
color: #555; color: #555;
margin-right: 15px; margin-right: 15px;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="fullscreenContainer"> <div class="fullscreenContainer" :class="{ isDark: isDark }">
<el-tooltip <el-tooltip
class="item" class="item"
effect="dark" effect="dark"
@ -32,6 +32,9 @@ export default {
props: { props: {
mindMap: { mindMap: {
type: Object type: Object
},
isDark: {
type: Boolean
} }
}, },
data() { data() {
@ -63,6 +66,12 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
&.isDark {
.btn {
color: hsla(0,0%,100%,.6);
}
}
.item { .item {
margin-right: 12px; margin-right: 12px;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="mouseActionContainer"> <div class="mouseActionContainer" :class="{ isDark: isDark }">
<el-tooltip <el-tooltip
class="item" class="item"
effect="dark" effect="dark"
@ -32,6 +32,9 @@ export default {
props: { props: {
mindMap: { mindMap: {
type: Object type: Object
},
isDark: {
type: Boolean
} }
}, },
data() { data() {
@ -64,6 +67,12 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
&.isDark{
.btn {
color: hsla(0,0%,100%,.6);
}
}
.item { .item {
margin-right: 12px; margin-right: 12px;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="navigatorContainer"> <div class="navigatorContainer" :class="{ isDark: isDark }">
<div class="item"> <div class="item">
<el-select <el-select
v-model="lang" v-model="lang"
@ -16,7 +16,7 @@
</el-select> </el-select>
</div> </div>
<div class="item"> <div class="item">
<MouseAction :mindMap="mindMap"></MouseAction> <MouseAction :isDark="isDark" :mindMap="mindMap"></MouseAction>
</div> </div>
<div class="item"> <div class="item">
<el-tooltip <el-tooltip
@ -59,10 +59,10 @@
</el-tooltip> </el-tooltip>
</div> </div>
<div class="item"> <div class="item">
<Fullscreen :mindMap="mindMap"></Fullscreen> <Fullscreen :isDark="isDark" :mindMap="mindMap"></Fullscreen>
</div> </div>
<div class="item"> <div class="item">
<Scale :mindMap="mindMap"></Scale> <Scale :isDark="isDark" :mindMap="mindMap"></Scale>
</div> </div>
<div class="item"> <div class="item">
<a href="https://github.com/wanglin2/mind-map" target="_blank"> <a href="https://github.com/wanglin2/mind-map" target="_blank">
@ -79,6 +79,7 @@ import MouseAction from './MouseAction.vue'
import { langList } from '@/config' import { langList } from '@/config'
import i18n from '@/i18n' import i18n from '@/i18n'
import { storeLang, getLang } from '@/api' import { storeLang, getLang } from '@/api'
import { mapState } from 'vuex'
/** /**
* @Author: 王林 * @Author: 王林
@ -105,6 +106,9 @@ export default {
openMiniMap: false openMiniMap: false
} }
}, },
computed: {
...mapState(['isDark']),
},
methods: { methods: {
readonlyChange() { readonlyChange() {
this.isReadonly = !this.isReadonly this.isReadonly = !this.isReadonly
@ -138,6 +142,20 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
&.isDark {
background: #262a2e;
.item {
a {
color: hsla(0,0%,100%,.6);
}
.btn {
color: hsla(0,0%,100%,.6);
}
}
}
.item { .item {
margin-right: 20px; margin-right: 20px;

View File

@ -2,6 +2,7 @@
<Sidebar ref="sidebar" :title="$t('outline.title')"> <Sidebar ref="sidebar" :title="$t('outline.title')">
<el-tree <el-tree
class="outlineTree" class="outlineTree"
:class="{ isDark: isDark }"
:data="data" :data="data"
:props="defaultProps" :props="defaultProps"
:expand-on-click-node="false" :expand-on-click-node="false"
@ -53,7 +54,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['activeSidebar']) ...mapState(['activeSidebar', 'isDark'])
}, },
watch: { watch: {
activeSidebar(val) { activeSidebar(val) {
@ -150,6 +151,10 @@ export default {
} }
.outlineTree { .outlineTree {
&.isDark {
background-color: #262a2e;
}
/deep/ .el-tree-node__content { /deep/ .el-tree-node__content {
height: auto; height: auto;
margin: 5px 0; margin: 5px 0;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="scaleContainer"> <div class="scaleContainer" :class="{ isDark: isDark }">
<el-tooltip <el-tooltip
class="item" class="item"
effect="dark" effect="dark"
@ -31,6 +31,9 @@ export default {
props: { props: {
mindMap: { mindMap: {
type: Object type: Object
},
isDark: {
type: Boolean
} }
}, },
data() { data() {
@ -84,6 +87,16 @@ export default {
display: flex; display: flex;
align-items: center; align-items: center;
&.isDark {
.btn {
color: hsla(0,0%,100%,.6);
}
.scaleInfo {
color: hsla(0,0%,100%,.6);
}
}
.btn { .btn {
cursor: pointer; cursor: pointer;
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<Sidebar ref="sidebar" :title="$t('shortcutKey.title')"> <Sidebar ref="sidebar" :title="$t('shortcutKey.title')">
<div class="box"> <div class="box" :class="{ isDark: isDark }">
<div v-for="item in shortcutKeyList" :key="item.type"> <div v-for="item in shortcutKeyList" :key="item.type">
<div class="title">{{ item.type }}</div> <div class="title">{{ item.type }}</div>
<div class="list" v-for="item2 in item.list" :key="item2.value"> <div class="list" v-for="item2 in item.list" :key="item2.value">
@ -38,7 +38,7 @@ export default {
return {} return {}
}, },
computed: { computed: {
...mapState(['activeSidebar']), ...mapState(['activeSidebar', 'isDark']),
shortcutKeyList() { shortcutKeyList() {
return shortcutKeyList[this.$i18n.locale] || shortcutKeyList.zh return shortcutKeyList[this.$i18n.locale] || shortcutKeyList.zh
@ -60,6 +60,28 @@ export default {
.box { .box {
padding: 0 20px; padding: 0 20px;
&.isDark {
.title {
color: #fff;
}
.list {
.item {
.icon {
color: hsla(0,0%,100%,.6);
}
.name {
color: hsla(0,0%,100%,.6);
}
.value {
color: hsla(0,0%,100%,.3);
}
}
}
}
.title { .title {
font-size: 16px; font-size: 16px;
font-weight: 500; font-weight: 500;

View File

@ -2,7 +2,7 @@
<div <div
class="sidebarContainer" class="sidebarContainer"
@click.stop @click.stop
:class="{ show: show }" :class="{ show: show, isDark: isDark }"
:style="{ zIndex: zIndex }" :style="{ zIndex: zIndex }"
> >
<span class="closeBtn el-icon-close" @click="close"></span> <span class="closeBtn el-icon-close" @click="close"></span>
@ -38,6 +38,9 @@ export default {
zIndex: 0 zIndex: 0
} }
}, },
computed: {
...mapState(['isDark']),
},
watch: { watch: {
show(val, oldVal) { show(val, oldVal) {
if (val && !oldVal) { if (val && !oldVal) {
@ -69,6 +72,20 @@ export default {
flex-direction: column; flex-direction: column;
transition: all 0.3s; transition: all 0.3s;
&.isDark {
background-color: #262a2e;
border-left-color: hsla(0,0%,100%,.1);
.sidebarHeader {
border-bottom-color: hsla(0,0%,100%,.1);
color: #fff;
}
.closeBtn {
color: #fff;
}
}
&.show { &.show {
right: 0; right: 0;
} }

View File

@ -2,7 +2,7 @@
<div <div
class="sidebarTriggerContainer" class="sidebarTriggerContainer"
@click.stop @click.stop
:class="{ hasActive: show && activeSidebar, show: show }" :class="{ hasActive: show && activeSidebar, show: show, isDark: isDark }"
> >
<div class="toggleShowBtn" :class="{hide: !show}" @click="show = !show"> <div class="toggleShowBtn" :class="{hide: !show}" @click="show = !show">
<span class="iconfont iconjiantouyou"></span> <span class="iconfont iconjiantouyou"></span>
@ -39,7 +39,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['activeSidebar']), ...mapState(['activeSidebar', 'isDark']),
triggerList() { triggerList() {
return sidebarTriggerList[this.$i18n.locale] || sidebarTriggerList.zh return sidebarTriggerList[this.$i18n.locale] || sidebarTriggerList.zh
@ -64,6 +64,20 @@ export default {
top: 50%; top: 50%;
transform: translateY(-50%); transform: translateY(-50%);
&.isDark {
.trigger {
background-color: #262a2e;
.triggerItem {
color: hsla(0,0%,100%,.6);
&:hover {
background-color: hsla(0,0%,100%,.05);
}
}
}
}
&.show { &.show {
right: 0; right: 0;
} }

View File

@ -1,6 +1,6 @@
<template> <template>
<Sidebar ref="sidebar" :title="$t('strusture.title')"> <Sidebar ref="sidebar" :title="$t('strusture.title')">
<div class="layoutList"> <div class="layoutList" :class="{ isDark: isDark }">
<div <div
class="layoutItem" class="layoutItem"
v-for="item in layoutList" v-for="item in layoutList"
@ -47,7 +47,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['activeSidebar']) ...mapState(['activeSidebar', 'isDark'])
}, },
watch: { watch: {
activeSidebar(val) { activeSidebar(val) {
@ -80,6 +80,12 @@ export default {
.layoutList { .layoutList {
padding: 20px; padding: 20px;
&.isDark {
.name {
color: #fff;
}
}
.layoutItem { .layoutItem {
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;

View File

@ -1,6 +1,6 @@
<template> <template>
<Sidebar ref="sidebar" :title="$t('style.title')"> <Sidebar ref="sidebar" :title="$t('style.title')">
<div class="styleBox" v-if="activeNodes.length > 0"> <div class="styleBox" :class="{ isDark: isDark }" v-if="activeNodes.length > 0">
<el-tabs class="tab" v-model="activeTab" @tab-click="handleTabClick"> <el-tabs class="tab" v-model="activeTab" @tab-click="handleTabClick">
<el-tab-pane :label="$t('style.normal')" name="normal"></el-tab-pane> <el-tab-pane :label="$t('style.normal')" name="normal"></el-tab-pane>
<el-tab-pane :label="$t('style.active')" name="active"></el-tab-pane> <el-tab-pane :label="$t('style.active')" name="active"></el-tab-pane>
@ -435,7 +435,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['activeSidebar']), ...mapState(['activeSidebar', 'isDark']),
fontFamilyList() { fontFamilyList() {
return fontFamilyList[this.$i18n.locale] || fontFamilyList.zh return fontFamilyList[this.$i18n.locale] || fontFamilyList.zh
@ -623,6 +623,28 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
&.isDark {
.sidebarContent {
.title {
color: #fff;
}
.row {
.rowItem {
.name {
color: hsla(0,0%,100%,.6);
}
}
.styleBtn {
background-color: #363b3f;
color: hsla(0, 0%, 100%, 0.6);
border-color: hsla(0, 0%, 100%, 0.1);
}
}
}
}
.tab { .tab {
flex-grow: 0; flex-grow: 0;
flex-shrink: 0; flex-shrink: 0;

View File

@ -1,6 +1,6 @@
<template> <template>
<Sidebar ref="sidebar" :title="$t('theme.title')"> <Sidebar ref="sidebar" :title="$t('theme.title')">
<div class="themeList"> <div class="themeList" :class="{ isDark: isDark }">
<div <div
class="themeItem" class="themeItem"
v-for="item in themeList" v-for="item in themeList"
@ -48,7 +48,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['activeSidebar']) ...mapState(['activeSidebar', 'isDark'])
}, },
watch: { watch: {
activeSidebar(val) { activeSidebar(val) {
@ -84,6 +84,12 @@ export default {
.themeList { .themeList {
padding: 20px; padding: 20px;
&.isDark {
.name {
color: #fff;
}
}
.themeItem { .themeItem {
width: 100%; width: 100%;
cursor: pointer; cursor: pointer;

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="toolbarContainer"> <div class="toolbarContainer" :class="{ isDark: isDark }">
<div class="toolbar"> <div class="toolbar">
<!-- 节点操作 --> <!-- 节点操作 -->
<div class="toolbarBlock"> <div class="toolbarBlock">
@ -199,7 +199,7 @@ export default {
} }
}, },
computed: { computed: {
...mapState(['isHandleLocalFile']), ...mapState(['isHandleLocalFile', 'isDark']),
hasRoot() { hasRoot() {
return ( return (
this.activeNodes.findIndex(node => { this.activeNodes.findIndex(node => {
@ -447,6 +447,33 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.toolbarContainer { .toolbarContainer {
&.isDark {
.toolbar {
color: hsla(0,0%,100%,.9);
.toolbarBlock {
background-color: #262a2e;
}
.toolbarBtn {
.icon {
background: transparent;
border-color: transparent;
}
&:hover {
&:not(.disabled) {
.icon {
background: hsla(0,0%,100%,.05);
}
}
}
&.disabled {
color: #54595f;
}
}
}
}
.toolbar { .toolbar {
position: fixed; position: fixed;
left: 50%; left: 50%;
@ -522,7 +549,6 @@ export default {
} }
@media screen and (max-width: 1040px) { @media screen and (max-width: 1040px) {
.toolbarContainer { .toolbarContainer {
.toolbar { .toolbar {
left: 20px; left: 20px;

View File

@ -17,7 +17,8 @@ const store = new Vuex.Store({
// 鼠标行为 // 鼠标行为
useLeftKeySelectionRightKeyDrag: false useLeftKeySelectionRightKeyDrag: false
}, },
activeSidebar: '' // 当前显示的侧边栏 activeSidebar: '', // 当前显示的侧边栏
isDark: false,// 是否是暗黑模式
}, },
mutations: { mutations: {
/** /**
@ -61,6 +62,11 @@ const store = new Vuex.Store({
*/ */
setActiveSidebar(state, data) { setActiveSidebar(state, data) {
state.activeSidebar = data state.activeSidebar = data
},
// 设置暗黑模式
setIsDark(state, data) {
state.isDark = data
} }
}, },
actions: { actions: {