Merge remote-tracking branch 'PanJiaChen/master'
This commit is contained in:
commit
aae2c2edff
19
package.json
19
package.json
|
@ -1,10 +1,9 @@
|
||||||
{
|
{
|
||||||
"name": "vue-element-admin",
|
"name": "vue-element-admin",
|
||||||
"version": "3.6.5",
|
"version": "3.6.6",
|
||||||
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
||||||
"author": "Pan <panfree23@gmail.com>",
|
"author": "Pan <panfree23@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||||
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
|
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
|
||||||
|
@ -12,6 +11,20 @@
|
||||||
"lint": "eslint --ext .js,.vue src",
|
"lint": "eslint --ext .js,.vue src",
|
||||||
"test": "npm run lint"
|
"test": "npm run lint"
|
||||||
},
|
},
|
||||||
|
"keywords": [
|
||||||
|
"vue",
|
||||||
|
"element-ui",
|
||||||
|
"admin",
|
||||||
|
"management-system",
|
||||||
|
"admin-template"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.17.1",
|
"axios": "0.17.1",
|
||||||
"clipboard": "1.7.1",
|
"clipboard": "1.7.1",
|
||||||
|
@ -37,7 +50,7 @@
|
||||||
"vue-multiselect": "2.0.8",
|
"vue-multiselect": "2.0.8",
|
||||||
"vue-router": "3.0.1",
|
"vue-router": "3.0.1",
|
||||||
"vue-splitpane": "1.0.2",
|
"vue-splitpane": "1.0.2",
|
||||||
"vuedraggable": "2.15.0",
|
"vuedraggable": "^2.16.0",
|
||||||
"vuex": "3.0.1",
|
"vuex": "3.0.1",
|
||||||
"xlsx": "0.11.16"
|
"xlsx": "0.11.16"
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<template>
|
||||||
|
<div class="board-column">
|
||||||
|
<div class="board-column-header">
|
||||||
|
{{headerText}}
|
||||||
|
</div>
|
||||||
|
<draggable
|
||||||
|
class="board-column-content"
|
||||||
|
:list="list"
|
||||||
|
:options="options">
|
||||||
|
<div class="board-item" v-for="element in list" :key="element.id">
|
||||||
|
{{element.name}} {{element.id}}
|
||||||
|
</div>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'dragKanban-demo',
|
||||||
|
components: {
|
||||||
|
draggable
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
headerText: {
|
||||||
|
type: String,
|
||||||
|
default: 'Header'
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Object,
|
||||||
|
default() {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.board-column {
|
||||||
|
min-width: 300px;
|
||||||
|
min-height: 100px;
|
||||||
|
height: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
background: #f0f0f0;
|
||||||
|
border-radius: 3px;
|
||||||
|
|
||||||
|
.board-column-header {
|
||||||
|
height: 50px;
|
||||||
|
line-height: 50px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 20px;
|
||||||
|
text-align: center;
|
||||||
|
background: #333;
|
||||||
|
color: #fff;
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.board-column-content {
|
||||||
|
height: auto;
|
||||||
|
overflow: hidden;
|
||||||
|
border: 10px solid transparent;
|
||||||
|
min-height: 60px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-start;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.board-item {
|
||||||
|
cursor: pointer;
|
||||||
|
width: 100%;
|
||||||
|
height: 64px;
|
||||||
|
margin: 5px 0;
|
||||||
|
background-color: #fff;
|
||||||
|
text-align: left;
|
||||||
|
line-height: 54px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
box-shadow: 0px 1px 3px 0 rgba(0,0,0,0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll" >
|
|
||||||
<div class="scroll-wrapper" ref="scrollWrapper" :style="{top: top + 'px'}">
|
|
||||||
<slot></slot>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
const delta = 15
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'scrollBar',
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
top: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
handleScroll(e) {
|
|
||||||
const eventDelta = e.wheelDelta || -e.deltaY * 3
|
|
||||||
const $container = this.$refs.scrollContainer
|
|
||||||
const $containerHeight = $container.offsetHeight
|
|
||||||
const $wrapper = this.$refs.scrollWrapper
|
|
||||||
const $wrapperHeight = $wrapper.offsetHeight
|
|
||||||
if (eventDelta > 0) {
|
|
||||||
this.top = Math.min(0, this.top + eventDelta)
|
|
||||||
} else {
|
|
||||||
if ($containerHeight - delta < $wrapperHeight) {
|
|
||||||
if (this.top < -($wrapperHeight - $containerHeight + delta)) {
|
|
||||||
this.top = this.top
|
|
||||||
} else {
|
|
||||||
this.top = Math.max(this.top + eventDelta, $containerHeight - $wrapperHeight - delta)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.top = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
|
||||||
@import '../../styles/variables.scss';
|
|
||||||
|
|
||||||
.scroll-container {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background-color: $menuBg;
|
|
||||||
.scroll-wrapper {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%!important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -2,39 +2,67 @@ export default{
|
||||||
bind(el, binding) {
|
bind(el, binding) {
|
||||||
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
||||||
const dragDom = el.querySelector('.el-dialog')
|
const dragDom = el.querySelector('.el-dialog')
|
||||||
dialogHeaderEl.style = 'cursor:move;'
|
dialogHeaderEl.style.cssText += ';cursor:move;'
|
||||||
|
dragDom.style.cssText += ';top:0px;'
|
||||||
|
|
||||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
||||||
const sty = dragDom.currentStyle || window.getComputedStyle(dragDom, null)
|
const getStyle = (function() {
|
||||||
|
if (window.document.currentStyle) {
|
||||||
|
return (dom, attr) => dom.currentStyle[attr]
|
||||||
|
} else {
|
||||||
|
return (dom, attr) => getComputedStyle(dom, false)[attr]
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|
||||||
dialogHeaderEl.onmousedown = (e) => {
|
dialogHeaderEl.onmousedown = (e) => {
|
||||||
// 鼠标按下,计算当前元素距离可视区的距离
|
// 鼠标按下,计算当前元素距离可视区的距离
|
||||||
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
||||||
const disY = e.clientY - dialogHeaderEl.offsetTop
|
const disY = e.clientY - dialogHeaderEl.offsetTop
|
||||||
|
|
||||||
// 获取到的值带px 正则匹配替换
|
const dragDomWidth = dragDom.offsetWidth
|
||||||
let styL, styT
|
const dragDomheight = dragDom.offsetHeight
|
||||||
|
|
||||||
// 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
|
const screenWidth = document.body.clientWidth
|
||||||
if (sty.left.includes('%')) {
|
const screenHeight = document.body.clientHeight
|
||||||
styL = +document.body.clientWidth * (+sty.left.replace(/\%/g, '') / 100)
|
|
||||||
styT = +document.body.clientHeight * (+sty.top.replace(/\%/g, '') / 100)
|
const minDragDomLeft = dragDom.offsetLeft
|
||||||
|
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
|
||||||
|
|
||||||
|
const minDragDomTop = dragDom.offsetTop
|
||||||
|
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight
|
||||||
|
|
||||||
|
// 获取到的值带px 正则匹配替换
|
||||||
|
let styL = getStyle(dragDom, 'left')
|
||||||
|
let styT = getStyle(dragDom, 'top')
|
||||||
|
|
||||||
|
if (styL.includes('%')) {
|
||||||
|
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
|
||||||
|
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
|
||||||
} else {
|
} else {
|
||||||
styL = +sty.left.replace(/\px/g, '')
|
styL = +styL.replace(/\px/g, '')
|
||||||
styT = +sty.top.replace(/\px/g, '')
|
styT = +styT.replace(/\px/g, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
document.onmousemove = function(e) {
|
document.onmousemove = function(e) {
|
||||||
// 通过事件委托,计算移动的距离
|
// 通过事件委托,计算移动的距离
|
||||||
const l = e.clientX - disX
|
let left = e.clientX - disX
|
||||||
const t = e.clientY - disY
|
let top = e.clientY - disY
|
||||||
|
|
||||||
|
// 边界处理
|
||||||
|
if (-(left) > minDragDomLeft) {
|
||||||
|
left = -minDragDomLeft
|
||||||
|
} else if (left > maxDragDomLeft) {
|
||||||
|
left = maxDragDomLeft
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-(top) > minDragDomTop) {
|
||||||
|
top = -minDragDomTop
|
||||||
|
} else if (top > maxDragDomTop) {
|
||||||
|
top = maxDragDomTop
|
||||||
|
}
|
||||||
|
|
||||||
// 移动当前元素
|
// 移动当前元素
|
||||||
dragDom.style.left = `${l + styL}px`
|
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
|
||||||
dragDom.style.top = `${t + styT}px`
|
|
||||||
|
|
||||||
// 将此时的位置传出去
|
|
||||||
// binding.value({x:e.pageX,y:e.pageY})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.onmouseup = function(e) {
|
document.onmouseup = function(e) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default {
|
||||||
componentMixin: 'Mixin',
|
componentMixin: 'Mixin',
|
||||||
backToTop: 'BackToTop',
|
backToTop: 'BackToTop',
|
||||||
dragDialog: 'Drag Dialog',
|
dragDialog: 'Drag Dialog',
|
||||||
|
dragKanban: 'Drag Kanban',
|
||||||
charts: 'Charts',
|
charts: 'Charts',
|
||||||
keyboardChart: 'Keyboard Chart',
|
keyboardChart: 'Keyboard Chart',
|
||||||
lineChart: 'Line Chart',
|
lineChart: 'Line Chart',
|
||||||
|
|
|
@ -19,6 +19,7 @@ export default {
|
||||||
componentMixin: '小组件',
|
componentMixin: '小组件',
|
||||||
backToTop: '返回顶部',
|
backToTop: '返回顶部',
|
||||||
dragDialog: '拖拽 Dialog',
|
dragDialog: '拖拽 Dialog',
|
||||||
|
dragKanban: '可拖拽看板',
|
||||||
charts: '图表',
|
charts: '图表',
|
||||||
keyboardChart: '键盘图表',
|
keyboardChart: '键盘图表',
|
||||||
lineChart: '折线图',
|
lineChart: '折线图',
|
||||||
|
|
|
@ -31,10 +31,10 @@ router.beforeEach((to, from, next) => {
|
||||||
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
|
router.addRoutes(store.getters.addRouters) // 动态添加可访问路由表
|
||||||
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
|
next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
|
||||||
})
|
})
|
||||||
}).catch(() => {
|
}).catch((err) => {
|
||||||
store.dispatch('FedLogOut').then(() => {
|
store.dispatch('FedLogOut').then(() => {
|
||||||
Message.error('Verification failed, please login again')
|
Message.error(err || 'Verification failed, please login again')
|
||||||
next({ path: '/login' })
|
next({ path: '/' })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -112,7 +112,8 @@ export const asyncRouterMap = [
|
||||||
{ path: 'count-to', component: _import('components-demo/countTo'), name: 'countTo-demo', meta: { title: 'countTo' }},
|
{ path: 'count-to', component: _import('components-demo/countTo'), name: 'countTo-demo', meta: { title: 'countTo' }},
|
||||||
{ path: 'mixin', component: _import('components-demo/mixin'), name: 'componentMixin-demo', meta: { title: 'componentMixin' }},
|
{ path: 'mixin', component: _import('components-demo/mixin'), name: 'componentMixin-demo', meta: { title: 'componentMixin' }},
|
||||||
{ path: 'back-to-top', component: _import('components-demo/backToTop'), name: 'backToTop-demo', meta: { title: 'backToTop' }},
|
{ path: 'back-to-top', component: _import('components-demo/backToTop'), name: 'backToTop-demo', meta: { title: 'backToTop' }},
|
||||||
{ path: 'drag-dialog', component: _import('components-demo/dragDialog'), name: 'dragDialog-demo', meta: { title: 'dragDialog' }}
|
{ path: 'drag-dialog', component: _import('components-demo/dragDialog'), name: 'dragDialog-demo', meta: { title: 'dragDialog' }},
|
||||||
|
{ path: 'drag-kanban', component: _import('components-demo/dragKanban'), name: 'dragKanban-demo', meta: { title: 'dragKanban' }}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const getters = {
|
const getters = {
|
||||||
sidebar: state => state.app.sidebar,
|
sidebar: state => state.app.sidebar,
|
||||||
language: state => state.app.language,
|
language: state => state.app.language,
|
||||||
|
device: state => state.app.device,
|
||||||
visitedViews: state => state.tagsView.visitedViews,
|
visitedViews: state => state.tagsView.visitedViews,
|
||||||
cachedViews: state => state.tagsView.cachedViews,
|
cachedViews: state => state.tagsView.cachedViews,
|
||||||
token: state => state.user.token,
|
token: state => state.user.token,
|
||||||
|
|
|
@ -3,8 +3,10 @@ import Cookies from 'js-cookie'
|
||||||
const app = {
|
const app = {
|
||||||
state: {
|
state: {
|
||||||
sidebar: {
|
sidebar: {
|
||||||
opened: !+Cookies.get('sidebarStatus')
|
opened: !+Cookies.get('sidebarStatus'),
|
||||||
|
withoutAnimation: false
|
||||||
},
|
},
|
||||||
|
device: 'desktop',
|
||||||
language: Cookies.get('language') || 'en'
|
language: Cookies.get('language') || 'en'
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
|
@ -15,6 +17,15 @@ const app = {
|
||||||
Cookies.set('sidebarStatus', 0)
|
Cookies.set('sidebarStatus', 0)
|
||||||
}
|
}
|
||||||
state.sidebar.opened = !state.sidebar.opened
|
state.sidebar.opened = !state.sidebar.opened
|
||||||
|
state.sidebar.withoutAnimation = false
|
||||||
|
},
|
||||||
|
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
||||||
|
Cookies.set('sidebarStatus', 1)
|
||||||
|
state.sidebar.opened = false
|
||||||
|
state.sidebar.withoutAnimation = withoutAnimation
|
||||||
|
},
|
||||||
|
TOGGLE_DEVICE: (state, device) => {
|
||||||
|
state.device = device
|
||||||
},
|
},
|
||||||
SET_LANGUAGE: (state, language) => {
|
SET_LANGUAGE: (state, language) => {
|
||||||
state.language = language
|
state.language = language
|
||||||
|
@ -25,6 +36,12 @@ const app = {
|
||||||
toggleSideBar({ commit }) {
|
toggleSideBar({ commit }) {
|
||||||
commit('TOGGLE_SIDEBAR')
|
commit('TOGGLE_SIDEBAR')
|
||||||
},
|
},
|
||||||
|
closeSideBar({ commit }, { withoutAnimation }) {
|
||||||
|
commit('CLOSE_SIDEBAR', withoutAnimation)
|
||||||
|
},
|
||||||
|
toggleDevice({ commit }, device) {
|
||||||
|
commit('TOGGLE_DEVICE', device)
|
||||||
|
},
|
||||||
setLanguage({ commit }, language) {
|
setLanguage({ commit }, language) {
|
||||||
commit('SET_LANGUAGE', language)
|
commit('SET_LANGUAGE', language)
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,13 @@ const user = {
|
||||||
reject('error')
|
reject('error')
|
||||||
}
|
}
|
||||||
const data = response.data
|
const data = response.data
|
||||||
|
|
||||||
|
if (data.roles && data.roles.length > 0) { // 验证返回的roles是否是一个非空数组
|
||||||
commit('SET_ROLES', data.roles)
|
commit('SET_ROLES', data.roles)
|
||||||
|
} else {
|
||||||
|
reject('getInfo: roles must be a non-null array !')
|
||||||
|
}
|
||||||
|
|
||||||
commit('SET_NAME', data.name)
|
commit('SET_NAME', data.name)
|
||||||
commit('SET_AVATAR', data.avatar)
|
commit('SET_AVATAR', data.avatar)
|
||||||
commit('SET_INTRODUCTION', data.introduction)
|
commit('SET_INTRODUCTION', data.introduction)
|
||||||
|
|
|
@ -7,10 +7,7 @@
|
||||||
}
|
}
|
||||||
// 侧边栏
|
// 侧边栏
|
||||||
.sidebar-container {
|
.sidebar-container {
|
||||||
.horizontal-collapse-transition {
|
transition: width 0.28s;
|
||||||
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
|
||||||
}
|
|
||||||
transition: width .28s;
|
|
||||||
width: 180px !important;
|
width: 180px !important;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
@ -20,15 +17,30 @@
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 1001;
|
z-index: 1001;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
//reset element-ui css
|
||||||
|
.horizontal-collapse-transition {
|
||||||
|
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
|
||||||
|
}
|
||||||
|
.scrollbar-wrapper {
|
||||||
|
height: calc(100% + 15px);
|
||||||
|
.el-scrollbar__view {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.is-horizontal {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
a {
|
a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.svg-icon {
|
.svg-icon {
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
.el-menu {
|
.el-menu {
|
||||||
border: none;
|
border: none;
|
||||||
|
height: 100%;
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,8 +59,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.el-submenu {
|
.el-submenu {
|
||||||
|
overflow: hidden;
|
||||||
&>.el-submenu__title {
|
&>.el-submenu__title {
|
||||||
padding-left: 10px !important;
|
padding-left: 10px !important;
|
||||||
|
.el-submenu__icon-arrow {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.el-menu--collapse {
|
||||||
|
.el-submenu {
|
||||||
|
&>.el-submenu__title {
|
||||||
&>span {
|
&>span {
|
||||||
height: 0;
|
height: 0;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
@ -56,14 +77,12 @@
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
.el-submenu__icon-arrow {
|
|
||||||
display: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.nest-menu .el-submenu>.el-submenu__title,
|
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
|
||||||
.el-submenu .el-menu-item {
|
.sidebar-container .el-submenu .el-menu-item {
|
||||||
min-width: 180px !important;
|
min-width: 180px !important;
|
||||||
background-color: $subMenuBg !important;
|
background-color: $subMenuBg !important;
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -73,4 +92,27 @@
|
||||||
.el-menu--collapse .el-menu .el-submenu {
|
.el-menu--collapse .el-menu .el-submenu {
|
||||||
min-width: 180px !important;
|
min-width: 180px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//适配移动端
|
||||||
|
.mobile {
|
||||||
|
.main-container {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
.sidebar-container {
|
||||||
|
transition: transform .28s;
|
||||||
|
width: 180px !important;
|
||||||
|
}
|
||||||
|
&.hideSidebar {
|
||||||
|
.sidebar-container {
|
||||||
|
transition-duration: 0.3s;
|
||||||
|
transform: translate3d(-180px, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.withoutAnimation {
|
||||||
|
.main-container,
|
||||||
|
.sidebar-container {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
<template>
|
||||||
|
<div class="components-container board">
|
||||||
|
<Kanban :key="1" class="kanban todo" :list="list1" :options="options" header-text="Todo"/>
|
||||||
|
<Kanban :key="2" class="kanban working" :list="list2" :options="options" header-text="Working"/>
|
||||||
|
<Kanban :key="3" class="kanban done" :list="list3" :options="options" header-text="Done"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import Kanban from '@/components/Kanban'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'dragKanban-demo',
|
||||||
|
components: {
|
||||||
|
Kanban
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {
|
||||||
|
group: 'mission'
|
||||||
|
},
|
||||||
|
list1: [
|
||||||
|
{ name: 'Mission', id: 1 },
|
||||||
|
{ name: 'Mission', id: 2 },
|
||||||
|
{ name: 'Mission', id: 3 },
|
||||||
|
{ name: 'Mission', id: 4 }
|
||||||
|
],
|
||||||
|
list2: [
|
||||||
|
{ name: 'Mission', id: 5 },
|
||||||
|
{ name: 'Mission', id: 6 },
|
||||||
|
{ name: 'Mission', id: 7 }
|
||||||
|
],
|
||||||
|
list3: [
|
||||||
|
{ name: 'Mission', id: 8 },
|
||||||
|
{ name: 'Mission', id: 9 },
|
||||||
|
{ name: 'Mission', id: 10 }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.board {
|
||||||
|
width: 1000px;
|
||||||
|
margin-left: 20px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-around;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.kanban {
|
||||||
|
&.todo {
|
||||||
|
.board-column-header {
|
||||||
|
background: #4A9FF9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.working {
|
||||||
|
.board-column-header {
|
||||||
|
background: #f9944a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.done {
|
||||||
|
.board-column-header {
|
||||||
|
background: #2ac06d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<el-table :data="list" style="width: 100%;padding-top: 15px;">
|
<el-table :data="list" style="width: 100%;padding-top: 15px;">
|
||||||
<el-table-column label="Order_No" show-overflow-tooltip>
|
<el-table-column label="Order_No" min-width="200">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{scope.row.order_no}}
|
{{scope.row.order_no}}
|
||||||
</template>
|
</template>
|
||||||
|
@ -42,7 +42,7 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
fetchData() {
|
fetchData() {
|
||||||
fetchList().then(response => {
|
fetchList().then(response => {
|
||||||
this.list = response.data.items.slice(0, 7)
|
this.list = response.data.items.slice(0, 8)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,10 +30,10 @@
|
||||||
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
|
<el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
|
||||||
<transaction-table></transaction-table>
|
<transaction-table></transaction-table>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="{span: 12}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}">
|
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}" style="margin-bottom:30px;">
|
||||||
<todo-list></todo-list>
|
<todo-list></todo-list>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="{span: 12}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}">
|
<el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 5}" style="margin-bottom:30px;" >
|
||||||
<box-card></box-card>
|
<box-card></box-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
|
<div class="app-wrapper" :class="classObj">
|
||||||
|
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"></div>
|
||||||
<sidebar class="sidebar-container"></sidebar>
|
<sidebar class="sidebar-container"></sidebar>
|
||||||
<div class="main-container">
|
<div class="main-container">
|
||||||
<navbar></navbar>
|
<navbar></navbar>
|
||||||
|
@ -11,6 +12,7 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { Navbar, Sidebar, AppMain, TagsView } from './components'
|
import { Navbar, Sidebar, AppMain, TagsView } from './components'
|
||||||
|
import ResizeMixin from './mixin/ResizeHandler'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'layout',
|
name: 'layout',
|
||||||
|
@ -20,9 +22,25 @@ export default {
|
||||||
AppMain,
|
AppMain,
|
||||||
TagsView
|
TagsView
|
||||||
},
|
},
|
||||||
|
mixins: [ResizeMixin],
|
||||||
computed: {
|
computed: {
|
||||||
sidebar() {
|
sidebar() {
|
||||||
return this.$store.state.app.sidebar
|
return this.$store.state.app.sidebar
|
||||||
|
},
|
||||||
|
device() {
|
||||||
|
return this.$store.state.app.device
|
||||||
|
},
|
||||||
|
classObj() {
|
||||||
|
return {
|
||||||
|
hideSidebar: !this.sidebar.opened,
|
||||||
|
withoutAnimation: this.sidebar.withoutAnimation,
|
||||||
|
mobile: this.device === 'mobile'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClickOutside() {
|
||||||
|
this.$store.dispatch('closeSideBar', { withoutAnimation: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,4 +54,13 @@ export default {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
.drawer-bg {
|
||||||
|
background: #000;
|
||||||
|
opacity: 0.3;
|
||||||
|
width: 100%;
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<scroll-bar>
|
<el-scrollbar wrapClass="scrollbar-wrapper">
|
||||||
<el-menu
|
<el-menu
|
||||||
mode="vertical"
|
mode="vertical"
|
||||||
:show-timeout="200"
|
:show-timeout="200"
|
||||||
|
@ -11,16 +11,15 @@
|
||||||
>
|
>
|
||||||
<sidebar-item :routes="permission_routers"></sidebar-item>
|
<sidebar-item :routes="permission_routers"></sidebar-item>
|
||||||
</el-menu>
|
</el-menu>
|
||||||
</scroll-bar>
|
</el-scrollbar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import SidebarItem from './SidebarItem'
|
import SidebarItem from './SidebarItem'
|
||||||
import ScrollBar from '@/components/ScrollBar'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { SidebarItem, ScrollBar },
|
components: { SidebarItem },
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
'permission_routers',
|
'permission_routers',
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
import store from '@/store'
|
||||||
|
|
||||||
|
const { body } = document
|
||||||
|
const WIDTH = 1024
|
||||||
|
const RATIO = 3
|
||||||
|
|
||||||
|
export default {
|
||||||
|
watch: {
|
||||||
|
$route(route) {
|
||||||
|
if (this.device === 'mobile' && this.sidebar.opened) {
|
||||||
|
store.dispatch('closeSideBar', { withoutAnimation: false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeMount() {
|
||||||
|
window.addEventListener('resize', this.resizeHandler)
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
const isMobile = this.isMobile()
|
||||||
|
if (isMobile) {
|
||||||
|
store.dispatch('toggleDevice', 'mobile')
|
||||||
|
store.dispatch('closeSideBar', { withoutAnimation: true })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isMobile() {
|
||||||
|
const rect = body.getBoundingClientRect()
|
||||||
|
return rect.width - RATIO < WIDTH
|
||||||
|
},
|
||||||
|
resizeHandler() {
|
||||||
|
if (!document.hidden) {
|
||||||
|
const isMobile = this.isMobile()
|
||||||
|
store.dispatch('toggleDevice', isMobile ? 'mobile' : 'desktop')
|
||||||
|
|
||||||
|
if (isMobile) {
|
||||||
|
store.dispatch('closeSideBar', { withoutAnimation: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue