Compare commits

...

17 Commits

Author SHA1 Message Date
Pan
9b5f0160af [release] 3.6.6 2018-05-02 14:46:31 +08:00
花裤衩
0e4ea0871c feat[sidebar]: add resonsive sidebar (#636) 2018-05-02 14:43:20 +08:00
Pan
88429bd809 Fix typo 2018-05-02 10:29:21 +08:00
xVirus
62a9565f86 siderbar.css add namespace (#622)
1. 原来的普通导航栏样式会使用 siderbar 的样式,背景黑底。
2. 修改后,sidebar 样式不变,普通导航栏可以正常使用。
2018-05-02 10:27:48 +08:00
Pan
f663b23b29 perf[el-dragDialog]: add the verification of moving edges 2018-04-30 14:58:08 +08:00
Pan
afd255d5ba fix[el-dargDialog]: fixed drag bug in IE 2018-04-29 22:38:59 +08:00
Pan
b7c8079350 doc: update package.json 2018-04-26 17:31:37 +08:00
Yuga Sun
543a9928cf feat: add draggable kanban using vue-draggable (#625) 2018-04-25 22:05:07 +08:00
Pan
8f37950589 perf[Tinymce]: remove autosize plugin 2018-04-19 18:33:12 +08:00
Pan
6821eac35b fix[complexTable]: fixed export_json_to_excel bug 2018-04-19 13:24:35 +08:00
Pan
cc5e62d5f5 fix[contextmenu]: adjust contextmenu z-index 2018-04-18 17:00:43 +08:00
Pan
0cccc636b8 perf[sidebar.css]: perf collapse transition Pan committed 2018-04-18 15:24:38 +08:00
Pan
563ce873bd perf[Tinymce]: remove fullpage plugin 2018-04-17 10:19:01 +08:00
Pan
44e94b2d16 doc: add gitter 2018-04-16 18:09:53 +08:00
Pan
a160848367 fix typo 2018-04-15 21:01:03 +08:00
Pan
7099e6a3eb doc: update readme 2018-04-13 13:36:07 +08:00
花裤衩
14fee27a92 feature: add drag dialog (#477) 2018-04-13 13:32:53 +08:00
21 changed files with 432 additions and 15 deletions

View File

@@ -30,6 +30,8 @@ English | [简体中文](./README.zh-CN.md)
- [Documentation](https://panjiachen.github.io/vue-element-admin-site/#/)
- [Gitter](https://gitter.im/vue-element-admin/discuss)
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
- [Donate](https://panjiachen.github.io/vue-element-admin-site/#/donate)
@@ -86,6 +88,7 @@ You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) l
- Form example
- Two-step login
- SplitPane
- Drag Dialog
- Dropzone
- Sticky
- CountTo

View File

@@ -30,6 +30,8 @@
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/zh-cn/)
- [Gitter讨论组](https://gitter.im/vue-element-admin/discuss)
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
- [Donate](https://panjiachen.github.io/vue-element-admin-site/#/zh-cn/donate)
@@ -52,7 +54,6 @@
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
响应需求开了一个qq群 `591724180` 方便大家交流
或者加入该群主 **[圈子](https://jianshiapp.com/circles/1209)** 楼主会经常分享一些技术相关的东西
@@ -99,6 +100,7 @@
- Form example
- 二步登录
- SplitPane
- 拖拽 Dialog
- Dropzone
- Sticky
- CountTo

View File

@@ -1,10 +1,9 @@
{
"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",
"author": "Pan <panfree23@gmail.com>",
"license": "MIT",
"private": true,
"scripts": {
"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",
@@ -12,6 +11,20 @@
"lint": "eslint --ext .js,.vue src",
"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": {
"axios": "0.17.1",
"clipboard": "1.7.1",
@@ -37,7 +50,7 @@
"vue-multiselect": "2.0.8",
"vue-router": "3.0.1",
"vue-splitpane": "1.0.2",
"vuedraggable": "2.15.0",
"vuedraggable": "^2.16.0",
"vuex": "3.0.1",
"xlsx": "^0.11.16"
},

View File

@@ -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>

View File

@@ -2,6 +2,6 @@
// Detail plugins list see https://www.tinymce.com/docs/plugins/
// Custom builds see https://www.tinymce.com/download/custom-builds/
const plugins = ['advlist anchor autolink autoresize autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullpage fullscreen hr image imagetools importcss insertdatetime legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
export default plugins

View File

@@ -0,0 +1,74 @@
export default{
bind(el, binding) {
const dialogHeaderEl = el.querySelector('.el-dialog__header')
const dragDom = el.querySelector('.el-dialog')
dialogHeaderEl.style.cssText += ';cursor:move;'
dragDom.style.cssText += ';top:0px;'
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
function getStyle(dom, attr) {
if (dom.currentStyle) {
return dom.currentStyle[attr]
} else {
return getComputedStyle(dom, false)[attr]
}
}
dialogHeaderEl.onmousedown = (e) => {
// 鼠标按下,计算当前元素距离可视区的距离
const disX = e.clientX - dialogHeaderEl.offsetLeft
const disY = e.clientY - dialogHeaderEl.offsetTop
const dragDomWidth = dragDom.offsetWidth
const dragDomheight = dragDom.offsetHeight
const screenWidth = document.body.clientWidth
const screenHeight = document.body.clientHeight
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 {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
document.onmousemove = function(e) {
// 通过事件委托,计算移动的距离
let left = e.clientX - disX
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.cssText += `;left:${left + styL}px;top:${top + styT}px;`
}
document.onmouseup = function(e) {
document.onmousemove = null
document.onmouseup = null
}
}
}
}

View File

@@ -0,0 +1,13 @@
import drag from './drag'
const install = function(Vue) {
Vue.directive('el-drag-dialog', drag)
}
if (window.Vue) {
window['el-drag-dialog'] = drag
Vue.use(install); // eslint-disable-line
}
drag.install = install
export default drag

View File

@@ -18,6 +18,8 @@ export default {
countTo: 'CountTo',
componentMixin: 'Mixin',
backToTop: 'BackToTop',
dragDialog: 'Drag Dialog',
dragKanban: 'Drag Kanban',
charts: 'Charts',
keyboardChart: 'Keyboard Chart',
lineChart: 'Line Chart',

View File

@@ -18,6 +18,8 @@ export default {
countTo: 'CountTo',
componentMixin: '小组件',
backToTop: '返回顶部',
dragDialog: '拖拽 Dialog',
dragKanban: '可拖拽看板',
charts: '图表',
keyboardChart: '键盘图表',
lineChart: '折线图',

View File

@@ -111,7 +111,9 @@ export const asyncRouterMap = [
{ path: 'sticky', component: _import('components-demo/sticky'), name: 'sticky-demo', meta: { title: 'sticky' }},
{ 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: '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-kanban', component: _import('components-demo/dragKanban'), name: 'dragKanban-demo', meta: { title: 'dragKanban' }}
]
},

View File

@@ -1,6 +1,7 @@
const getters = {
sidebar: state => state.app.sidebar,
language: state => state.app.language,
device: state => state.app.device,
visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,

View File

@@ -3,8 +3,10 @@ import Cookies from 'js-cookie'
const app = {
state: {
sidebar: {
opened: !+Cookies.get('sidebarStatus')
opened: !+Cookies.get('sidebarStatus'),
withoutAnimation: false
},
device: 'desktop',
language: Cookies.get('language') || 'en'
},
mutations: {
@@ -15,6 +17,15 @@ const app = {
Cookies.set('sidebarStatus', 0)
}
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) => {
state.language = language
@@ -25,6 +36,12 @@ const app = {
toggleSideBar({ commit }) {
commit('TOGGLE_SIDEBAR')
},
closeSideBar({ commit }, { withoutAnimation }) {
commit('CLOSE_SIDEBAR', withoutAnimation)
},
toggleDevice({ commit }, device) {
commit('TOGGLE_DEVICE', device)
},
setLanguage({ commit }, language) {
commit('SET_LANGUAGE', language)
}

View File

@@ -1,12 +1,17 @@
#app {
// 主体区域
.main-container {
min-height: 100%;
transition: margin-left .28s;
margin-left: 180px;
}
// 侧边栏
.sidebar-container {
.horizontal-collapse-transition {
transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
}
transition: width .28s;
width: 180px !important;
height: 100%;
@@ -29,6 +34,7 @@
width: 100% !important;
}
}
.hideSidebar {
.sidebar-container {
width: 36px !important;
@@ -59,8 +65,9 @@
}
}
}
.nest-menu .el-submenu>.el-submenu__title,
.el-submenu .el-menu-item {
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
.sidebar-container .el-submenu .el-menu-item {
min-width: 180px !important;
background-color: $subMenuBg !important;
&:hover {
@@ -70,4 +77,29 @@
.el-menu--collapse .el-menu .el-submenu {
min-width: 180px !important;
}
//适配移动端
.mobile {
.main-container {
margin-left: 0px;
}
.sidebar-container {
top: 50px;
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;
}
}
}

View File

@@ -26,7 +26,7 @@ export function validateUpperCase(str) {
}
/* 大小写字母*/
export function validatAlphabets(str) {
export function validateAlphabets(str) {
const reg = /^[A-Za-z]+$/
return reg.test(str)
}

View File

@@ -0,0 +1,43 @@
<template>
<div class="components-container">
<el-button type="primary" @click="dialogTableVisible = true">open a Drag Dialog</el-button>
<el-dialog v-el-drag-dialog title="Shipping address" :visible.sync="dialogTableVisible">
<el-table :data="gridData">
<el-table-column property="date" label="Date" width="150"></el-table-column>
<el-table-column property="name" label="Name" width="200"></el-table-column>
<el-table-column property="address" label="Address"></el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script>
import elDragDialog from '@/directive/el-dragDialog' // base on element-ui
export default {
name: 'dragDialog-demo',
directives: { elDragDialog },
data() {
return {
dialogTableVisible: false,
gridData: [{
date: '2016-05-02',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}, {
date: '2016-05-04',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}, {
date: '2016-05-01',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}, {
date: '2016-05-03',
name: 'John Smith',
address: 'No.1518, Jinshajiang Road, Putuo District'
}]
}
}
}
</script>

View File

@@ -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>

View File

@@ -335,7 +335,11 @@ export default {
const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
const data = this.formatJson(filterVal, this.list)
excel.export_json_to_excel(tHeader, data, 'table-list')
excel.export_json_to_excel({
header: tHeader,
data,
filename: 'table-list'
})
this.downloadLoading = false
})
},

View File

@@ -1,5 +1,5 @@
<template>
<div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
<div class="app-wrapper" :class="classObj">
<sidebar class="sidebar-container"></sidebar>
<div class="main-container">
<navbar></navbar>
@@ -11,6 +11,7 @@
<script>
import { Navbar, Sidebar, AppMain, TagsView } from './components'
import ResizeMixin from './mixin/ResizeHandler'
export default {
name: 'layout',
@@ -20,9 +21,20 @@ export default {
AppMain,
TagsView
},
mixins: [ResizeMixin],
computed: {
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'
}
}
}
}

View File

@@ -2,7 +2,6 @@
<scroll-bar>
<el-menu
mode="vertical"
:collapse-transition="false"
:show-timeout="200"
:default-active="$route.path"
:collapse="isCollapse"

View File

@@ -156,7 +156,7 @@ export default {
.contextmenu {
margin: 0;
background: #fff;
z-index: 2;
z-index: 100;
position: absolute;
list-style-type: none;
padding: 5px 0;

View File

@@ -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 })
}
}
}
}
}