This commit is contained in:
Pan 2017-04-20 14:32:41 +08:00
parent 7bedb8610c
commit 6eca8e4751
17 changed files with 325 additions and 341 deletions

View file

@ -35,6 +35,7 @@
},
"devDependencies": {
"autoprefixer": "6.7.2",
"axios-mock-adapter": "^1.8.1",
"babel-core": "6.22.1",
"babel-eslint": "7.1.1",
"babel-loader": "6.2.10",
@ -47,11 +48,11 @@
"copy-webpack-plugin": "4.0.1",
"css-loader": "0.26.1",
"eslint": "3.14.1",
"eslint-config-airbnb-base": "11.0.1",
"eslint-friendly-formatter": "2.0.7",
"eslint-import-resolver-webpack": "0.8.1",
"eslint-loader": "1.6.1",
"eslint-plugin-html": "2.0.0",
"eslint-config-airbnb-base": "11.0.1",
"eslint-import-resolver-webpack": "0.8.1",
"eslint-plugin-import": "2.2.0",
"eventsource-polyfill": "0.9.6",
"express": "4.14.1",
@ -61,26 +62,26 @@
"function-bind": "1.1.0",
"html-webpack-plugin": "2.28.0",
"http-proxy-middleware": "0.17.3",
"webpack-bundle-analyzer": "2.2.1",
"semver": "5.3.0",
"node-sass": "3.7.0",
"opn": "4.0.2",
"optimize-css-assets-webpack-plugin": "1.3.0",
"ora": "1.1.0",
"pushstate-server": "2.1.0",
"rimraf": "2.6.0",
"sass-loader": "4.0.2",
"script-loader": "0.7.0",
"semver": "5.3.0",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
"vue-loader": "11.3.4",
"vue-style-loader": "2.0.0",
"vue-template-compiler": "2.2.6",
"webpack": "2.2.1",
"webpack-bundle-analyzer": "2.2.1",
"webpack-dashboard": "0.2.1",
"webpack-dev-middleware": "1.10.0",
"webpack-hot-middleware": "2.16.1",
"webpack-merge": "2.6.1",
"webpack-dashboard": "0.2.1",
"node-sass": "3.7.0",
"pushstate-server": "2.1.0",
"sass-loader": "4.0.2",
"script-loader": "0.7.0",
"style-loader": "0.13.1"
"webpack-merge": "2.6.1"
},
"engines": {
"node": ">= 4.0.0",

View file

@ -57,17 +57,20 @@
}
},
accept: (file, done) => {
const token = this.$store.getters.token;
getToken(token).then(response => {
file.token = response.data.qiniu_token;
file.key = response.data.qiniu_key;
file.url = response.data.qiniu_url;
done();
})
/* 七牛*/
// const token = this.$store.getters.token;
// getToken(token).then(response => {
// file.token = response.data.qiniu_token;
// file.key = response.data.qiniu_key;
// file.url = response.data.qiniu_url;
// done();
// })
done();
},
sending: (file, xhr, formData) => {
formData.append('token', file.token);
formData.append('key', file.key);
/* 七牛*/
// formData.append('token', file.token);
// formData.append('key', file.key);
vm.initOnce = false;
}
});

View file

@ -7,32 +7,12 @@
<script>
export default {
name: 'Pane',
props: {
// split: {
// validator: function (value) {
// return ['vertical', 'horizontal'].indexOf(value) >= 0
// },
// required: true
// }
},
// computed:{
// classes () {
// return this.$parent.split
// },
// },
data() {
const classes = ['Pane', this.$parent.split, 'className'];
return {
classes: classes.join(' '),
percent: 50
}
},
created() {
// console.log(this.$parent.split)
},
methods: {
}
}
</script>

View file

