Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

init right-panel #1707

Merged
merged 4 commits into from
Mar 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
140 changes: 140 additions & 0 deletions src/components/RightPanel/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<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'}" type="primary" circle @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: 240,
type: Number
}
},
data() {
return {
show: false
}
},
watch: {
show(value) {
if (value && !this.clickNotClose) {
this.addEventClick()
}
if (value) {
addClass(document.body, 'showRightPanel')
} else {
removeClass(document.body, 'showRightPanel')
}
}
},
mounted() {
this.insertToBody()
},
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: calc(100% - 15px);
}
</style>

<style rel="stylesheet/scss" lang="scss" scoped>
.rightPanel-background {
opacity: 0;
transition: opacity .3s cubic-bezier(.7,.3,.1,1);
background: rgba(0, 0, 0, .2);
width: 0;
height: 0;
position: fixed;
z-index: -1;
}

.rightPanel {
background: #fff;
z-index: 3000;
position: fixed;
height: 100vh;
width: 100%;
max-width: 260px;
top: 0px;
left: 0px;
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
transition: all .25s cubic-bezier(.7,.3,.1,1);
transform: translate(100%);
z-index: 40000;
left: auto;
right: 0px;
}

.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 {
position: absolute;
left: -48px;
border-radius: 4px 0 0 4px !important;
width: 48px;
height: 48px;
background: #1890ff;
cursor: pointer;
pointer-events: auto;
z-index: 0;
text-align: center;
color: #fff;
line-height: 48px;

i {
font-size: 24px;
line-height: 48px;
}
}
</style>
27 changes: 17 additions & 10 deletions src/layout/Layout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,41 @@
<div :class="classObj" class="app-wrapper">
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
<sidebar class="sidebar-container" />
<div class="main-container">
<div :class="{hasTagsView:needTagsView}" class="main-container">
<navbar />
<tags-view />
<tags-view v-if="needTagsView" />
<app-main />
<right-panel v-if="showSettings">
<settings />
</right-panel>
</div>
</div>
</template>

<script>
import { Navbar, Sidebar, AppMain, TagsView } from './components'
import RightPanel from '@/components/RightPanel'
import { Navbar, Sidebar, AppMain, TagsView, Settings } from './components'
import ResizeMixin from './mixin/ResizeHandler'
import { mapState } from 'vuex'

export default {
name: 'Layout',
components: {
RightPanel,
Navbar,
Sidebar,
AppMain,
TagsView
TagsView,
Settings
},
mixins: [ResizeMixin],
computed: {
sidebar() {
return this.$store.state.app.sidebar
},
device() {
return this.$store.state.app.device
},
...mapState({
sidebar: state => state.app.sidebar,
device: state => state.app.device,
showSettings: state => state.settings.showSettings,
needTagsView: state => state.settings.tagsView
}),
classObj() {
return {
hideSidebar: !this.sidebar.opened,
Expand Down
9 changes: 7 additions & 2 deletions src/layout/components/AppMain.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,16 @@ export default {

<style scoped>
.app-main {
/*84 = navbar + tags-view = 50 +34 */
min-height: calc(100vh - 84px);
/*50= navbar 50 */
min-height: calc(100vh - 50px);
width: 100%;
position: relative;
overflow: hidden;
}

.hasTagsView .app-main {
/*84 = navbar + tags-view = 50 + 34 */
min-height: calc(100vh - 84px);
}
</style>

8 changes: 8 additions & 0 deletions src/layout/components/Navbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,16 @@ export default {
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
.hasTagsView {
.navbar {
border-bottom: none;
}
}

.navbar {
height: 50px;
overflow: hidden;
box-shadow: 0 1px 4px rgba(0,21,41,.08);

.hamburger-container {
line-height: 46px;
Expand Down Expand Up @@ -150,6 +157,7 @@ export default {
.avatar-wrapper {
margin-top: 5px;
position: relative;

.user-avatar {
cursor: pointer;
width: 40px;
Expand Down
68 changes: 68 additions & 0 deletions src/layout/components/Settings/index.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<template>
<div class="drawer-container">
<div>
<h3 class="drawer-title">
系统布局配置
</h3>

<div class="drawer-item">
<span>开启 Tags-View</span>
<el-switch v-model="tagsView" class="drawer-switch" />
</div>

<!-- <div class="drawer-item">
<span>显示 Logo</span>
<el-switch v-model="sidebarLogo" class="drawer-switch" />
</div> -->
</div>
</div>
</template>

<script>
export default {
data() {
return {
sidebarLogo: true
}
},
computed: {
tagsView: {
get() {
return this.$store.state.settings.tagsView
},
set(val) {
this.$store.dispatch('changeSetting', {
key: 'tagsView',
value: val
})
}
}
}
}
</script>

<style rel="stylesheet/scss" 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>
1 change: 1 addition & 0 deletions src/layout/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export { default as Navbar } from './Navbar'
export { default as Sidebar } from './Sidebar/index.vue'
export { default as TagsView } from './TagsView/index.vue'
export { default as AppMain } from './AppMain'
export { default as Settings } from './Settings'
22 changes: 22 additions & 0 deletions src/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default {

/**
* @type {boolean} true | false
* @description Whether show the settings right-panel
*/
showSettings: true,

/**
* @type {boolean} true | false
* @description Whether need tagsView
*/
tagsView: true,

/**
* @type {string | array} 'production' | ['production','development']
* @description Need show err logs component.
* The default is only used in the production env
* If you want to use it in dev, you can pass ['production','development']
*/
errorLog: 'production'
}
2 changes: 2 additions & 0 deletions src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import app from './modules/app'
import errorLog from './modules/errorLog'
import permission from './modules/permission'
import tagsView from './modules/tagsView'
import settings from './modules/settings'
import user from './modules/user'
import getters from './getters'

Expand All @@ -15,6 +16,7 @@ const store = new Vuex.Store({
errorLog,
permission,
tagsView,
settings,
user
},
getters
Expand Down
23 changes: 23 additions & 0 deletions src/store/modules/settings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import defaultSettings from '@/settings'
const { showSettings, tagsView } = defaultSettings

const settings = {
state: {
showSettings: showSettings,
tagsView: tagsView
},
mutations: {
CHANGE_SETTING: (state, { key, value }) => {
if (state.hasOwnProperty(key)) {
state[key] = value
}
}
},
actions: {
changeSetting({ commit }, data) {
commit('CHANGE_SETTING', data)
}
}
}

export default settings
13 changes: 13 additions & 0 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,16 @@ export function createUniqueString() {
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
return (+(randomNum + timestamp)).toString(32)
}

export function hasClass(ele, cls) {
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
}
export function addClass(ele, cls) {
if (!hasClass(ele, cls)) ele.className += ' ' + cls
}
export function removeClass(ele, cls) {
if (hasClass(ele, cls)) {
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
ele.className = ele.className.replace(reg, ' ')
}
}