@ -1,6 +1,28 @@
<template>
<div :class="classes" @mousedown="onMouseDown"></div>
</template>
<script>
export default {
props: {
split: {
validator(value) {
return ['vertical', 'horizontal'].indexOf(value) >= 0
},
required: true
},
onMouseDown: {
type: Function,
required: true
}
},
data() {
const classes = ['Resizer', this.split, 'className'];
return {
classes: classes.join(' ')
}
}
}
</script>
<style scoped>
.Resizer {
-moz-box-sizing: border-box;
@ -37,8 +59,6 @@
.Resizer.vertical {
width: 11px;
height: 100%;
/*margin: 0 -5px;*/
border-left: 5px solid rgba(255, 255, 255, 0);
border-right: 5px solid rgba(255, 255, 255, 0);
cursor: col-resize;
@ -49,27 +69,3 @@
border-right: 5px solid rgba(0, 0, 0, 0.5);
}
</style>
<script>
export default {
props: {
split: {
validator(value) {
return ['vertical', 'horizontal'].indexOf(value) >= 0
},
required: true
},
onMouseDown: {
type: Function,
required: true
}
},
data() {
const classes = ['Resizer', this.split, 'className'];
return {
classes: classes.join(' ')
}
},
methods: {}
}
</script>

View file

@ -1,175 +0,0 @@
<!--<template>-->
<!--<div :style="{ cursor, userSelect }" class="vue-splitter-container clearfix" @mouseup="onMouseUp"-->
<!--@mousemove="onMouseMove">-->
<!--<Pane split="vertical" :style="{ width: percent+'%' }" class="left-container splitter-pane">-->
<!--orange-->
<!--</Pane>-->
<!--<Resizer split="vertical" :onMouseDown="onMouseDown" @click="onClick"></Resizer>-->
<!--<div class="todel" :style="{ width: 100-percent+'%'}">-->
<!--<Pane split="horizontal" class="top-container">-->
<!--<div slot>apple banana</div>-->
<!--</Pane>-->
<!--<Resizer split="horizontal" :onMouseDown="onMouseDown" @click="onClick"></Resizer>-->
<!--<Pane split="horizontal" class="bottom-container">-->
<!--<div slot>apple banana</div>-->
<!--</Pane>-->
<!--</div>-->
<!--</div>-->
<!--</template>-->
<style scoped>
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.vue-splitter-container {
height: inherit;
display: flex;
}
</style>
<script>
/* eslint-disable */
import Resizer from './Resizer';
import vue from 'vue'
export default {
name: 'splitPane',
components: {Resizer},
props: {
margin: {
type: Number,
default: 10
}
},
data () {
return {
active: false,
percent: 50,
hasMoved: false,
panes: []
}
},
props: {
split: {
validator: function (value) {
return ['vertical', 'horizontal'].indexOf(value) >= 0
},
required: true
}
},
computed: {
userSelect () {
return this.active ? 'none' : ''
},
cursor () {
return this.active ? 'col-resize' : ''
},
// $paneItems () {
// return this.$children.filter(child => {
// console.log(child)
// })
// }
},
render(h){
const temp = [];
this.$slots.default.map((item, i) => {
if (item.tag && item.tag.toUpperCase().indexOf('PANE') >= 0) {
temp.push(item)
}
});
const newSlots = [];
const length = temp.length;
temp.map((item, index)=> {
newSlots.push(item)
if (index != length - 1) {
newSlots.push(
h('Resizer', {
props: {
split: this.split,
onMouseDown: this.onMouseDown
}
})
)
}
})
return h('div', {
on: {
mousemove: this.onMouseMove
}
}, [
h('div', {
'class': {
'vue-splitter-container': true
},
}, newSlots)
])
},
// beforeMount(){
// this.$slots.default=this.$slots.default.map((item, i) => {
// if (item.tag&&item.tag.toUpperCase().indexOf('PANE') >= 0) {
// return item
// }else{
// return null
// }
// })
//
// },
created(){
},
mounted(){
},
methods: {
onClick () {
if (!this.hasMoved) {
this.percent = 50;
this.$emit('resize');
}
},
onMouseDown () {
this.active = true;
this.hasMoved = false;
},
onMouseUp () {
this.active = false;
},
onMouseMove (e) {
if (e.buttons === 0 || e.which === 0) {
this.active = false;
}
if (this.active) {
let offset = 0;
let target = e.currentTarget;
while (target) {
offset += target.offsetLeft;
target = target.offsetParent;
}
const percent = Math.floor(((e.pageX - offset) / e.currentTarget.offsetWidth) * 10000) / 100;
if (percent > this.margin && percent < 100 - this.margin) {
this.percent = percent;
}
console.log(percent)
this.$children.map((v, i)=> {
if (i == 0) {
v.percent = percent
} else {
v.percent = 100 - percent
}
})
this.$emit('resize');
this.hasMoved = true;
}
}
}
}
</script>

View file

@ -1,7 +0,0 @@
import SplitPane from './a.vue';
import Pane from './Pane.vue';
export {
SplitPane,
Pane
}

View file

@ -66,7 +66,6 @@
mounted() {
const element = this.$el;
const elementOffset = element.getBoundingClientRect();
console.log(elementOffset.height)
// this.height = elementOffset.height+'px';
},
methods: {

View file

@ -1,30 +1,28 @@
<template>
<div class="twoDndList">
<div class="twoDndList-list" :style="{width:width1}">
<h3>{{list1Title}}</h3>
<draggable :list="list1" class="dragArea" :options="{group:'article'}">
<div class="list-complete-item" v-for="element in list1">
<div class="list-complete-item-handle">[{{element.id}}] {{element.title}}</div>
<div style="position:absolute;right:0px;">
<a style="float: left ;margin-top: -20px;margin-right:5px;" :href="'/article/edit/'+element.id" target="_blank"><i style="color:#20a0ff" class="el-icon-information"></i></a>
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
<div class="twoDndList">
<div class="twoDndList-list" :style="{width:width1}">
<h3>{{list1Title}}</h3>
<draggable :list="list1" class="dragArea" :options="{group:'article'}">
<div class="list-complete-item" v-for="element in list1">
<div class="list-complete-item-handle">[{{element.author}}] {{element.title}}</div>
<div style="position:absolute;right:0px;">
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
<i style="color:#ff4949" class="el-icon-delete"></i>
</span>
</div>
</div>
</draggable>
</div>
<div class="twoDndList-list" :style="{width:width2}">
<h3>{{list2Title}}</h3>
<draggable :list="filterList2" class="dragArea" :options="{group:'article'}">
<div class="list-complete-item" v-for="element in filterList2">
<div class='list-complete-item-handle2' @click="pushEle(element)"> [{{element.id}}] {{element.title}}</div>
<a style="float: right ;margin-top: -20px;" :href="'/article/edit/'+element.id" target="_blank"><i style="color:#20a0ff" class="el-icon-information"></i></a>
</div>
</draggable>
</div>
</div>
</draggable>
</div>
<div class="twoDndList-list" :style="{width:width2}">
<h3>{{list2Title}}</h3>
<draggable :list="filterList2" class="dragArea" :options="{group:'article'}">
<div class="list-complete-item" v-for="element in filterList2">
<div class='list-complete-item-handle2' @click="pushEle(element)"> [{{element.author}}] {{element.title}}</div>
</div>
</draggable>
</div>
</div>
</template>
<script>
@ -124,6 +122,7 @@
.list-complete-item {
cursor: pointer;
position: relative;
font-size: 14px;
padding: 5px 12px;
margin-top: 4px;
border: 1px solid #bfcbd9;

View file

@ -1,5 +1,9 @@
import axios from 'axios';
import Mock from 'mockjs';
Mock.mock(/\/article\/list/, {
import MockAdapter from 'axios-mock-adapter';
const mock = new MockAdapter(axios);
const articleList = {
'data|20': [{
id: '@id',
title: '@ctitle(10, 20)',
@ -7,6 +11,7 @@ Mock.mock(/\/article\/list/, {
display_time: '@datetime',
pageviews: '@integer(300, 5000)'
}]
})
export default Mock;
}
const data = JSON.stringify(Mock.mock(articleList))
mock.onGet('/article/list').reply(200, data);
export default mock;

View file

@ -20,7 +20,12 @@ import reset from '../views/login/reset';
const Tinymce = resolve => require(['../views/components/tinymce'], resolve);
const Markdown = resolve => require(['../views/components/markdown'], resolve);
const JsonEditor = resolve => require(['../views/components/jsoneditor'], resolve);
const DndList = resolve => require(['../views/components/dndlist'], resolve);
const AvatarUpload = resolve => require(['../views/components/avatarupload'], resolve);
const Dropzone = resolve => require(['../views/components/dropzone'], resolve);
const Sticky = resolve => require(['../views/components/sticky'], resolve);
const SplitPane = resolve => require(['../views/components/splitpane'], resolve);
/* charts*/
const KeyboardChart = resolve => require(['../views/charts/keyboard'], resolve);
@ -72,9 +77,12 @@ export default new Router({
children: [
{ path: 'tinymce', component: Tinymce, name: '富文本编辑器' },
{ path: 'markdown', component: Markdown, name: 'Markdown' },
{ path: 'jsoneditor', component: JsonEditor, name: 'json编辑器' },
{ path: 'avatarupload', component: AvatarUpload, name: '头像上传' }
{ path: 'jsoneditor', component: JsonEditor, name: 'JSON编辑器' },
{ path: 'dndlist', component: DndList, name: '列表拖拽' },
{ path: 'splitpane', component: SplitPane, name: 'SplitPane' },
{ path: 'avatarupload', component: AvatarUpload, name: '头像上传' },
{ path: 'dropzone', component: Dropzone, name: 'Dropzone' },
{ path: 'sticky', component: Sticky, name: 'Sticky' }
]
},
{

View file

@ -84,6 +84,13 @@ code {
padding: 20px 10px;
margin-bottom: 20px;
display: block;
a {
color: #337ab7;
cursor: pointer;
&:hover {
color: rgb(32, 160, 255);
}
}
}
.fade-enter-active,

View file

@ -1,17 +1,14 @@
<template>
<div class="components-container">
<code>公司做的后台主要是一个cms系统公司也是已自媒体为核心的所以富文本是后台很核心的功能在选择富文本的过程中也走了不少的弯路市面上常见的富文本都基本用过了最终选择了tinymce</code>
<code>拖拽https://github.com/SortableJS/Vue.Draggable Vue.Draggable</code>
<div class="editor-container">
<TwoDndList :list1="list1" :list2="list2" :list1Title="头条列表" list2Title="文章池"></TwoDndList>
<DndList :list1="list1" :list2="list2" list1Title="头条列表" list2Title="文章池" />
</div>
<!--<div class='editor-content'>
{{content}}
</div>-->
</div>
</template>
<script>
import DndList from 'components/twoDndList'
import { getList } from 'api/article';
export default {
components: { DndList },
data() {
@ -20,8 +17,18 @@
list2: []
}
},
created() {
this.fetchData();
},
methods: {
fetchData() {
this.listLoading = true;
getList(this.listQuery).then(response => {
this.list1 = response.data.splice(0, 5);
this.list2 = response.data;
console.log(this.list1, this.list2)
})
}
}
};
</script>

View file

@ -0,0 +1,28 @@
<template>
<div class="components-container">
<code>https://github.com/rowanwins/vue-dropzone
由于我司业务有特殊需求而且要传七牛 所以没用第三方 选择了自己封装
</code>
<div class="editor-container">
<Dropzone v-on:dropzone-removedFile="dropzoneR" v-on:dropzone-success="dropzoneS" id="myVueDropzone"
url="https://httpbin.org/post"></Dropzone>
</div>
</div>
</template>
<script>
import Dropzone from 'components/Dropzone';
export default {
components: { Dropzone },
methods: {
dropzoneS(file) {
this.$message({ message: '上传成功', type: 'success' });
},
dropzoneR(file) {
this.$message({ message: '删除成功', type: 'success' });
}
}
};
</script>

View file

@ -0,0 +1,62 @@
<template>
<div class="components-container" >
<code>splitPane 如果你用过<a href='http://codepen.io/' target='_blank'>codepen</a>,<a href='https://jsfiddle.net/' target='_blank'>jsfiddle</a>就不会陌生了
暂还没有时间开源封装好日后补上
</code>
<splitPane v-on:resize="resize" split="vertical">
<template slot="paneL">
<div class="left-container"></div>
</template>
<template slot="paneR">
<split-pane split="horizontal">
<template slot="paneL">
<div class="top-container"></div>
</template>
<template slot="paneR">
<div class="bottom-container">
</div>
</template>
</split-pane>
</template>
</splitPane>
</div>
</template>
<script>
import splitPane from 'components/SplitPane'
export default {
components: { splitPane },
methods: {
resize() {
console.log('resize')
}
}
};
</script>
<style scoped>
.components-container{
position: relative;
height: 100vh;
}
.left-container {
background-color: #F38181;
height:100%;
}
.right-container {
background-color: #FCE38A;
height: 200px;
}
.top-container {
background-color: #FCE38A;
width: 100%;
height: 100%;
}
.bottom-container {
width: 100%;
background-color: #95E1D3;
height: 100%;
}
</style>

View file

@ -0,0 +1,125 @@
<template>
<div>
<Sticky className="sub-navbar">
<el-dropdown trigger="click">
<el-button>
平台<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-border" slot="dropdown">
<el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
<el-checkbox v-for="item in platformsOptions" :label="item.key" :key="item.key">
{{item.name}}
</el-checkbox>
</el-checkbox-group>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown trigger="click">
<el-button>
外链<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding no-border" style="width:300px" slot="dropdown">
<el-input placeholder="请输入内容" v-model="url">
<template slot="prepend">填写url</template>
</el-input>
</el-dropdown-menu>
</el-dropdown>
<div class="time-container">
<el-date-picker v-model="time" type="datetime" :picker-options="pickerOptions" format="yyyy-MM-dd HH:mm:ss" placeholder="发布时间">
</el-date-picker>
</div>
<el-button style="margin-left: 10px;" type="success">发布
</el-button>
</Sticky>
<div class="components-container">
<code>Sticky header 当页面滚动到预设的位置会吸附在顶部</code>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
<div>我是占位</div>
</div>
</div>
</template>
<script>
import Sticky from 'components/Sticky';
export default {
components: { Sticky },
data() {
return {
time: '',
url: '',
platforms: ['a-platform'],
platformsOptions: [
{ key: 'a-platform', name: '平台A' },
{ key: 'b-platform', name: '平台B' },
{ key: 'c-platform', name: '平台C' }
],
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now();
}
}
}
}
};
</script>
<style scoped>
.time-container {
display: inline-block;
}
</style>

View file

@ -1,61 +1,7 @@
<template>
<div class="errorpage-container"> 404
<splitPane v-on:resize="resize" split="vertical">
<template slot="paneL">
<div class="left-container"></div>
</template>
<template slot="paneR">
<splitPane split="horizontal">
<template slot="paneL">
<div class="top-container"></div>
</template>
<template slot="paneR">
<div class="bottom-container">
</div>
</template>
</splitPane>
</template>
</splitPane>
</div>
<div>404</div>
</template>
<script>
import splitPane from 'components/SplitPane/SplitPane'
export default {
components: { splitPane },
methods: {
resize() {
console.log('resize')
}
}
};
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.errorpage-container{
position: relative;
height: 100vh;
}
.left-container {
background-color: #F38181;
height:100%;
}
.right-container {
background-color: #FCE38A;
height: 200px;
}
.top-container {
background-color: #FCE38A;
width: 100%;
height: 100%;
}
.bottom-container {
width: 100%;
background-color: #95E1D3;
height: 100%;
}
</style>

View file

@ -33,7 +33,7 @@
</div>
</template>
<script>
import { getList } from 'api/article'
import { getList } from 'api/article';
export default {
data() {
return {