全局代码格式 优化

This commit is contained in:
Pan 2017-07-06 17:56:17 +08:00
parent 622a8c3a69
commit de992c50a6
73 changed files with 3156 additions and 3151 deletions

View File

@ -1,13 +1,13 @@
<template> <template>
<div id="app"> <div id="app">
<router-view></router-view> <router-view></router-view>
</div> </div>
</template> </template>
<script> <script>
export default{ export default{
name: 'APP' name: 'APP'
} }
</script> </script>
<style lang="scss"> <style lang="scss">

View File

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 160 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -1,6 +1,7 @@
<template> <template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div> <div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';

View File

@ -1,6 +1,7 @@
<template> <template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div> <div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';

View File

@ -1,6 +1,7 @@
<template> <template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div> <div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';

View File

@ -1,6 +1,7 @@
<template> <template>
<div :class="className" :id="id" :style="{height:height,width:width}"></div> <div :class="className" :id="id" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';

View File

@ -1,62 +1,63 @@
<template> <template>
<div :ref="id" :action="url" class="dropzone" :id="id"> <div :ref="id" :action="url" class="dropzone" :id="id">
<input type="file" name="file"> <input type="file" name="file">
</div> </div>
</template> </template>
<script> <script>
import Dropzone from 'dropzone'; import Dropzone from 'dropzone';
import 'dropzone/dist/dropzone.css'; import 'dropzone/dist/dropzone.css';
// import { getToken } from 'api/qiniu'; // import { getToken } from 'api/qiniu';
Dropzone.autoDiscover = false; Dropzone.autoDiscover = false;
export default { export default {
data() { data() {
return { return {
dropzone: '', dropzone: '',
initOnce: true initOnce: true
} }
}, },
mounted() { mounted() {
const element = document.getElementById(this.id); const element = document.getElementById(this.id);
const vm = this; const vm = this;
this.dropzone = new Dropzone(element, { this.dropzone = new Dropzone(element, {
clickable: this.clickable, clickable: this.clickable,
thumbnailWidth: this.thumbnailWidth, thumbnailWidth: this.thumbnailWidth,
thumbnailHeight: this.thumbnailHeight, thumbnailHeight: this.thumbnailHeight,
maxFiles: this.maxFiles, maxFiles: this.maxFiles,
maxFilesize: this.maxFilesize, maxFilesize: this.maxFilesize,
dictRemoveFile: 'Remove', dictRemoveFile: 'Remove',
addRemoveLinks: this.showRemoveLink, addRemoveLinks: this.showRemoveLink,
acceptedFiles: this.acceptedFiles, acceptedFiles: this.acceptedFiles,
autoProcessQueue: this.autoProcessQueue, autoProcessQueue: this.autoProcessQueue,
dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload', dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
dictMaxFilesExceeded: '只能一个图', dictMaxFilesExceeded: '只能一个图',
previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>', previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
init() { init() {
const val = vm.defaultImg; const val = vm.defaultImg;
if (!val) return; if (!val) return;
if (Array.isArray(val)) { if (Array.isArray(val)) {
if (val.length === 0) return; if (val.length === 0) return;
val.map((v, i) => { val.map((v, i) => {
const mockFile = { name: 'name' + i, size: 12345, url: v }; const mockFile = { name: 'name' + i, size: 12345, url: v };
this.options.addedfile.call(this, mockFile);
this.options.thumbnail.call(this, mockFile, v);
mockFile.previewElement.classList.add('dz-success');
mockFile.previewElement.classList.add('dz-complete');
vm.initOnce = false;
return true;
})
} else {
const mockFile = { name: 'name', size: 12345, url: val };
this.options.addedfile.call(this, mockFile); this.options.addedfile.call(this, mockFile);
this.options.thumbnail.call(this, mockFile, val); this.options.thumbnail.call(this, mockFile, v);
mockFile.previewElement.classList.add('dz-success'); mockFile.previewElement.classList.add('dz-success');
mockFile.previewElement.classList.add('dz-complete'); mockFile.previewElement.classList.add('dz-complete');
vm.initOnce = false; vm.initOnce = false;
} return true;
}, })
accept: (file, done) => { } else {
const mockFile = { name: 'name', size: 12345, url: val };
this.options.addedfile.call(this, mockFile);
this.options.thumbnail.call(this, mockFile, val);
mockFile.previewElement.classList.add('dz-success');
mockFile.previewElement.classList.add('dz-complete');
vm.initOnce = false;
}
},
accept: (file, done) => {
/* 七牛*/ /* 七牛*/
// const token = this.$store.getters.token; // const token = this.$store.getters.token;
// getToken(token).then(response => { // getToken(token).then(response => {
@ -65,142 +66,142 @@
// file.url = response.data.qiniu_url; // file.url = response.data.qiniu_url;
// done(); // done();
// }) // })
done(); done();
}, },
sending: (file, xhr, formData) => { sending: (file, xhr, formData) => {
/* 七牛*/ /* 七牛*/
console.log(file, xhr, formData) console.log(file, xhr, formData)
// formData.append('token', file.token); // formData.append('token', file.token);
// formData.append('key', file.key); // formData.append('key', file.key);
vm.initOnce = false; vm.initOnce = false;
}
});
if (this.couldPaste) {
document.addEventListener('paste', this.pasteImg)
} }
});
this.dropzone.on('success', file => { if (this.couldPaste) {
vm.$emit('dropzone-success', file, vm.dropzone.element) document.addEventListener('paste', this.pasteImg)
}); }
this.dropzone.on('addedfile', file => {
vm.$emit('dropzone-fileAdded', file) this.dropzone.on('success', file => {
}); vm.$emit('dropzone-success', file, vm.dropzone.element)
this.dropzone.on('removedfile', file => { });
vm.$emit('dropzone-removedFile', file) this.dropzone.on('addedfile', file => {
}); vm.$emit('dropzone-fileAdded', file)
this.dropzone.on('error', (file, error, xhr) => { });
vm.$emit('dropzone-error', file, error, xhr) this.dropzone.on('removedfile', file => {
}); vm.$emit('dropzone-removedFile', file)
this.dropzone.on('successmultiple', (file, error, xhr) => { });
vm.$emit('dropzone-successmultiple', file, error, xhr) this.dropzone.on('error', (file, error, xhr) => {
}); vm.$emit('dropzone-error', file, error, xhr)
});
this.dropzone.on('successmultiple', (file, error, xhr) => {
vm.$emit('dropzone-successmultiple', file, error, xhr)
});
},
methods: {
removeAllFiles() {
this.dropzone.removeAllFiles(true)
}, },
methods: { processQueue() {
removeAllFiles() { this.dropzone.processQueue()
this.dropzone.removeAllFiles(true) },
}, pasteImg(event) {
processQueue() { const items = (event.clipboardData || event.originalEvent.clipboardData).items;
this.dropzone.processQueue() if (items[0].kind === 'file') {
}, this.dropzone.addFile(items[0].getAsFile())
pasteImg(event) { }
const items = (event.clipboardData || event.originalEvent.clipboardData).items; },
if (items[0].kind === 'file') { initImages(val) {
this.dropzone.addFile(items[0].getAsFile()) if (!val) return;
} if (Array.isArray(val)) {
}, val.map((v, i) => {
initImages(val) { const mockFile = { name: 'name' + i, size: 12345, url: v };
if (!val) return;
if (Array.isArray(val)) {
val.map((v, i) => {
const mockFile = { name: 'name' + i, size: 12345, url: v };
this.dropzone.options.addedfile.call(this.dropzone, mockFile);
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v);
mockFile.previewElement.classList.add('dz-success');
mockFile.previewElement.classList.add('dz-complete');
return true
})
} else {
const mockFile = { name: 'name', size: 12345, url: val };
this.dropzone.options.addedfile.call(this.dropzone, mockFile); this.dropzone.options.addedfile.call(this.dropzone, mockFile);
this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val); this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v);
mockFile.previewElement.classList.add('dz-success'); mockFile.previewElement.classList.add('dz-success');
mockFile.previewElement.classList.add('dz-complete'); mockFile.previewElement.classList.add('dz-complete');
} return true
} })
} else {
}, const mockFile = { name: 'name', size: 12345, url: val };
destroyed() { this.dropzone.options.addedfile.call(this.dropzone, mockFile);
document.removeEventListener('paste', this.pasteImg); this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val);
this.dropzone.destroy(); mockFile.previewElement.classList.add('dz-success');
}, mockFile.previewElement.classList.add('dz-complete');
watch: {
defaultImg(val) {
if (val.length === 0) {
this.initOnce = false;
return;
}
if (!this.initOnce) return;
this.initImages(val);
this.initOnce = false;
}
},
props: {
id: {
type: String,
required: true
},
url: {
type: String,
required: true
},
clickable: {
type: Boolean,
default: true
},
defaultMsg: {
type: String,
default: '上传图片'
},
acceptedFiles: {
type: String
},
thumbnailHeight: {
type: Number,
default: 200
},
thumbnailWidth: {
type: Number,
default: 200
},
showRemoveLink: {
type: Boolean,
default: true
},
maxFilesize: {
type: Number,
default: 2
},
maxFiles: {
type: Number,
default: 3
},
autoProcessQueue: {
type: Boolean,
default: true
},
useCustomDropzoneOptions: {
type: Boolean,
default: false
},
defaultImg: {
default: false
},
couldPaste: {
default: false
} }
} }
},
destroyed() {
document.removeEventListener('paste', this.pasteImg);
this.dropzone.destroy();
},
watch: {
defaultImg(val) {
if (val.length === 0) {
this.initOnce = false;
return;
}
if (!this.initOnce) return;
this.initImages(val);
this.initOnce = false;
}
},
props: {
id: {
type: String,
required: true
},
url: {
type: String,
required: true
},
clickable: {
type: Boolean,
default: true
},
defaultMsg: {
type: String,
default: '上传图片'
},
acceptedFiles: {
type: String
},
thumbnailHeight: {
type: Number,
default: 200
},
thumbnailWidth: {
type: Number,
default: 200
},
showRemoveLink: {
type: Boolean,
default: true
},
maxFilesize: {
type: Number,
default: 2
},
maxFiles: {
type: Number,
default: 3
},
autoProcessQueue: {
type: Boolean,
default: true
},
useCustomDropzoneOptions: {
type: Boolean,
default: false
},
defaultImg: {
default: false
},
couldPaste: {
default: false
}
} }
}
</script> </script>
<style scoped> <style scoped>

View File

@ -1,51 +1,56 @@
<template> <template>
<div> <div>
<el-badge :is-dot="true" style="line-height: 30px;" @click.native="dialogTableVisible=true"> <el-badge :is-dot="true" style="line-height: 30px;" @click.native="dialogTableVisible=true">
<el-button size="small" type="primary"> <el-button size="small" type="primary">
<svg t="1492682037685" class="bug-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1863" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z" p-id="1864"></path></svg> <svg t="1492682037685" class="bug-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1863"
</el-button> xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
</el-badge> <path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
<el-dialog title="bug日志" :visible.sync="dialogTableVisible"> p-id="1864"></path>
<el-table :data="logsList"> </svg>
<el-table-column label="message"> </el-button>
<template scope="scope"> </el-badge>
<div>msg:{{ scope.row.err.message }}</div> <el-dialog title="bug日志" :visible.sync="dialogTableVisible">
<br/> <el-table :data="logsList">
<div>url: {{scope.row.url}}</div> <el-table-column label="message">
</template> <template scope="scope">
</el-table-column> <div>msg:{{ scope.row.err.message }}</div>
<el-table-column label="stack"> <br/>
<template scope="scope"> <div>url: {{scope.row.url}}</div>
{{ scope.row.err.stack}} </template>
</template> </el-table-column>
</el-table-column> <el-table-column label="stack">
<template scope="scope">
{{ scope.row.err.stack}}
</template>
</el-table-column>
</el-table> </el-table>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'errLog', name: 'errLog',
props: { props: {
logsList: { logsList: {
type: Array type: Array
} }
}, },
data() { data() {
return { return {
dialogTableVisible: false dialogTableVisible: false
}
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.bug-svg { .bug-svg {
width: 1em; width: 1em;
height: 1em; height: 1em;
vertical-align: -0.15em; vertical-align: -0.15em;
fill: currentColor; fill: currentColor;
overflow: hidden; overflow: hidden;
} }
</style> </style>

View File

@ -1,36 +1,46 @@
<template> <template>
<div> <div>
<svg t="1492500959545" @click="toggleClick" class="wscn-icon hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z" p-id="1692"></path><path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z" p-id="1693"></path><path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z" p-id="1694"></path></svg> <svg t="1492500959545" @click="toggleClick" class="wscn-icon hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
</div> version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
<path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
p-id="1692"></path>
<path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
p-id="1693"></path>
<path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
p-id="1694"></path>
</svg>
</div>
</template> </template>
<script> <script>
export default { export default {
name: 'hamburger', name: 'hamburger',
props: { props: {
isActive: { isActive: {
type: Boolean, type: Boolean,
default: false default: false
}, },
toggleClick: { toggleClick: {
type: Function, type: Function,
default: null default: null
}
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.hamburger { .hamburger {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
width: 20px; width: 20px;
height: 20px; height: 20px;
transform: rotate(0deg); transform: rotate(0deg);
transition: .38s; transition: .38s;
transform-origin: 50% 50%; transform-origin: 50% 50%;
} }
.hamburger.is-active {
transform: rotate(90deg); .hamburger.is-active {
} transform: rotate(90deg);
}
</style> </style>

View File

@ -1,147 +1,147 @@
<template> <template>
<div class="material-input__component" :class="computedClasses"> <div class="material-input__component" :class="computedClasses">
<input v-if="type === 'email'" type="email" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy" <input v-if="type === 'email'" type="email" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)"
@blur="handleFocus(false)" @input="handleModelInput"> @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'url'" type="url" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy" <input v-if="type === 'url'" type="url" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)"
@blur="handleFocus(false)" @input="handleModelInput"> @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'number'" type="number" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy" <input v-if="type === 'number'" type="number" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :max="max" :min="min" :minlength="minlength" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :max="max" :min="min" :minlength="minlength" :maxlength="maxlength"
:maxlength="maxlength" :required="required" @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput"> :required="required" @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'password'" type="password" class="material-input" :name="name" :id="id" :placeholder="placeholder" <input v-if="type === 'password'" type="password" class="material-input" :name="name" :id="id" :placeholder="placeholder"
v-model="valueCopy" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :max="max" :min="min" v-model="valueCopy" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :max="max" :min="min" :required="required"
:required="required" @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput"> @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'tel'" type="tel" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy" <input v-if="type === 'tel'" type="tel" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :required="required" @focus="handleFocus(true)"
@blur="handleFocus(false)" @input="handleModelInput"> @blur="handleFocus(false)" @input="handleModelInput">
<input v-if="type === 'text'" type="text" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy" <input v-if="type === 'text'" type="text" class="material-input" :name="name" :id="id" :placeholder="placeholder" v-model="valueCopy"
:readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :minlength="minlength" :maxlength="maxlength" :readonly="readonly" :disabled="disabled" :autocomplete="autocomplete" :minlength="minlength" :maxlength="maxlength" :required="required"
:required="required" @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput"> @focus="handleFocus(true)" @blur="handleFocus(false)" @input="handleModelInput">
<span class="material-input-bar"></span> <span class="material-input-bar"></span>
<label class="material-label"> <label class="material-label">
<slot></slot> <slot></slot>
</label> </label>
<div v-if="errorMessages" class="material-errors"> <div v-if="errorMessages" class="material-errors">
<div v-for="error in computedErrors" class="material-error"> <div v-for="error in computedErrors" class="material-error" :key='error'>
{{ error }} {{ error }}
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue // source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
export default { export default {
name: 'material-input', name: 'material-input',
computed: { computed: {
computedErrors() { computedErrors() {
return typeof this.errorMessages === 'string' return typeof this.errorMessages === 'string'
? [this.errorMessages] : this.errorMessages ? [this.errorMessages] : this.errorMessages
}, },
computedClasses() { computedClasses() {
return { return {
'material--active': this.focus, 'material--active': this.focus,
'material--disabled': this.disabled, 'material--disabled': this.disabled,
'material--has-errors': Boolean(!this.valid || (this.errorMessages && this.errorMessages.length)), 'material--has-errors': Boolean(!this.valid || (this.errorMessages && this.errorMessages.length)),
'material--raised': Boolean(this.focus || this.valueCopy || // has value 'material--raised': Boolean(this.focus || this.valueCopy || // has value
(this.placeholder && !this.valueCopy)) // has placeholder (this.placeholder && !this.valueCopy)) // has placeholder
}
}
},
data() {
return {
valueCopy: null,
focus: false,
valid: true
}
},
beforeMount() {
// Here we are following the Vue2 convention on custom v-model:
// https://github.com/vuejs/vue/issues/2873#issuecomment-223759341
this.copyValue(this.value)
},
methods: {
handleModelInput(event) {
this.$emit('input', event.target.value, event)
this.handleValidation()
},
handleFocus(focused) {
this.focus = focused
},
handleValidation() {
this.valid = this.$el ? this.$el.querySelector('.material-input').validity.valid : this.valid
},
copyValue(value) {
this.valueCopy = value
this.handleValidation()
}
},
watch: {
value(newValue) {
this.copyValue(newValue)
}
},
props: {
id: {
type: String,
default: null
},
name: {
type: String,
default: null
},
type: {
type: String,
default: 'text'
},
value: {
default: null
},
placeholder: {
type: String,
default: null
},
readonly: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
min: {
type: String,
default: null
},
max: {
type: String,
default: null
},
minlength: {
type: Number,
default: null
},
maxlength: {
type: Number,
default: null
},
required: {
type: Boolean,
default: true
},
autocomplete: {
type: String,
default: 'off'
},
errorMessages: {
type: [Array, String],
default: null
}
} }
} }
},
data() {
return {
valueCopy: null,
focus: false,
valid: true
}
},
beforeMount() {
// Here we are following the Vue2 convention on custom v-model:
// https://github.com/vuejs/vue/issues/2873#issuecomment-223759341
this.copyValue(this.value)
},
methods: {
handleModelInput(event) {
this.$emit('input', event.target.value, event)
this.handleValidation()
},
handleFocus(focused) {
this.focus = focused
},
handleValidation() {
this.valid = this.$el ? this.$el.querySelector('.material-input').validity.valid : this.valid
},
copyValue(value) {
this.valueCopy = value
this.handleValidation()
}
},
watch: {
value(newValue) {
this.copyValue(newValue)
}
},
props: {
id: {
type: String,
default: null
},
name: {
type: String,
default: null
},
type: {
type: String,
default: 'text'
},
value: {
default: null
},
placeholder: {
type: String,
default: null
},
readonly: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
min: {
type: String,
default: null
},
max: {
type: String,
default: null
},
minlength: {
type: Number,
default: null
},
maxlength: {
type: Number,
default: null
},
required: {
type: Boolean,
default: true
},
autocomplete: {
type: String,
default: 'off'
},
errorMessages: {
type: [Array, String],
default: null
}
}
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>

View File

@ -6,106 +6,109 @@
</template> </template>
<script> <script>
import 'simplemde/dist/simplemde.min.css' import 'simplemde/dist/simplemde.min.css';
import SimpleMDE from 'simplemde' import SimpleMDE from 'simplemde';
export default {
name: 'Sticky', export default {
props: { name: 'Sticky',
value: String, props: {
id: { value: String,
type: String, id: {
default: 'markdown-editor' type: String,
}, default: 'markdown-editor'
autofocus: {
type: Boolean,
default: false
},
placeholder: {
type: String,
default: ''
},
height: {
type: Number,
default: 150
},
zIndex: {
type: Number,
default: 10
},
toolbar: {
type: Array
}
},
data() {
return {
simplemde: null,
hasChange: false
};
},
watch: {
value(val) {
if (val === this.simplemde.value() && !this.hasChange) return;
this.simplemde.value(val);
}
},
mounted() {
this.simplemde = new SimpleMDE({
element: document.getElementById(this.id),
autofocus: this.autofocus,
toolbar: this.toolbar,
spellChecker: false,
insertTexts: {
link: ['[', ']( )']
}, },
// hideIcons: ['guide', 'heading', 'quote', 'image', 'preview', 'side-by-side', 'fullscreen'], autofocus: {
placeholder: this.placeholder type: Boolean,
}); default: false
if (this.value) { },
this.simplemde.value(this.value); placeholder: {
} type: String,
this.simplemde.codemirror.on('change', () => { default: ''
if (this.hasChange) { },
this.hasChange = true height: {
type: Number,
default: 150
},
zIndex: {
type: Number,
default: 10
},
toolbar: {
type: Array
} }
this.$emit('input', this.simplemde.value()); },
}); data() {
}, return {
destroyed() { simplemde: null,
this.simplemde = null; hasChange: false
} };
},
watch: {
value(val) {
if (val === this.simplemde.value() && !this.hasChange) return;
this.simplemde.value(val);
}
},
mounted() {
this.simplemde = new SimpleMDE({
element: document.getElementById(this.id),
autofocus: this.autofocus,
toolbar: this.toolbar,
spellChecker: false,
insertTexts: {
link: ['[', ']( )']
},
// hideIcons: ['guide', 'heading', 'quote', 'image', 'preview', 'side-by-side', 'fullscreen'],
placeholder: this.placeholder
});
if (this.value) {
this.simplemde.value(this.value);
}
this.simplemde.codemirror.on('change', () => {
if (this.hasChange) {
this.hasChange = true
}
this.$emit('input', this.simplemde.value());
});
},
destroyed() {
this.simplemde = null;
}
}; };
</script> </script>
<style> <style>
.simplemde-container .CodeMirror { .simplemde-container .CodeMirror {
/*height: 150px;*/ /*height: 150px;*/
min-height: 150px; min-height: 150px;
} }
.simplemde-container .CodeMirror-scroll{
min-height: 150px;
}
.simplemde-container .CodeMirror-code{ .simplemde-container .CodeMirror-scroll {
padding-bottom: 40px; min-height: 150px;
} }
.simplemde-container .editor-statusbar {
display: none;
}
.simplemde-container .CodeMirror .CodeMirror-code .cm-link { .simplemde-container .CodeMirror-code {
color: #1482F0; padding-bottom: 40px;
} }
.simplemde-container .CodeMirror .CodeMirror-code .cm-string.cm-url { .simplemde-container .editor-statusbar {
color: #2d3b4d; display: none;
font-weight: bold; }
}
.simplemde-container .CodeMirror .CodeMirror-code .cm-formatting-link-string.cm-url { .simplemde-container .CodeMirror .CodeMirror-code .cm-link {
padding: 0 2px; color: #1482F0;
font-weight: bold; }
color: #E61E1E;
} .simplemde-container .CodeMirror .CodeMirror-code .cm-string.cm-url {
color: #2d3b4d;
font-weight: bold;
}
.simplemde-container .CodeMirror .CodeMirror-code .cm-formatting-link-string.cm-url {
padding: 0 2px;
font-weight: bold;
color: #E61E1E;
}
</style> </style>

View File

@ -1,145 +1,140 @@
<template> <template>
<div class="pan-item" :style="{zIndex:zIndex,height:height,width:width}"> <div class="pan-item" :style="{zIndex:zIndex,height:height,width:width}">
<div class="pan-info"> <div class="pan-info">
<div class="pan-info-roles-container"> <div class="pan-info-roles-container">
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
<img class="pan-thumb" :src="image"> <img class="pan-thumb" :src="image">
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'PanThumb', name: 'PanThumb',
props: { props: {
image: { image: {
type: String, type: String,
required: true required: true
},
zIndex: {
type: Number,
default: 100
},
width: {
type: String,
default: '150px'
},
height: {
type: String,
default: '150px'
}
}, },
data() { zIndex: {
return {}; type: Number,
default: 100
},
width: {
type: String,
default: '150px'
},
height: {
type: String,
default: '150px'
} }
}; }
};
</script> </script>
<style scoped> <style scoped>
.pan-item { .pan-item {
width: 200px; width: 200px;
height: 200px; height: 200px;
border-radius: 50%; border-radius: 50%;
display: inline-block; display: inline-block;
position: relative; position: relative;
cursor: default; cursor: default;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
} }
.pan-info-roles-container { .pan-info-roles-container {
padding: 20px; padding: 20px;
text-align: center; text-align: center;
} }
.pan-thumb { .pan-thumb {
width: 100%; width: 100%;
height: 100%; height: 100%;
background-size: 100%; background-size: 100%;
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
position: absolute; position: absolute;
transform-origin: 95% 40%; transform-origin: 95% 40%;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
.pan-thumb:after { .pan-thumb:after {
content: ''; content: '';
width: 8px; width: 8px;
height: 8px; height: 8px;
position: absolute; position: absolute;
border-radius: 50%; border-radius: 50%;
top: 40%; top: 40%;
left: 95%; left: 95%;
margin: -4px 0 0 -4px; margin: -4px 0 0 -4px;
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%); background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9); box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
} }
.pan-info { .pan-info {
position: absolute; position: absolute;
width: inherit; width: inherit;
height: inherit; height: inherit;
border-radius: 50%; border-radius: 50%;
overflow: hidden; overflow: hidden;
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05); box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
} }
.pan-info h3 { .pan-info h3 {
color: #fff; color: #fff;
text-transform: uppercase; text-transform: uppercase;
position: relative; position: relative;
letter-spacing: 2px; letter-spacing: 2px;
font-size: 18px; font-size: 18px;
margin: 0 60px; margin: 0 60px;
padding: 22px 0 0 0; padding: 22px 0 0 0;
height: 85px; height: 85px;
font-family: 'Open Sans', Arial, sans-serif; font-family: 'Open Sans', Arial, sans-serif;
text-shadow: 0 0 1px #fff, text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
0 1px 2px rgba(0, 0, 0, 0.3); }
}
.pan-info p { .pan-info p {
color: #fff; color: #fff;
padding: 10px 5px; padding: 10px 5px;
font-style: italic; font-style: italic;
margin: 0 30px; margin: 0 30px;
font-size: 12px; font-size: 12px;
border-top: 1px solid rgba(255, 255, 255, 0.5); border-top: 1px solid rgba(255, 255, 255, 0.5);
} }
.pan-info p a { .pan-info p a {
display: block; display: block;
color: #333; color: #333;
width: 80px; width: 80px;
height: 80px; height: 80px;
background: rgba(255, 255, 255, 0.3); background: rgba(255, 255, 255, 0.3);
border-radius: 50%; border-radius: 50%;
color: #fff; color: #fff;
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
text-transform: uppercase; text-transform: uppercase;
font-size: 9px; font-size: 9px;
letter-spacing: 1px; letter-spacing: 1px;
padding-top: 24px; padding-top: 24px;
margin: 7px auto 0; margin: 7px auto 0;
font-family: 'Open Sans', Arial, sans-serif; font-family: 'Open Sans', Arial, sans-serif;
opacity: 0; opacity: 0;
transition: transform 0.3s ease-in-out 0.2s, transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
opacity 0.3s ease-in-out 0.2s, transform: translateX(60px) rotate(90deg);
background 0.2s linear 0s; }
transform: translateX(60px) rotate(90deg);
}
.pan-info p a:hover { .pan-info p a:hover {
background: rgba(255, 255, 255, 0.5); background: rgba(255, 255, 255, 0.5);
} }
.pan-item:hover .pan-thumb { .pan-item:hover .pan-thumb {
transform: rotate(-110deg); transform: rotate(-110deg);
} }
.pan-item:hover .pan-info p a { .pan-item:hover .pan-info p a {
opacity: 1; opacity: 1;
transform: translateX(0px) rotate(0deg); transform: translateX(0px) rotate(0deg);
} }
</style> </style>

View File

@ -1,50 +1,53 @@
<template> <template>
<svg @click='click' class="icon screenfull" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
<svg @click='click' class="icon screenfull" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" t="1497503607356" viewBox="0 0 1024 1024" version="1.1" p-id="4109" :fill='fill' :width="width" :height="height"><path d="M604.157933 512l204.484208 204.484208 82.942037-82.942037c10.364045-10.952446 26.498514-13.83817 40.309054-8.067746 13.249769 5.742794 22.465664 18.99154 22.465664 33.977859l0 258.042008c0 20.168342-16.695241 36.863582-36.863582 36.863582L659.452283 954.357873c-14.986319 0-28.236088-9.215896-33.977859-23.025413-5.770424-13.249769-2.885723-29.384237 8.067746-39.748283l82.942037-82.942037L512 604.157933 307.515792 808.642141l82.942037 82.942037c10.952446 10.364045 13.83817 26.498514 8.067746 39.748283-5.742794 13.809517-18.99154 23.025413-33.977859 23.025413L106.504686 954.357873c-20.168342 0-36.863582-16.695241-36.863582-36.863582L69.641103 659.452283c0-14.986319 9.215896-28.236088 23.025413-33.977859 13.249769-5.770424 29.384237-2.8847 39.748283 8.067746l82.942037 82.942037 204.484208-204.484208L215.357859 307.515792l-82.942037 82.942037c-6.890944 6.918573-16.10684 10.952446-25.911136 10.952446-4.593622 0-9.804297-1.14815-13.83817-2.8847-13.809517-5.742794-23.025413-18.99154-23.025413-33.977859L69.641103 106.504686c0-20.168342 16.695241-36.863582 36.863582-36.863582L364.546693 69.641103c14.986319 0 28.236088 9.215896 33.977859 23.025413 5.770424 13.249769 2.8847 29.384237-8.067746 39.748283l-82.942037 82.942037 204.484208 204.484208L716.484208 215.357859l-82.942037-82.942037c-10.952446-10.364045-13.83817-26.498514-8.067746-39.748283 5.742794-13.809517 18.99154-23.025413 33.977859-23.025413l258.042008 0c20.168342 0 36.863582 16.695241 36.863582 36.863582l0 258.042008c0 14.986319-9.215896 28.236088-22.465664 33.977859-4.593622 1.736551-9.804297 2.8847-14.397918 2.8847-9.804297 0-19.020192-4.033873-25.911136-10.952446l-82.942037-82.942037L604.157933 512z" p-id="4110"/></svg> t="1497503607356" viewBox="0 0 1024 1024" version="1.1" p-id="4109" :fill='fill' :width="width" :height="height">
<path d="M604.157933 512l204.484208 204.484208 82.942037-82.942037c10.364045-10.952446 26.498514-13.83817 40.309054-8.067746 13.249769 5.742794 22.465664 18.99154 22.465664 33.977859l0 258.042008c0 20.168342-16.695241 36.863582-36.863582 36.863582L659.452283 954.357873c-14.986319 0-28.236088-9.215896-33.977859-23.025413-5.770424-13.249769-2.885723-29.384237 8.067746-39.748283l82.942037-82.942037L512 604.157933 307.515792 808.642141l82.942037 82.942037c10.952446 10.364045 13.83817 26.498514 8.067746 39.748283-5.742794 13.809517-18.99154 23.025413-33.977859 23.025413L106.504686 954.357873c-20.168342 0-36.863582-16.695241-36.863582-36.863582L69.641103 659.452283c0-14.986319 9.215896-28.236088 23.025413-33.977859 13.249769-5.770424 29.384237-2.8847 39.748283 8.067746l82.942037 82.942037 204.484208-204.484208L215.357859 307.515792l-82.942037 82.942037c-6.890944 6.918573-16.10684 10.952446-25.911136 10.952446-4.593622 0-9.804297-1.14815-13.83817-2.8847-13.809517-5.742794-23.025413-18.99154-23.025413-33.977859L69.641103 106.504686c0-20.168342 16.695241-36.863582 36.863582-36.863582L364.546693 69.641103c14.986319 0 28.236088 9.215896 33.977859 23.025413 5.770424 13.249769 2.8847 29.384237-8.067746 39.748283l-82.942037 82.942037 204.484208 204.484208L716.484208 215.357859l-82.942037-82.942037c-10.952446-10.364045-13.83817-26.498514-8.067746-39.748283 5.742794-13.809517 18.99154-23.025413 33.977859-23.025413l258.042008 0c20.168342 0 36.863582 16.695241 36.863582 36.863582l0 258.042008c0 14.986319-9.215896 28.236088-22.465664 33.977859-4.593622 1.736551-9.804297 2.8847-14.397918 2.8847-9.804297 0-19.020192-4.033873-25.911136-10.952446l-82.942037-82.942037L604.157933 512z"
p-id="4110" />
</svg>
</template> </template>
<script> <script>
import screenfull from 'screenfull'; import screenfull from 'screenfull';
export default { export default {
name: 'hamburger', name: 'hamburger',
props: { props: {
width: { width: {
type: Number, type: Number,
default: 22 default: 22
},
height: {
type: Number,
default: 22
},
fill: {
type: String,
default: '#48576a'
}
}, },
data() { height: {
return { type: Number,
isFullscreen: false default: 22
}
}, },
methods: { fill: {
click() { type: String,
if (!screenfull.enabled) { default: '#48576a'
this.$message({ }
message: 'you browser can not work', },
type: 'warning' data() {
}); return {
return false; isFullscreen: false
} }
screenfull.toggle(); },
methods: {
click() {
if (!screenfull.enabled) {
this.$message({
message: 'you browser can not work',
type: 'warning'
});
return false;
} }
screenfull.toggle();
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.screenfull { .screenfull {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
vertical-align: -0.15em; vertical-align: -0.15em;
} }
</style> </style>

View File

@ -1,41 +1,44 @@
<template> <template>
<div :class="classes"> <div :class="classes">
<slot></slot> <slot></slot>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'Pane', name: 'Pane',
data() { data() {
const classes = ['Pane', this.$parent.split, 'className']; const classes = ['Pane', this.$parent.split, 'className'];
return { return {
classes: classes.join(' '), classes: classes.join(' '),
percent: 50 percent: 50
}
}
} }
}
}
</script> </script>
<style> <style scoped>
.splitter-pane.vertical.splitter-paneL{ .splitter-pane.vertical.splitter-paneL {
position: absolute; position: absolute;
left: 0px; left: 0px;
height: 100%; height: 100%;
} }
.splitter-pane.vertical.splitter-paneR{
position: absolute; .splitter-pane.vertical.splitter-paneR {
right: 0px; position: absolute;
height: 100%; right: 0px;
} height: 100%;
.splitter-pane.horizontal.splitter-paneL{ }
position: absolute;
top: 0px; .splitter-pane.horizontal.splitter-paneL {
width: 100%; position: absolute;
} top: 0px;
.splitter-pane.horizontal.splitter-paneR{ width: 100%;
position: absolute; }
bottom: 0px;
width: 100%; .splitter-pane.horizontal.splitter-paneR {
} position: absolute;
bottom: 0px;
width: 100%;
}
</style> </style>

View File

@ -1,71 +1,72 @@
<template> <template>
<div :class="classes" @mousedown="onMouseDown"></div> <div :class="classes" @mousedown="onMouseDown"></div>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
split: { split: {
validator(value) { validator(value) {
return ['vertical', 'horizontal'].indexOf(value) >= 0 return ['vertical', 'horizontal'].indexOf(value) >= 0
},
required: true
}, },
onMouseDown: { required: true
type: Function,
required: true
}
}, },
data() { onMouseDown: {
const classes = ['Resizer', this.split, 'className']; type: Function,
return { required: true
classes: classes.join(' ') }
} },
data() {
const classes = ['Resizer', this.split, 'className'];
return {
classes: classes.join(' ')
} }
} }
}
</script> </script>
<style scoped> <style scoped>
.Resizer { .Resizer {
-moz-box-sizing: border-box; -moz-box-sizing: border-box;
-webkit-box-sizing: border-box; -webkit-box-sizing: border-box;
box-sizing: border-box; box-sizing: border-box;
background: #000; background: #000;
position: absolute; position: absolute;
opacity: .2; opacity: .2;
z-index: 1; z-index: 1;
/*-moz-background-clip: padding;*/ /*-moz-background-clip: padding;*/
/*-webkit-background-clip: padding;*/ /*-webkit-background-clip: padding;*/
/*background-clip: padding-box;*/ /*background-clip: padding-box;*/
} }
/*.Resizer:hover {*/
/*-webkit-transition: all 2s ease;*/
/*transition: all 2s ease;*/
/*}*/
/*.Resizer:hover {*/ .Resizer.horizontal {
/*-webkit-transition: all 2s ease;*/ height: 11px;
/*transition: all 2s ease;*/ margin: -5px 0;
/*}*/ border-top: 5px solid rgba(255, 255, 255, 0);
border-bottom: 5px solid rgba(255, 255, 255, 0);
cursor: row-resize;
width: 100%;
}
.Resizer.horizontal { .Resizer.horizontal:hover {
height: 11px; border-top: 5px solid rgba(0, 0, 0, 0.5);
margin: -5px 0; border-bottom: 5px solid rgba(0, 0, 0, 0.5);
border-top: 5px solid rgba(255, 255, 255, 0); }
border-bottom: 5px solid rgba(255, 255, 255, 0);
cursor: row-resize;
width: 100%;
}
.Resizer.horizontal:hover { .Resizer.vertical {
border-top: 5px solid rgba(0, 0, 0, 0.5); width: 11px;
border-bottom: 5px solid rgba(0, 0, 0, 0.5); height: 100%;
} border-left: 5px solid rgba(255, 255, 255, 0);
border-right: 5px solid rgba(255, 255, 255, 0);
cursor: col-resize;
}
.Resizer.vertical { .Resizer.vertical:hover {
width: 11px; border-left: 5px solid rgba(0, 0, 0, 0.5);
height: 100%; border-right: 5px solid rgba(0, 0, 0, 0.5);
border-left: 5px solid rgba(255, 255, 255, 0); }
border-right: 5px solid rgba(255, 255, 255, 0);
cursor: col-resize;
}
.Resizer.vertical:hover {
border-left: 5px solid rgba(0, 0, 0, 0.5);
border-right: 5px solid rgba(0, 0, 0, 0.5);
}
</style> </style>

View File

@ -1,111 +1,111 @@
<template> <template>
<div ref :style="{ cursor, userSelect}" class="vue-splitter-container clearfix" @mouseup="onMouseUp" <div ref :style="{ cursor, userSelect}" class="vue-splitter-container clearfix" @mouseup="onMouseUp" @mousemove="onMouseMove">
@mousemove="onMouseMove"> <pane class="splitter-pane splitter-paneL" :split="split" :style="{ [type]: percent+'%'}">
<Pane class="splitter-pane splitter-paneL" :split="split" :style="{ [type]: percent+'%'}"> <slot name="paneL"></slot>
<slot name="paneL"></slot> </pane>
</Pane> <resizer :style="{ [resizeType]: percent+'%'}" :split="split" :onMouseDown="onMouseDown" @click="onClick"></resizer>
<Resizer :style="{ [resizeType]: percent+'%'}" :split="split" :onMouseDown="onMouseDown" <pane class="splitter-pane splitter-paneR" :split="split" :style="{ [type]: 100-percent+'%'}">
@click="onClick"></Resizer> <slot name="paneR"></slot>
<Pane class="splitter-pane splitter-paneR" :split="split" :style="{ [type]: 100-percent+'%'}"> </pane>
<slot name="paneR"></slot> </div>
</Pane>
</div>
</template> </template>
<style scoped>
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.vue-splitter-container {
height: 100%;
/*display: flex;*/
position: relative;
}
</style>
<script> <script>
import Resizer from './Resizer'; import Resizer from './Resizer';
import Pane from './Pane'; import Pane from './Pane';
export default { export default {
name: 'splitPane', name: 'splitPane',
components: { Resizer, Pane }, components: { Resizer, Pane },
props: { props: {
margin: { margin: {
type: Number, type: Number,
default: 10 default: 10
},
split: {
validator(value) {
return ['vertical', 'horizontal'].indexOf(value) >= 0
}, },
split: { required: true
validator(value) { }
return ['vertical', 'horizontal'].indexOf(value) >= 0 },
}, data() {
required: true return {
active: false,
hasMoved: false,
height: null,
percent: 50,
type: this.split === 'vertical' ? 'width' : 'height',
resizeType: this.split === 'vertical' ? 'left' : 'top'
}
},
computed: {
userSelect() {
return this.active ? 'none' : ''
},
cursor() {
return this.active ? 'col-resize' : ''
}
},
methods: {
onClick() {
if (!this.hasMoved) {
this.percent = 50;
this.$emit('resize');
} }
}, },
data() { onMouseDown() {
return { this.active = true;
active: false, this.hasMoved = false;
hasMoved: false,
height: null,
percent: 50,
type: this.split === 'vertical' ? 'width' : 'height',
resizeType: this.split === 'vertical' ? 'left' : 'top'
}
}, },
computed: { onMouseUp() {
userSelect() { this.active = false;
return this.active ? 'none' : ''
},
cursor() {
return this.active ? 'col-resize' : ''
}
}, },
methods: { onMouseMove(e) {
onClick() { if (e.buttons === 0 || e.which === 0) {
if (!this.hasMoved) {
this.percent = 50;
this.$emit('resize');
}
},
onMouseDown() {
this.active = true;
this.hasMoved = false;
},
onMouseUp() {
this.active = false; this.active = false;
}, }
onMouseMove(e) { if (this.active) {
if (e.buttons === 0 || e.which === 0) { let offset = 0;
this.active = false; let target = e.currentTarget;
} if (this.split === 'vertical') {
if (this.active) { while (target) {
let offset = 0; offset += target.offsetLeft;
let target = e.currentTarget; target = target.offsetParent;
if (this.split === 'vertical') {
while (target) {
offset += target.offsetLeft;
target = target.offsetParent;
}
} else {
while (target) {
offset += target.offsetTop;
target = target.offsetParent;
}
} }
} else {
while (target) {
offset += target.offsetTop;
target = target.offsetParent;
}
}
const currentPage = this.split === 'vertical' ? e.pageX : e.pageY; const currentPage = this.split === 'vertical' ? e.pageX : e.pageY;
const targetOffset = this.split === 'vertical' ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight; const targetOffset = this.split === 'vertical' ? e.currentTarget.offsetWidth : e.currentTarget.offsetHeight;
const percent = Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100; const percent = Math.floor(((currentPage - offset) / targetOffset) * 10000) / 100;
if (percent > this.margin && percent < 100 - this.margin) { if (percent > this.margin && percent < 100 - this.margin) {
this.percent = percent; this.percent = percent;
}
this.$emit('resize');
this.hasMoved = true;
} }
this.$emit('resize');
this.hasMoved = true;
} }
} }
} }
}
</script> </script>
<style scoped>
.clearfix:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
.vue-splitter-container {
height: 100%;
/*display: flex;*/
position: relative;
}
</style>

View File

@ -1,73 +1,74 @@
<template> <template>
<div :style="{height:height+'px',zIndex:zIndex}"> <div :style="{height:height+'px',zIndex:zIndex}">
<div :class="className" :style="{top:stickyTop+'px',zIndex:zIndex,position:position,width:width,height:height+'px'}"> <div :class="className" :style="{top:stickyTop+'px',zIndex:zIndex,position:position,width:width,height:height+'px'}">
<slot> <slot>
<div>sticky</div> <div>sticky</div>
</slot> </slot>
</div>
</div> </div>
</div>
</template> </template>
<script>
export default {
name: 'Sticky',
props: {
stickyTop: {
type: Number,
default: 0
},
zIndex: {
type: Number,
default: 1
},
className: {
type: String
}
},
data() {
return {
active: false,
position: '',
currentTop: '',
width: undefined,
height: undefined,
child: null,
stickyHeight: 0
}; <script>
export default {
name: 'Sticky',
props: {
stickyTop: {
type: Number,
default: 0
}, },
methods: { zIndex: {
sticky() { type: Number,
if (this.active) { default: 1
return
}
this.position = 'fixed';
this.active = true;
this.width = this.width + 'px';
},
reset() {
if (!this.active) {
return
}
this.position = '';
this.width = 'auto'
this.active = false
},
handleScroll() {
this.width = this.$el.getBoundingClientRect().width;
const offsetTop = this.$el.getBoundingClientRect().top;
if (offsetTop <= this.stickyTop) {
this.sticky();
return
}
this.reset()
}
}, },
mounted() { className: {
this.height = this.$el.getBoundingClientRect().height; type: String
window.addEventListener('scroll', this.handleScroll);
},
destroyed() {
window.removeEventListener('scroll', this.handleScroll);
} }
}; },
data() {
return {
active: false,
position: '',
currentTop: '',
width: undefined,
height: undefined,
child: null,
stickyHeight: 0
};
},
methods: {
sticky() {
if (this.active) {
return
}
this.position = 'fixed';
this.active = true;
this.width = this.width + 'px';
},
reset() {
if (!this.active) {
return
}
this.position = '';
this.width = 'auto'
this.active = false
},
handleScroll() {
this.width = this.$el.getBoundingClientRect().width;
const offsetTop = this.$el.getBoundingClientRect().top;
if (offsetTop <= this.stickyTop) {
this.sticky();
return
}
this.reset()
}
},
mounted() {
this.height = this.$el.getBoundingClientRect().height;
window.addEventListener('scroll', this.handleScroll);
},
destroyed() {
window.removeEventListener('scroll', this.handleScroll);
}
};
</script> </script>

View File

@ -6,79 +6,79 @@
<script> <script>
// import { getToken, upload } from 'api/qiniu'; // // import { getToken, upload } from 'api/qiniu'; //
export default { export default {
name: 'tinymce', name: 'tinymce',
props: { props: {
id: { id: {
type: String, type: String,
default: 'tinymceEditor' default: 'tinymceEditor'
}, },
value: { value: {
type: String, type: String,
default: '' default: ''
}, },
toolbar: { toolbar: {
type: Array, type: Array,
required: false, required: false,
default() { default() {
return ['removeformat undo redo | bullist numlist | outdent indent | forecolor | fullscreen code', 'bold italic blockquote | h2 p media link | alignleft aligncenter alignright'] return ['removeformat undo redo | bullist numlist | outdent indent | forecolor | fullscreen code', 'bold italic blockquote | h2 p media link | alignleft aligncenter alignright']
}
},
data() {
return {
hasChange: false,
hasInit: false
}
},
menubar: {
default: ''
},
height: {
type: Number,
required: false,
default: 360
} }
}, },
data() { watch: {
return { value(val) {
hasChange: false, if (!this.hasChange && this.hasInit) {
hasInit: false this.$nextTick(() => tinymce.get(this.id).setContent(val))
}
} }
}, },
menubar: { mounted() {
default: '' const _this = this;
}, tinymce.init({
height: { selector: `#${this.id}`,
type: Number, height: this.height,
required: false, body_class: 'panel-body ',
default: 360 object_resizing: false,
}
},
watch: {
value(val) {
if (!this.hasChange && this.hasInit) {
this.$nextTick(() => tinymce.get(this.id).setContent(val))
}
}
},
mounted() {
const _this = this;
tinymce.init({
selector: `#${this.id}`,
height: this.height,
body_class: 'panel-body ',
object_resizing: false,
// language: 'zh_CN', // language: 'zh_CN',
// language_url: '/static/tinymce/langs/zh_CN.js', // language_url: '/static/tinymce/langs/zh_CN.js',
toolbar: this.toolbar, toolbar: this.toolbar,
menubar: this.menubar, menubar: this.menubar,
plugins: 'advlist,autolink,code,paste,textcolor, colorpicker,fullscreen,link,lists,media,wordcount, imagetools,watermark', plugins: 'advlist,autolink,code,paste,textcolor, colorpicker,fullscreen,link,lists,media,wordcount, imagetools,watermark',
end_container_on_empty_block: true, end_container_on_empty_block: true,
powerpaste_word_import: 'clean', powerpaste_word_import: 'clean',
code_dialog_height: 450, code_dialog_height: 450,
code_dialog_width: 1000, code_dialog_width: 1000,
advlist_bullet_styles: 'square', advlist_bullet_styles: 'square',
advlist_number_styles: 'default', advlist_number_styles: 'default',
block_formats: '普通标签=p;小标题=h2;', block_formats: '普通标签=p;小标题=h2;',
imagetools_cors_hosts: ['wpimg.wallstcn.com', 'wallstreetcn.com'], imagetools_cors_hosts: ['wpimg.wallstcn.com', 'wallstreetcn.com'],
imagetools_toolbar: 'watermark', imagetools_toolbar: 'watermark',
default_link_target: '_blank', default_link_target: '_blank',
link_title: false, link_title: false,
init_instance_callback: editor => { init_instance_callback: editor => {
if (_this.value) { if (_this.value) {
editor.setContent(_this.value) editor.setContent(_this.value)
} }
_this.hasInit = true; _this.hasInit = true;
editor.on('NodeChange Change KeyUp', () => { editor.on('NodeChange Change KeyUp', () => {
this.hasChange = true; this.hasChange = true;
this.$emit('input', editor.getContent({ format: 'raw' })); this.$emit('input', editor.getContent({ format: 'raw' }));
}); });
}, },
// //
// images_dataimg_filter(img) { // images_dataimg_filter(img) {
// setTimeout(() => { // setTimeout(() => {
@ -112,44 +112,44 @@
// console.log(err); // console.log(err);
// }); // });
// }, // },
setup(editor) { setup(editor) {
editor.addButton('h2', { editor.addButton('h2', {
title: '小标题', // tooltip text seen on mouseover title: '小标题', // tooltip text seen on mouseover
text: '小标题', text: '小标题',
onclick() { onclick() {
editor.execCommand('mceToggleFormat', false, 'h2'); editor.execCommand('mceToggleFormat', false, 'h2');
}, },
onPostRender() { onPostRender() {
const btn = this; const btn = this;
editor.on('init', () => { editor.on('init', () => {
editor.formatter.formatChanged('h2', state => { editor.formatter.formatChanged('h2', state => {
btn.active(state); btn.active(state);
});
}); });
}); }
} });
}); editor.addButton('p', {
editor.addButton('p', { title: '正文',
title: '正文', text: '正文',
text: '正文', onclick() {
onclick() { editor.execCommand('mceToggleFormat', false, 'p');
editor.execCommand('mceToggleFormat', false, 'p'); },
}, onPostRender() {
onPostRender() { const btn = this;
const btn = this; editor.on('init', () => {
editor.on('init', () => { editor.formatter.formatChanged('p', state => {
editor.formatter.formatChanged('p', state => { btn.active(state);
btn.active(state); });
}); });
}); }
} });
}); }
} });
}); },
}, destroyed() {
destroyed() { tinymce.get(this.id).destroy();
tinymce.get(this.id).destroy(); }
} }
}
</script> </script>
<style scoped> <style scoped>

View File

@ -1,14 +1,7 @@
<template> <template>
<div class="upload-container"> <div class="upload-container">
<el-upload <el-upload class="image-uploader" :data="dataObj" drag :multiple="false" :show-file-list="false" action="https://httpbin.org/post"
class="image-uploader" :on-success="handleImageScucess">
:data="dataObj"
drag
:multiple="false"
:show-file-list="false"
action="https://httpbin.org/post"
:on-success="handleImageScucess">
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
</el-upload> </el-upload>
@ -22,53 +15,54 @@
</div> </div>
</div> </div>
</template> </template>
<script> <script>
// //
import { getToken } from 'api/qiniu'; import { getToken } from 'api/qiniu';
export default { export default {
name: 'singleImageUpload', name: 'singleImageUpload',
props: { props: {
value: String value: String
}, },
computed: { computed: {
imageUrl() { imageUrl() {
return this.value return this.value
} }
}, },
data() { data() {
return { return {
tempUrl: '', tempUrl: '',
dataObj: { token: '', key: '' } dataObj: { token: '', key: '' }
};
},
methods: {
rmImage() {
this.emitInput('');
},
emitInput(val) {
this.$emit('input', val);
},
handleImageScucess() {
this.emitInput(this.tempUrl)
},
beforeUpload() {
const _self = this;
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key;
const token = response.data.qiniu_token;
_self._data.dataObj.token = token;
_self._data.dataObj.key = key;
this.tempUrl = response.data.qiniu_url;
resolve(true);
}).catch(err => {
console.log(err);
reject(false)
});
});
}
}
}; };
},
methods: {
rmImage() {
this.emitInput('');
},
emitInput(val) {
this.$emit('input', val);
},
handleImageScucess() {
this.emitInput(this.tempUrl)
},
beforeUpload() {
const _self = this;
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key;
const token = response.data.qiniu_token;
_self._data.dataObj.token = token;
_self._data.dataObj.key = key;
this.tempUrl = response.data.qiniu_url;
resolve(true);
}).catch(err => {
console.log(err);
reject(false)
});
});
}
}
};
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>

View File

@ -1,126 +1,119 @@
<template> <template>
<div class="singleImageUpload2 upload-container"> <div class="singleImageUpload2 upload-container">
<el-upload <el-upload class="image-uploader" :data="dataObj" drag :multiple="false" :show-file-list="false" action="https://httpbin.org/post"
class="image-uploader" :on-success="handleImageScucess">
:data="dataObj" <i class="el-icon-upload"></i>
drag <div class="el-upload__text">Drag或<em>点击上传</em></div>
:multiple="false" </el-upload>
:show-file-list="false" <div v-show="imageUrl.length>0" class="image-preview">
action="https://httpbin.org/post" <div class="image-preview-wrapper" v-show="imageUrl.length>1">
<img :src="imageUrl">
:on-success="handleImageScucess"> <div class="image-preview-action">
<i class="el-icon-upload"></i> <i @click="rmImage" class="el-icon-delete"></i>
<div class="el-upload__text">Drag或<em>点击上传</em></div> </div>
</el-upload> </div>
<div v-show="imageUrl.length>0" class="image-preview"> </div>
<div class="image-preview-wrapper" v-show="imageUrl.length>1"> </div>
<img :src="imageUrl">
<div class="image-preview-action">
<i @click="rmImage" class="el-icon-delete"></i>
</div>
</div>
</div>
</div>
</template> </template>
<script> <script>
// //
import { getToken } from 'api/qiniu'; import { getToken } from 'api/qiniu';
export default { export default {
name: 'singleImageUpload2', name: 'singleImageUpload2',
props: { props: {
value: String value: String
}, },
computed: { computed: {
imageUrl() { imageUrl() {
return this.value return this.value
} }
}, },
data() { data() {
return { return {
tempUrl: '', tempUrl: '',
dataObj: { token: '', key: '' } dataObj: { token: '', key: '' }
};
},
methods: {
rmImage() {
this.emitInput('');
},
emitInput(val) {
this.$emit('input', val);
},
handleImageScucess() {
this.emitInput(this.tempUrl)
},
beforeUpload() {
const _self = this;
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key;
const token = response.data.qiniu_token;
_self._data.dataObj.token = token;
_self._data.dataObj.key = key;
this.tempUrl = response.data.qiniu_url;
resolve(true);
}).catch(err => {
console.log(err);
reject(false)
});
});
}
}
}; };
},
methods: {
rmImage() {
this.emitInput('');
},
emitInput(val) {
this.$emit('input', val);
},
handleImageScucess() {
this.emitInput(this.tempUrl)
},
beforeUpload() {
const _self = this;
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key;
const token = response.data.qiniu_token;
_self._data.dataObj.token = token;
_self._data.dataObj.key = key;
this.tempUrl = response.data.qiniu_url;
resolve(true);
}).catch(err => {
console.log(err);
reject(false)
});
});
}
}
};
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.upload-container { .upload-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: relative; position: relative;
.image-uploader{ .image-uploader {
height: 100%; height: 100%;
} }
.image-preview { .image-preview {
width: 100%; width: 100%;
height: 100%; height: 100%;
position: absolute; position: absolute;
left: 0px; left: 0px;
top: 0px; top: 0px;
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
.image-preview-wrapper { .image-preview-wrapper {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.image-preview-action { .image-preview-action {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
left: 0; left: 0;
top: 0; top: 0;
cursor: default; cursor: default;
text-align: center; text-align: center;
color: #fff; color: #fff;
opacity: 0; opacity: 0;
font-size: 20px; font-size: 20px;
background-color: rgba(0, 0, 0, .5); background-color: rgba(0, 0, 0, .5);
transition: opacity .3s; transition: opacity .3s;
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
line-height: 200px; line-height: 200px;
.el-icon-delete { .el-icon-delete {
font-size: 36px; font-size: 36px;
} }
} }
&:hover { &:hover {
.image-preview-action { .image-preview-action {
opacity: 1; opacity: 1;
} }
} }
} }
} }
</style> </style>

View File

@ -1,154 +1,146 @@
<template> <template>
<div class="upload-container"> <div class="upload-container">
<el-upload <el-upload class="image-uploader" :data="dataObj" drag :multiple="false" :show-file-list="false" action="https://httpbin.org/post"
class="image-uploader" :on-success="handleImageScucess">
:data="dataObj" <i class="el-icon-upload"></i>
drag <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
:multiple="false" </el-upload>
:show-file-list="false" <div class="image-preview image-app-preview">
action="https://httpbin.org/post" <div class="image-preview-wrapper" v-show="imageUrl.length>1">
<div class='app-fake-conver'>&nbsp&nbsp全球 付费节目单 最热 经济</div>
:on-success="handleImageScucess"> <img :src="imageUrl">
<i class="el-icon-upload"></i> <div class="image-preview-action">
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <i @click="rmImage" class="el-icon-delete"></i>
</el-upload> </div>
<div class="image-preview image-app-preview"> </div>
<div class="image-preview-wrapper" v-show="imageUrl.length>1"> </div>
<div class='app-fake-conver'>&nbsp&nbsp全球 付费节目单 最热 经济</div> <div class="image-preview">
<img :src="imageUrl"> <div class="image-preview-wrapper" v-show="imageUrl.length>1">
<div class="image-preview-action"> <img :src="imageUrl">
<i @click="rmImage" class="el-icon-delete"></i> <div class="image-preview-action">
</div> <i @click="rmImage" class="el-icon-delete"></i>
</div> </div>
</div> </div>
<div class="image-preview"> </div>
<div class="image-preview-wrapper" v-show="imageUrl.length>1"> </div>
<img :src="imageUrl">
<div class="image-preview-action">
<i @click="rmImage" class="el-icon-delete"></i>
</div>
</div>
</div>
</div>
</template> </template>
<script> <script>
// //
import { getToken } from 'api/qiniu'; import { getToken } from 'api/qiniu';
export default { export default {
name: 'singleImageUpload', name: 'singleImageUpload',
props: { props: {
value: String value: String
}, },
computed: { computed: {
imageUrl() { imageUrl() {
return this.value return this.value
} }
}, },
data() { data() {
return { return {
tempUrl: '', tempUrl: '',
dataObj: { token: '', key: '' } dataObj: { token: '', key: '' }
};
},
methods: {
rmImage() {
this.emitInput('');
},
emitInput(val) {
this.$emit('input', val);
},
handleImageScucess(file) {
this.emitInput(file.files.file)
},
beforeUpload() {
const _self = this;
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key;
const token = response.data.qiniu_token;
_self._data.dataObj.token = token;
_self._data.dataObj.key = key;
this.tempUrl = response.data.qiniu_url;
resolve(true);
}).catch(err => {
console.log(err);
reject(false)
});
});
}
}
}; };
},
methods: {
rmImage() {
this.emitInput('');
},
emitInput(val) {
this.$emit('input', val);
},
handleImageScucess(file) {
this.emitInput(file.files.file)
},
beforeUpload() {
const _self = this;
return new Promise((resolve, reject) => {
getToken().then(response => {
const key = response.data.qiniu_key;
const token = response.data.qiniu_token;
_self._data.dataObj.token = token;
_self._data.dataObj.key = key;
this.tempUrl = response.data.qiniu_url;
resolve(true);
}).catch(err => {
console.log(err);
reject(false)
});
});
}
}
};
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss"; @import "src/styles/mixin.scss";
.upload-container { .upload-container {
width: 100%; width: 100%;
position: relative; position: relative;
@include clearfix; @include clearfix;
.image-uploader { .image-uploader {
width: 35%; width: 35%;
float: left; float: left;
} }
.image-preview { .image-preview {
width: 200px; width: 200px;
height: 200px; height: 200px;
position: relative; position: relative;
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
float: left; float: left;
margin-left: 50px; margin-left: 50px;
.image-preview-wrapper { .image-preview-wrapper {
position: relative; position: relative;
width: 100%; width: 100%;
height: 100%; height: 100%;
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
} }
.image-preview-action { .image-preview-action {
position: absolute; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
left: 0; left: 0;
top: 0; top: 0;
cursor: default; cursor: default;
text-align: center; text-align: center;
color: #fff; color: #fff;
opacity: 0; opacity: 0;
font-size: 20px; font-size: 20px;
background-color: rgba(0, 0, 0, .5); background-color: rgba(0, 0, 0, .5);
transition: opacity .3s; transition: opacity .3s;
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
line-height: 200px; line-height: 200px;
.el-icon-delete { .el-icon-delete {
font-size: 36px; font-size: 36px;
} }
} }
&:hover { &:hover {
.image-preview-action { .image-preview-action {
opacity: 1; opacity: 1;
} }
} }
} }
.image-app-preview{ .image-app-preview {
width: 320px; width: 320px;
height: 180px; height: 180px;
position: relative; position: relative;
border: 1px dashed #d9d9d9; border: 1px dashed #d9d9d9;
float: left; float: left;
margin-left: 50px; margin-left: 50px;
.app-fake-conver{ .app-fake-conver {
height: 44px; height: 44px;
position: absolute; position: absolute;
width: 100%; width: 100%; // background: rgba(0, 0, 0, .1);
// background: rgba(0, 0, 0, .1); text-align: center;
text-align: center; line-height: 64px;
line-height: 64px; color: #fff;
color: #fff; }
}
} }
}
}
</style> </style>

View File

@ -4,61 +4,61 @@
</div> </div>
</template> </template>
<script> <script>
import CodeMirror from 'codemirror'; import CodeMirror from 'codemirror';
import 'codemirror/addon/lint/lint.css'; import 'codemirror/addon/lint/lint.css';
import 'codemirror/lib/codemirror.css'; import 'codemirror/lib/codemirror.css';
import 'codemirror/theme/rubyblue.css'; import 'codemirror/theme/rubyblue.css';
require('script-loader!jsonlint'); require('script-loader!jsonlint');
import 'codemirror/mode/javascript/javascript' import 'codemirror/mode/javascript/javascript'
import 'codemirror/addon/lint/lint' import 'codemirror/addon/lint/lint'
import 'codemirror/addon/lint/json-lint'; import 'codemirror/addon/lint/json-lint';
export default { export default {
name: 'jsonEditor', name: 'jsonEditor',
data() { data() {
return { return {
jsonEditor: false jsonEditor: false
} }
}, },
props: ['value'], props: ['value'],
watch: { watch: {
value(value) { value(value) {
const editor_value = this.jsonEditor.getValue(); const editor_value = this.jsonEditor.getValue();
if (value !== editor_value) { if (value !== editor_value) {
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2)); this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
}
}
},
mounted() {
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
lineNumbers: true,
mode: 'application/json',
gutters: ['CodeMirror-lint-markers'],
theme: 'rubyblue',
lint: true
});
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
this.jsonEditor.on('change', cm => {
this.$emit('changed', cm.getValue())
this.$emit('input', cm.getValue())
})
},
methods: {
getValue() {
return this.jsonEditor.getValue()
} }
} }
},
mounted() {
this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
lineNumbers: true,
mode: 'application/json',
gutters: ['CodeMirror-lint-markers'],
theme: 'rubyblue',
lint: true
});
this.jsonEditor.setValue(JSON.stringify(this.value, null, 2));
this.jsonEditor.on('change', cm => {
this.$emit('changed', cm.getValue())
this.$emit('input', cm.getValue())
})
},
methods: {
getValue() {
return this.jsonEditor.getValue()
}
} }
}
</script> </script>
<style> <style>
.CodeMirror { .CodeMirror {
height: 100%; height: 100%;
} }
.json-editor .cm-s-rubyblue span.cm-string{
color: #F08047; .json-editor .cm-s-rubyblue span.cm-string {
} color: #F08047;
}
</style> </style>

View File

@ -3,7 +3,7 @@
<div class="twoDndList-list" :style="{width:width1}"> <div class="twoDndList-list" :style="{width:width1}">
<h3>{{list1Title}}</h3> <h3>{{list1Title}}</h3>
<draggable :list="list1" class="dragArea" :options="{group:'article'}"> <draggable :list="list1" class="dragArea" :options="{group:'article'}">
<div class="list-complete-item" v-for="element in list1"> <div class="list-complete-item" v-for="element in list1" :key='element'>
<div class="list-complete-item-handle">[{{element.author}}] {{element.title}}</div> <div class="list-complete-item-handle">[{{element.author}}] {{element.title}}</div>
<div style="position:absolute;right:0px;"> <div style="position:absolute;right:0px;">
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)"> <span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
@ -17,7 +17,7 @@
<div class="twoDndList-list" :style="{width:width2}"> <div class="twoDndList-list" :style="{width:width2}">
<h3>{{list2Title}}</h3> <h3>{{list2Title}}</h3>
<draggable :list="filterList2" class="dragArea" :options="{group:'article'}"> <draggable :list="filterList2" class="dragArea" :options="{group:'article'}">
<div class="list-complete-item" v-for="element in filterList2"> <div class="list-complete-item" v-for="element in filterList2" :key='element'>
<div class='list-complete-item-handle2' @click="pushEle(element)"> [{{element.author}}] {{element.title}}</div> <div class='list-complete-item-handle2' @click="pushEle(element)"> [{{element.author}}] {{element.title}}</div>
</div> </div>
</draggable> </draggable>
@ -26,131 +26,133 @@
</template> </template>
<script> <script>
import draggable from 'vuedraggable' import draggable from 'vuedraggable'
export default { export default {
name: 'twoDndList', name: 'twoDndList',
components: { draggable }, components: { draggable },
computed: { computed: {
filterList2() { filterList2() {
return this.list2.filter(v => { return this.list2.filter(v => {
if (this.isNotInList1(v)) { if (this.isNotInList1(v)) {
return v return v
} }
return false; return false;
}) })
}
},
props: {
list1: {
type: Array,
default() {
return []
} }
}, },
props: { list2: {
list1: { type: Array,
type: Array, default() {
default() { return []
return []
}
},
list2: {
type: Array,
default() {
return []
}
},
list1Title: {
type: String,
default: 'list1'
},
list2Title: {
type: String,
default: 'list2'
},
width1: {
type: String,
default: '48%'
},
width2: {
type: String,
default: '48%'
} }
}, },
methods: { list1Title: {
isNotInList1(v) { type: String,
return this.list1.every(k => v.id !== k.id) default: 'list1'
}, },
isNotInList2(v) { list2Title: {
return this.list2.every(k => v.id !== k.id) type: String,
}, default: 'list2'
deleteEle(ele) { },
for (const item of this.list1) { width1: {
if (item.id === ele.id) { type: String,
const index = this.list1.indexOf(item); default: '48%'
this.list1.splice(index, 1) },
break width2: {
} type: String,
default: '48%'
}
},
methods: {
isNotInList1(v) {
return this.list1.every(k => v.id !== k.id)
},
isNotInList2(v) {
return this.list2.every(k => v.id !== k.id)
},
deleteEle(ele) {
for (const item of this.list1) {
if (item.id === ele.id) {
const index = this.list1.indexOf(item);
this.list1.splice(index, 1)
break
} }
if (this.isNotInList2(ele)) {
this.list2.unshift(ele)
}
},
pushEle(ele) {
this.list1.push(ele)
} }
if (this.isNotInList2(ele)) {
this.list2.unshift(ele)
}
},
pushEle(ele) {
this.list1.push(ele)
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.twoDndList { .twoDndList {
background: #fff; background: #fff;
padding-bottom: 40px; padding-bottom: 40px;
&:after { &:after {
content: ""; content: "";
display: table; display: table;
clear: both; clear: both;
} }
.twoDndList-list { .twoDndList-list {
float: left; float: left;
padding-bottom: 30px; padding-bottom: 30px;
&:first-of-type { &:first-of-type {
margin-right: 2%; margin-right: 2%;
}
.dragArea {
margin-top: 15px;
min-height: 50px;
padding-bottom: 30px;
}
}
} }
.dragArea {
margin-top: 15px;
min-height: 50px;
padding-bottom: 30px;
}
}
}
.list-complete-item { .list-complete-item {
cursor: pointer; cursor: pointer;
position: relative; position: relative;
font-size: 14px; font-size: 14px;
padding: 5px 12px; padding: 5px 12px;
margin-top: 4px; margin-top: 4px;
border: 1px solid #bfcbd9; border: 1px solid #bfcbd9;
transition: all 1s; transition: all 1s;
} }
.list-complete-item-handle { .list-complete-item-handle {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
margin-right: 50px; margin-right: 50px;
} }
.list-complete-item-handle2{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-right: 20px;
}
.list-complete-item.sortable-chosen { .list-complete-item-handle2 {
background: #4AB7BD; overflow: hidden;
} text-overflow: ellipsis;
white-space: nowrap;
margin-right: 20px;
}
.list-complete-item.sortable-ghost { .list-complete-item.sortable-chosen {
background: #30B08F; background: #4AB7BD;
} }
.list-complete-enter, .list-complete-leave-active { .list-complete-item.sortable-ghost {
opacity: 0; background: #30B08F;
} }
.list-complete-enter,
.list-complete-leave-active {
opacity: 0;
}
</style> </style>

View File

@ -24,7 +24,6 @@ export function parseTime(time, cFormat) {
time = +time * 1000 time = +time * 1000
} }
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'; const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
let date; let date;
if (typeof time == 'object') { if (typeof time == 'object') {
@ -75,8 +74,6 @@ export function formatTime(time, option) {
} }
} }
/* 数字 格式化*/ /* 数字 格式化*/
export function nFormatter(num, digits) { export function nFormatter(num, digits) {
const si = [ const si = [
@ -95,14 +92,12 @@ export function nFormatter(num, digits) {
return num.toString(); return num.toString();
} }
export function html2Text(val) { export function html2Text(val) {
const div = document.createElement('div'); const div = document.createElement('div');
div.innerHTML = val; div.innerHTML = val;
return div.textContent || div.innerText; return div.textContent || div.innerText;
} }
export function toThousandslsFilter(num) { export function toThousandslsFilter(num) {
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ',')); return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','));
} }

View File

@ -20,7 +20,6 @@ import vueWaves from './directive/waves';// 水波纹指令
import errLog from 'store/errLog';// error log组件 import errLog from 'store/errLog';// error log组件
import './mock/index.js'; // 该项目所有请求使用mockjs模拟 import './mock/index.js'; // 该项目所有请求使用mockjs模拟
// register globally // register globally
Vue.component('multiselect', Multiselect); Vue.component('multiselect', Multiselect);
Vue.component('Sticky', Sticky); Vue.component('Sticky', Sticky);
@ -28,8 +27,6 @@ Vue.component('icon-svg', IconSvg)
Vue.use(ElementUI); Vue.use(ElementUI);
Vue.use(vueWaves); Vue.use(vueWaves);
Vue.config.productionTip = false;
// register global utility filters. // register global utility filters.
Object.keys(filters).forEach(key => { Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key]) Vue.filter(key, filters[key])
@ -78,11 +75,12 @@ router.beforeEach((to, from, next) => {
} }
}); });
router.afterEach(() => { router.afterEach(() => {
NProgress.done(); // 结束Progress NProgress.done(); // 结束Progress
}); });
Vue.config.productionTip = false;
// 生产环境错误日志 // 生产环境错误日志
if (process.env === 'production') { if (process.env === 'production') {
Vue.config.errorHandler = function(err, vm) { Vue.config.errorHandler = function(err, vm) {

View File

@ -6,25 +6,21 @@ const userMap = {
token: 'admin', token: 'admin',
introduction: '我是超级管理员', introduction: '我是超级管理员',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Super Admin', name: 'Super Admin'
uid: '001'
}, },
editor: { editor: {
role: ['editor'], role: ['editor'],
token: 'editor', token: 'editor',
introduction: '我是编辑', introduction: '我是编辑',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor', name: 'Normal Editor'
uid: '002'
}, },
developer: { developer: {
role: ['develop'], role: ['develop'],
token: 'develop', token: 'develop',
introduction: '我是开发', introduction: '我是开发',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: '工程师小王', name: '工程师小王'
uid: '003'
} }
} }

View File

@ -29,7 +29,6 @@ const SplitPane = _import('components/splitpane');
const CountTo = _import('components/countTo'); const CountTo = _import('components/countTo');
const Mixin = _import('components/mixin'); const Mixin = _import('components/mixin');
/* charts */ /* charts */
const chartIndex = _import('charts/index'); const chartIndex = _import('charts/index');
const KeyboardChart = _import('charts/keyboard'); const KeyboardChart = _import('charts/keyboard');
@ -63,7 +62,6 @@ const Tab = _import('example/tab/index');
/* permission */ /* permission */
const Permission = _import('permission/index'); const Permission = _import('permission/index');
Vue.use(Router); Vue.use(Router);
/** /**

View File

@ -4,10 +4,7 @@ const getters = {
token: state => state.user.token, token: state => state.user.token,
avatar: state => state.user.avatar, avatar: state => state.user.avatar,
name: state => state.user.name, name: state => state.user.name,
uid: state => state.user.uid,
email: state => state.user.email,
introduction: state => state.user.introduction, introduction: state => state.user.introduction,
auth_type: state => state.user.auth_type,
status: state => state.user.status, status: state => state.user.status,
roles: state => state.user.roles, roles: state => state.user.roles,
setting: state => state.user.setting, setting: state => state.user.setting,

View File

@ -5,10 +5,7 @@ const user = {
state: { state: {
user: '', user: '',
status: '', status: '',
email: '',
code: '', code: '',
uid: undefined,
auth_type: '',
token: Cookies.get('Admin-Token'), token: Cookies.get('Admin-Token'),
name: '', name: '',
avatar: '', avatar: '',
@ -20,21 +17,12 @@ const user = {
}, },
mutations: { mutations: {
SET_AUTH_TYPE: (state, type) => {
state.auth_type = type;
},
SET_CODE: (state, code) => { SET_CODE: (state, code) => {
state.code = code; state.code = code;
}, },
SET_TOKEN: (state, token) => { SET_TOKEN: (state, token) => {
state.token = token; state.token = token;
}, },
SET_UID: (state, uid) => {
state.uid = uid;
},
SET_EMAIL: (state, email) => {
state.email = email;
},
SET_INTRODUCTION: (state, introduction) => { SET_INTRODUCTION: (state, introduction) => {
state.introduction = introduction; state.introduction = introduction;
}, },
@ -70,7 +58,6 @@ const user = {
const data = response.data; const data = response.data;
Cookies.set('Admin-Token', response.data.token); Cookies.set('Admin-Token', response.data.token);
commit('SET_TOKEN', data.token); commit('SET_TOKEN', data.token);
commit('SET_EMAIL', email);
resolve(); resolve();
}).catch(error => { }).catch(error => {
reject(error); reject(error);
@ -78,7 +65,6 @@ const user = {
}); });
}, },
// 获取用户信息 // 获取用户信息
GetInfo({ commit, state }) { GetInfo({ commit, state }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -87,7 +73,6 @@ const user = {
commit('SET_ROLES', data.role); commit('SET_ROLES', data.role);
commit('SET_NAME', data.name); commit('SET_NAME', data.name);
commit('SET_AVATAR', data.avatar); commit('SET_AVATAR', data.avatar);
commit('SET_UID', data.uid);
commit('SET_INTRODUCTION', data.introduction); commit('SET_INTRODUCTION', data.introduction);
resolve(response); resolve(response);
}).catch(error => { }).catch(error => {
@ -100,7 +85,7 @@ const user = {
LoginByThirdparty({ commit, state }, code) { LoginByThirdparty({ commit, state }, code) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
commit('SET_CODE', code); commit('SET_CODE', code);
loginByThirdparty(state.status, state.email, state.code, state.auth_type).then(response => { loginByThirdparty(state.status, state.email, state.code).then(response => {
commit('SET_TOKEN', response.data.token); commit('SET_TOKEN', response.data.token);
Cookies.set('Admin-Token', response.data.token); Cookies.set('Admin-Token', response.data.token);
resolve(); resolve();
@ -110,7 +95,6 @@ const user = {
}); });
}, },
// 登出 // 登出
LogOut({ commit, state }) { LogOut({ commit, state }) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -7,10 +7,11 @@
</template> </template>
<script> <script>
import keyboardChart from 'components/Charts/keyboard'; import keyboardChart from 'components/Charts/keyboard';
export default {
components: { keyboardChart } export default {
}; components: { keyboardChart }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -7,10 +7,11 @@
</template> </template>
<script> <script>
import keyboardChart2 from 'components/Charts/keyboard2'; import keyboardChart2 from 'components/Charts/keyboard2';
export default {
components: { keyboardChart2 } export default {
}; components: { keyboardChart2 }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -7,10 +7,11 @@
</template> </template>
<script> <script>
import lineMarker from 'components/Charts/lineMarker'; import lineMarker from 'components/Charts/lineMarker';
export default {
components: { lineMarker } export default {
}; components: { lineMarker }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -7,10 +7,11 @@
</template> </template>
<script> <script>
import mixChart from 'components/Charts/mixChart'; import mixChart from 'components/Charts/mixChart';
export default {
components: { mixChart } export default {
}; components: { mixChart }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -4,45 +4,46 @@
由于我在使用时它只有vue@1版本而且有些业务的需求耦合到七牛等等原因吧自己改造了一下如果大家要使用的话优先还是使用官方component 由于我在使用时它只有vue@1版本而且有些业务的需求耦合到七牛等等原因吧自己改造了一下如果大家要使用的话优先还是使用官方component
</code> </code>
<PanThumb :image='image'> <pan-thumb :image='image'></pan-thumb>
</PanThumb>
<el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">修改头像 <el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">修改头像
</el-button> </el-button>
<ImageCropper :width="300" :height="300" url="https://httpbin.org/post" @close='close' @crop-upload-success="cropSuccess" <image-cropper :width="300" :height="300" url="https://httpbin.org/post" @close='close' @crop-upload-success="cropSuccess" :key="imagecropperKey" v-show="imagecropperShow"></image-cropper>
:key="imagecropperKey" v-show="imagecropperShow" />
</div> </div>
</template> </template>
<script> <script>
import ImageCropper from 'components/ImageCropper'; import ImageCropper from 'components/ImageCropper';
import PanThumb from 'components/PanThumb'; import PanThumb from 'components/PanThumb';
export default {
components: { ImageCropper, PanThumb }, export default {
data() { components: { ImageCropper, PanThumb },
return { data() {
imagecropperShow: false, return {
imagecropperKey: 0, imagecropperShow: false,
image: 'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191' imagecropperKey: 0,
} image: 'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
},
methods: {
cropSuccess(resData) {
this.imagecropperShow = false;
this.imagecropperKey = this.imagecropperKey + 1;
this.image = resData.files.avatar;
},
close() {
this.imagecropperShow = false;
}
} }
}; },
methods: {
cropSuccess(resData) {
this.imagecropperShow = false;
this.imagecropperKey = this.imagecropperKey + 1;
this.image = resData.files.avatar;
},
close() {
this.imagecropperShow = false;
}
}
};
</script> </script>
<style scoped> <style scoped>
.avatar{ .avatar{
width: 200px; width: 200px;
height: 200px; height: 200px;
border-radius: 50%; border-radius: 50%;
} }
</style> </style>

View File

@ -3,7 +3,7 @@
<code> <a href='https://github.com/PanJiaChen/vue-countTo' target='_blank'>countTo component</a></code> <code> <a href='https://github.com/PanJiaChen/vue-countTo' target='_blank'>countTo component</a></code>
<count-to ref='example' class='example' :start-val='_startVal' :end-val='_endVal' :duration='_duration' :decimals='_decimals' <count-to ref='example' class='example' :start-val='_startVal' :end-val='_endVal' :duration='_duration' :decimals='_decimals'
:separator='_separator' :prefix='_prefix' :suffix='_suffix' :autoplay='false' /> :separator='_separator' :prefix='_prefix' :suffix='_suffix' :autoplay='false'></count-to>
<div style='margin-left: 25%;margin-top: 40px;'> <div style='margin-left: 25%;margin-top: 40px;'>
<label class="label" for="startValInput">startVal: <input type="number" v-model.number='setStartVal' name='startValInput' /></label> <label class="label" for="startValInput">startVal: <input type="number" v-model.number='setStartVal' name='startValInput' /></label>
<label class="label" for="endValInput">endVal: <input type="number" v-model.number='setEndVal' name='endVaInput' /></label> <label class="label" for="endValInput">endVal: <input type="number" v-model.number='setEndVal' name='endVaInput' /></label>
@ -22,72 +22,72 @@
</template> </template>
<script> <script>
import countTo from 'vue-count-to'; import countTo from 'vue-count-to';
export default { export default {
components: { countTo }, components: { countTo },
data() { data() {
return { return {
setStartVal: 0, setStartVal: 0,
setEndVal: 2017, setEndVal: 2017,
setDuration: 4000, setDuration: 4000,
setDecimals: 0, setDecimals: 0,
setSeparator: ',', setSeparator: ',',
setSuffix: ' rmb', setSuffix: ' rmb',
setPrefix: '¥ ' setPrefix: '¥ '
} }
}, },
computed: { computed: {
_startVal() { _startVal() {
if (this.setStartVal) { if (this.setStartVal) {
return this.setStartVal return this.setStartVal
} else { } else {
return 0 return 0
} }
}, },
_endVal() { _endVal() {
if (this.setEndVal) { if (this.setEndVal) {
return this.setEndVal return this.setEndVal
} else { } else {
return 0 return 0
} }
}, },
_duration() { _duration() {
if (this.setDuration) { if (this.setDuration) {
return this.setDuration return this.setDuration
} else { } else {
return 100 return 100
} }
}, },
_decimals() { _decimals() {
if (this.setDecimals) { if (this.setDecimals) {
if (this.setDecimals < 0 || this.setDecimals > 20) { if (this.setDecimals < 0 || this.setDecimals > 20) {
alert('digits argument must be between 0 and 20') alert('digits argument must be between 0 and 20')
return 0 return 0
} }
return this.setDecimals return this.setDecimals
} else { } else {
return 0 return 0
} }
}, },
_separator() { _separator() {
return this.setSeparator return this.setSeparator
}, },
_suffix() { _suffix() {
return this.setSuffix return this.setSuffix
}, },
_prefix() { _prefix() {
return this.setPrefix return this.setPrefix
} }
}, },
methods: { methods: {
start() { start() {
this.$refs.example.start(); this.$refs.example.start();
}, },
pauseResume() { pauseResume() {
this.$refs.example.pauseResume(); this.$refs.example.pauseResume();
} }
} }
}; };
</script> </script>
<style scoped> <style scoped>

View File

@ -2,35 +2,37 @@
<div class="components-container"> <div class="components-container">
<code>drag-list base on <a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a></code> <code>drag-list base on <a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a></code>
<div class="editor-container"> <div class="editor-container">
<DndList :list1="list1" :list2="list2" list1Title="头条列表" list2Title="文章池" /> <dnd-list :list1="list1" :list2="list2" list1Title="头条列表" list2Title="文章池"></dnd-list>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import DndList from 'components/twoDndList' import DndList from 'components/twoDndList'
import { getList } from 'api/article'; import { getList } from 'api/article';
export default {
components: { DndList }, export default {
data() { components: { DndList },
return { data() {
list1: [], return {
list2: [] list1: [],
} 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)
})
}
} }
}; },
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> </script>

View File

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

View File

@ -8,16 +8,17 @@
</template> </template>
<script> <script>
import jsonEditor from 'components/jsonEditor'; import jsonEditor from 'components/jsonEditor';
const jsonData = '[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]'; const jsonData = '[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]';
export default {
components: { jsonEditor }, export default {
data() { components: { jsonEditor },
return { data() {
value: JSON.parse(jsonData) return {
} value: JSON.parse(jsonData)
} }
}; }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -2,7 +2,7 @@
<div class="components-container"> <div class="components-container">
<code>Markdown 我们这里选用了 <a href="https://github.com/sparksuite/simplemde-markdown-editor" target="_blank">simplemde-markdown-editor</a> 简单的用vue封装了一下<a target='_blank' href='https://segmentfault.com/a/1190000009762198#articleHeader14'> 相关文章 </a></code> <code>Markdown 我们这里选用了 <a href="https://github.com/sparksuite/simplemde-markdown-editor" target="_blank">simplemde-markdown-editor</a> 简单的用vue封装了一下<a target='_blank' href='https://segmentfault.com/a/1190000009762198#articleHeader14'> 相关文章 </a></code>
<div class="editor-container"> <div class="editor-container">
<MdEditor id='contentEditor' ref="contentEditor" v-model='content' :height="300" :zIndex='20'></MdEditor> <md-editor id='contentEditor' ref="contentEditor" v-model='content' :height="300" :zIndex='20'></md-editor>
</div> </div>
<el-button @click='markdown2Html' style="margin-top:80px;" type="primary">转为HTML<i class="el-icon-document el-icon--right"></i></el-button> <el-button @click='markdown2Html' style="margin-top:80px;" type="primary">转为HTML<i class="el-icon-document el-icon--right"></i></el-button>
<div v-html="html"></div> <div v-html="html"></div>
@ -10,24 +10,24 @@
</template> </template>
<script> <script>
import MdEditor from 'components/MdEditor'; import MdEditor from 'components/MdEditor';
export default { export default {
components: { MdEditor }, components: { MdEditor },
data() { data() {
return { return {
content: '## Simplemde', content: '## Simplemde',
html: '' html: ''
}
},
methods: {
markdown2Html() {
import('showdown').then(showdown => {
const converter = new showdown.Converter();
this.html = converter.makeHtml(this.content)
})
}
} }
}; },
methods: {
markdown2Html() {
import('showdown').then(showdown => {
const converter = new showdown.Converter();
this.html = converter.makeHtml(this.content)
})
}
}
};
</script> </script>

View File

@ -1,16 +1,16 @@
<template> <template>
<div class="components-container"> <div class="components-container">
<div class='component-item'> <div class='component-item'>
<MDinput name="name" v-model="title" required :maxlength="100"> <md-input name="name" v-model="title" required :maxlength="100">
标题 标题
</MDinput> </md-input>
<code class='code-part'>Material Design 的input</code> <code class='code-part'>Material Design 的input</code>
</div> </div>
<div class='component-item'> <div class='component-item'>
<PanThumb image='https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'> <pan-thumb image='https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'>
上海花裤衩 上海花裤衩
</PanThumb> </pan-thumb>
<code class='code-part'>图片hover效果</code> <code class='code-part'>图片hover效果</code>
</div> </div>
@ -18,21 +18,21 @@
<el-button v-waves type="primary">水波纹效果</el-button> <el-button v-waves type="primary">水波纹效果</el-button>
<code class='code-part'>水波纹 v-directive</code> <code class='code-part'>水波纹 v-directive</code>
</div> </div>
</div> </div>
</template> </template>
<script>
import MDinput from 'components/MDinput';
import PanThumb from 'components/PanThumb';
export default { <script>
components: { MDinput, PanThumb }, import MdInput from 'components/MDinput';
data() { import PanThumb from 'components/PanThumb';
return {
title: '' export default {
} components: { MdInput, PanThumb },
data() {
return {
title: ''
} }
}; }
};
</script> </script>
<style scoped> <style scoped>

View File

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

View File

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<Sticky className="sub-navbar"> <sticky className="sub-navbar">
<el-dropdown trigger="click"> <el-dropdown trigger="click">
<el-button> <el-button>
平台<i class="el-icon-caret-bottom el-icon--right"></i> 平台<i class="el-icon-caret-bottom el-icon--right"></i>
@ -32,7 +32,7 @@
<el-button style="margin-left: 10px;" type="success">发布 <el-button style="margin-left: 10px;" type="success">发布
</el-button> </el-button>
</Sticky> </sticky>
<div class="components-container"> <div class="components-container">
<code>Sticky header 当页面滚动到预设的位置会吸附在顶部</code> <code>Sticky header 当页面滚动到预设的位置会吸附在顶部</code>
@ -90,33 +90,34 @@
<div>我是占位</div> <div>我是占位</div>
</div> </div>
</div> </div>
</template> </template>
<script>
import Sticky from 'components/Sticky';
export default {
components: { Sticky }, <script>
data() { import Sticky from 'components/Sticky';
return {
time: '', export default {
url: '', components: { Sticky },
platforms: ['a-platform'], data() {
platformsOptions: [ return {
time: '',
url: '',
platforms: ['a-platform'],
platformsOptions: [
{ key: 'a-platform', name: '平台A' }, { key: 'a-platform', name: '平台A' },
{ key: 'b-platform', name: '平台B' }, { key: 'b-platform', name: '平台B' },
{ key: 'c-platform', name: '平台C' } { key: 'c-platform', name: '平台C' }
], ],
pickerOptions: { pickerOptions: {
disabledDate(time) { disabledDate(time) {
return time.getTime() > Date.now(); return time.getTime() > Date.now();
}
} }
} }
} }
}
}; };
</script> </script>
<style scoped> <style scoped>
.time-container { .time-container {
display: inline-block; display: inline-block;

View File

@ -9,16 +9,16 @@
</template> </template>
<script> <script>
import Tinymce from 'components/Tinymce'; import Tinymce from 'components/Tinymce';
export default { export default {
components: { Tinymce }, components: { Tinymce },
data() { data() {
return { return {
content: 'Tinymce' content: 'Tinymce'
}
} }
}; }
};
</script> </script>
<style scoped> <style scoped>

View File

@ -1,82 +1,82 @@
<template> <template>
<div class="dashboard-editor-container"> <div class="dashboard-editor-container">
<div class=" clearfix"> <div class=" clearfix">
<PanThumb style="float: left" :image="avatar"> 你的权限: <pan-thumb style="float: left" :image="avatar"> 你的权限:
<span class="pan-info-roles" v-for="item in roles">{{item}}</span> <span class="pan-info-roles" v-for="item in roles">{{item}}</span>
</PanThumb> </pan-thumb>
<a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github"> <a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;" <svg width="80" height="80" viewBox="0 0 250 250" style="fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
aria-hidden="true"> aria-hidden="true">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path> fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"fill="currentColor" class="octo-body"></path> <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
</svg> fill="currentColor" class="octo-body"></path>
</a> </svg>
<div class="info-container"> </a>
<span class="display_name">{{name}}</span> <div class="info-container">
<span style='font-size:20px;padding-top:20px;display:inline-block;'>普通编辑dashboard</span> <span class="display_name">{{name}}</span>
</div> <span style='font-size:20px;padding-top:20px;display:inline-block;'>普通编辑dashboard</span>
</div> </div>
<div> </div>
<img class='emptyGif' :src="emptyGif" > <div>
</div> <img class='emptyGif' :src="emptyGif">
</div> </div>
</div>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import PanThumb from 'components/PanThumb'; import PanThumb from 'components/PanThumb';
export default {
name: 'dashboard-default', export default {
components: { PanThumb }, name: 'dashboard-default',
data() { components: { PanThumb },
return { data() {
emptyGif: 'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3' return {
} emptyGif: 'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3'
},
computed: {
...mapGetters([
'name',
'avatar',
'email',
'uid',
'introduction',
'roles'
])
} }
},
computed: {
...mapGetters([
'name',
'avatar',
'roles'
])
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.emptyGif { .emptyGif {
display: block; display: block;
width: 45%; width: 45%;
margin: 0 auto; margin: 0 auto;
} }
.dashboard-editor-container {
background-color: #e3e3e3; .dashboard-editor-container {
min-height: 100vh; background-color: #e3e3e3;
margin-top: -50px; min-height: 100vh;
padding: 100px 60px 0px; margin-top: -50px;
.pan-info-roles { padding: 100px 60px 0px;
font-size: 12px; .pan-info-roles {
font-weight: 700; font-size: 12px;
color: #333; font-weight: 700;
display: block; color: #333;
} display: block;
.info-container { }
position: relative; .info-container {
margin-left: 190px; position: relative;
height: 150px; margin-left: 190px;
line-height: 200px; height: 150px;
.display_name { line-height: 200px;
font-size: 48px; .display_name {
line-height: 48px; font-size: 48px;
color: #212121; line-height: 48px;
position: absolute; color: #212121;
top: 25px; position: absolute;
} top: 25px;
} }
} }
}
</style> </style>

View File

@ -1,6 +1,7 @@
<template> <template>
<div :class="className" :style="{height:height,width:width}"></div> <div :class="className" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';
require('echarts/theme/macarons'); // echarts require('echarts/theme/macarons'); // echarts

View File

@ -1,109 +1,109 @@
<template> <template>
<div class="dashboard-editor-container"> <div class="dashboard-editor-container">
<a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github"> <a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;" <svg width="80" height="80" viewBox="0 0 250 250" style="fill:#4AB7BD; color:#fff; position: absolute; top: 50px; border: 0; right: 0;"
aria-hidden="true"> aria-hidden="true">
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path> <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
<path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" <path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path> fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
<path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" <path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
fill="currentColor" class="octo-body"></path> fill="currentColor" class="octo-body"></path>
</svg> </svg>
</a> </a>
<el-row class="btn-group"> <el-row class="btn-group">
<el-col :span="4" class='text-center'> <el-col :span="4" class='text-center'>
<router-link class="pan-btn blue-btn" to="/components/index">Components</router-link> <router-link class="pan-btn blue-btn" to="/components/index">Components</router-link>
</el-col> </el-col>
<el-col :span="4" class='text-center'> <el-col :span="4" class='text-center'>
<router-link class="pan-btn light-blue-btn" to="/charts/index">Charts</router-link> <router-link class="pan-btn light-blue-btn" to="/charts/index">Charts</router-link>
</el-col> </el-col>
<el-col :span="4" class='text-center'> <el-col :span="4" class='text-center'>
<router-link class="pan-btn pink-btn" to="/excel/download">Excel</router-link> <router-link class="pan-btn pink-btn" to="/excel/download">Excel</router-link>
</el-col> </el-col>
<el-col :span="4" class='text-center'> <el-col :span="4" class='text-center'>
<router-link class="pan-btn green-btn" to="/example/table/table">Table</router-link> <router-link class="pan-btn green-btn" to="/example/table/table">Table</router-link>
</el-col> </el-col>
<el-col :span="4" class='text-center'> <el-col :span="4" class='text-center'>
<router-link class="pan-btn tiffany-btn" to="/example/form/edit">Form</router-link> <router-link class="pan-btn tiffany-btn" to="/example/form/edit">Form</router-link>
</el-col> </el-col>
<el-col :span="4" class='text-center'> <el-col :span="4" class='text-center'>
<router-link class="pan-btn yellow-btn" to="/example/form/edit">Theme</router-link> <router-link class="pan-btn yellow-btn" to="/example/form/edit">Theme</router-link>
</el-col> </el-col>
</el-row> </el-row>
<el-row> <el-row>
<el-col :span="6"> <el-col :span="6">
<el-card class="box-card"> <el-card class="box-card">
<div slot="header" class="box-card-header"> <div slot="header" class="box-card-header">
<pan-thumb class="panThumb" :image="avatar"> 你的权限: <pan-thumb class="panThumb" :image="avatar"> 你的权限:
<span class="pan-info-roles" :key='item' v-for="item in roles">{{item}}</span> <span class="pan-info-roles" :key='item' v-for="item in roles">{{item}}</span>
</pan-thumb> </pan-thumb>
</div> </div>
<span class="display_name">{{name}}</span> <span class="display_name">{{name}}</span>
<div class="info-item"> <div class="info-item">
<countTo class="info-item-num" :startVal='0' :endVal='statisticsData.article_count' :duration='3400'></countTo> <countTo class="info-item-num" :startVal='0' :endVal='statisticsData.article_count' :duration='3400'></countTo>
<span class="info-item-text">文章</span> <span class="info-item-text">文章</span>
<icon-svg icon-class="a" class="dashboard-editor-icon"></icon-svg> <icon-svg icon-class="a" class="dashboard-editor-icon"></icon-svg>
</div> </div>
<div class="info-item"> <div class="info-item">
<countTo class="info-item-num" :startVal='0' :endVal='statisticsData.pageviews_count' :duration='3600'></countTo> <countTo class="info-item-num" :startVal='0' :endVal='statisticsData.pageviews_count' :duration='3600'></countTo>
<span class="info-item-text">浏览量</span> <span class="info-item-text">浏览量</span>
<icon-svg icon-class="b" class="dashboard-editor-icon"></icon-svg> <icon-svg icon-class="b" class="dashboard-editor-icon"></icon-svg>
</div> </div>
</el-card> </el-card>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<pie-chart></pie-chart> <pie-chart></pie-chart>
</el-col> </el-col>
<el-col :span="10"> <el-col :span="10">
<bar-chart></bar-chart> <bar-chart></bar-chart>
</el-col> </el-col>
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="15"> <el-col :span="15">
<line-chart></line-chart> <line-chart></line-chart>
</el-col> </el-col>
<el-col :span="9"> <el-col :span="9">
<todo-list></todo-list> <todo-list></todo-list>
</el-col> </el-col>
</el-row> </el-row>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import panThumb from 'components/PanThumb'; import panThumb from 'components/PanThumb';
import pieChart from './pieChart'; import pieChart from './pieChart';
import barChart from './barChart'; import barChart from './barChart';
import lineChart from './lineChart'; import lineChart from './lineChart';
import countTo from 'vue-count-to'; import countTo from 'vue-count-to';
import todoList from 'components/TodoList'; import todoList from 'components/TodoList';
export default { export default {
name: 'dashboard-editor', name: 'dashboard-editor',
components: { panThumb, countTo, pieChart, lineChart, barChart, todoList }, components: { panThumb, countTo, pieChart, lineChart, barChart, todoList },
data() { data() {
return { return {
statisticsData: { statisticsData: {
article_count: 1024, article_count: 1024,
comment_count: 102400, comment_count: 102400,
latest_article: [], latest_article: [],
month_article_count: 28, month_article_count: 28,
pageviews_count: 1024 pageviews_count: 1024
}
}
},
computed: {
...mapGetters([
'name',
'avatar',
'roles'
])
} }
} }
},
computed: {
...mapGetters([
'name',
'avatar',
'roles'
])
}
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>

View File

@ -1,12 +1,12 @@
<template> <template>
<div :class="className" :style="{height:height,width:width}"></div> <div :class="className" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';
require('echarts/theme/macarons'); // echarts require('echarts/theme/macarons'); // echarts
import { debounce } from 'utils'; import { debounce } from 'utils';
export default { export default {
props: { props: {
className: { className: {

View File

@ -1,6 +1,7 @@
<template> <template>
<div :class="className" :style="{height:height,width:width}"></div> <div :class="className" :style="{height:height,width:width}"></div>
</template> </template>
<script> <script>
import echarts from 'echarts'; import echarts from 'echarts';
require('echarts/theme/macarons'); // echarts require('echarts/theme/macarons'); // echarts

View File

@ -1,39 +1,36 @@
<template> <template>
<div class="dashboard-container"> <div class="dashboard-container">
<component v-bind:is="currentRole"> </component> <component v-bind:is="currentRole"> </component>
</div> </div>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import EditorDashboard from './editor/index'; import EditorDashboard from './editor/index';
import DefaultDashboard from './default/index'; import DefaultDashboard from './default/index';
export default {
name: 'dashboard', export default {
components: { EditorDashboard, DefaultDashboard }, name: 'dashboard',
data() { components: { EditorDashboard, DefaultDashboard },
return { data() {
currentRole: 'EditorDashboard' return {
} currentRole: 'EditorDashboard'
},
computed: {
...mapGetters([
'name',
'avatar',
'email',
'introduction',
'roles'
])
},
created() {
if (this.roles.indexOf('admin') >= 0) {
return;
}
// const isEditor = this.roles.some(v => v.indexOf('editor') >= 0)
// if (!isEditor) {
// this.currentRole = 'DefaultDashboard';
// }
this.currentRole = 'DefaultDashboard';
} }
},
computed: {
...mapGetters([
'name',
'avatar',
'email',
'introduction',
'roles'
])
},
created() {
if (this.roles.indexOf('admin') >= 0) {
return;
}
this.currentRole = 'DefaultDashboard';
} }
}
</script> </script>

View File

@ -1,6 +1,6 @@
<template> <template>
<div class="errPage-container"> <div class="errPage-container">
<err-code/> <err-code></err-code>
<h3>请点击右上角bug小图表</h3> <h3>请点击右上角bug小图表</h3>
<code> <code>
@ -11,19 +11,15 @@
</template> </template>
<script> <script>
import errCode from './errcode'; import errCode from './errcode';
export default {
components: { errCode }, export default {
methods: { components: { errCode }
back() { };
this.$router.go(-1)
}
}
};
</script> </script>
<style scoped> <style scoped>
.errPage-container{ .errPage-container {
padding: 30px; padding: 30px;
} }
</style> </style>

View File

@ -28,25 +28,25 @@
</template> </template>
<script> <script>
import errGif from 'assets/401.gif'; import errGif from 'assets/401_images/401.gif';
export default { export default {
data() { data() {
return { return {
errGif: errGif + '?' + +new Date(), errGif: errGif + '?' + +new Date(),
ewizardClap: 'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646', ewizardClap: 'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646',
dialogVisible: false dialogVisible: false
} }
}, },
methods: { methods: {
back() { back() {
if (this.$route.query.noGoBack) { if (this.$route.query.noGoBack) {
this.$router.push({ path: '/dashboard' }); this.$router.push({ path: '/dashboard' });
} else { } else {
this.$router.go(-1); this.$router.go(-1);
}
} }
} }
}; }
};
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>

View File

@ -2,10 +2,10 @@
<div style="background:#f0f2f5;margin-top: -20px;"> <div style="background:#f0f2f5;margin-top: -20px;">
<div class="wscn-http404"> <div class="wscn-http404">
<div class="pic-404"> <div class="pic-404">
<img class="pic-404__parent" src="../../assets/404.png" alt="404"> <img class="pic-404__parent" :src="img_404" alt="404">
<img class="pic-404__child left" src="../../assets/404_cloud.png" alt="404"> <img class="pic-404__child left" :src="img_404_cloud" alt="404">
<img class="pic-404__child mid" src="../../assets/404_cloud.png" alt="404"> <img class="pic-404__child mid" :src="img_404_cloud" alt="404">
<img class="pic-404__child right" src="../../assets/404_cloud.png" alt="404"> <img class="pic-404__child right" :src="img_404_cloud" alt="404">
</div> </div>
<div class="bullshit"> <div class="bullshit">
<div class="bullshit__oops">OOPS!</div> <div class="bullshit__oops">OOPS!</div>
@ -19,7 +19,16 @@
</template> </template>
<script> <script>
import img_404 from '@/assets/404_images/404.png'
import img_404_cloud from '@/assets/404_images/404_cloud.png'
export default { export default {
data() {
return {
img_404,
img_404_cloud
}
},
computed: { computed: {
message() { message() {
return '特朗普说这个页面你不能进......' return '特朗普说这个页面你不能进......'
@ -29,191 +38,192 @@
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.wscn-http404 { .wscn-http404 {
position: relative;
width: 1200px;
margin: 20px auto 60px;
padding: 0 100px;
overflow: hidden;
.pic-404 {
position: relative; position: relative;
width: 1200px; float: left;
margin: 20px auto 60px; width: 600px;
padding: 0 100px; padding: 150px 0;
overflow: hidden; overflow: hidden;
.pic-404 { &__parent {
position: relative; width: 100%;
float: left; }
width: 600px; &__child {
padding: 150px 0; position: absolute;
overflow: hidden; &.left {
&__parent { width: 80px;
width: 100%; top: 17px;
left: 220px;
opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
} }
&__child { &.mid {
position: absolute; width: 46px;
&.left { top: 10px;
width: 80px; left: 420px;
opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
}
&.right {
width: 62px;
top: 100px;
left: 500px;
opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
}
@keyframes cloudLeft {
0% {
top: 17px; top: 17px;
left: 220px; left: 220px;
opacity: 0; opacity: 0;
animation-name: cloudLeft;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
} }
&.mid { 20% {
width: 46px; top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
}
@keyframes cloudMid {
0% {
top: 10px; top: 10px;
left: 420px; left: 420px;
opacity: 0; opacity: 0;
animation-name: cloudMid;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1.2s;
} }
&.right { 20% {
width: 62px; top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px; top: 100px;
left: 500px; left: 500px;
opacity: 0; opacity: 0;
animation-name: cloudRight;
animation-duration: 2s;
animation-timing-function: linear;
animation-fill-mode: forwards;
animation-delay: 1s;
} }
@keyframes cloudLeft { 20% {
0% { top: 120px;
top: 17px; left: 460px;
left: 220px; opacity: 1;
opacity: 0;
}
20% {
top: 33px;
left: 188px;
opacity: 1;
}
80% {
top: 81px;
left: 92px;
opacity: 1;
}
100% {
top: 97px;
left: 60px;
opacity: 0;
}
} }
@keyframes cloudMid { 80% {
0% { top: 180px;
top: 10px; left: 340px;
left: 420px; opacity: 1;
opacity: 0;
}
20% {
top: 40px;
left: 360px;
opacity: 1;
}
70% {
top: 130px;
left: 180px;
opacity: 1;
}
100% {
top: 160px;
left: 120px;
opacity: 0;
}
}
@keyframes cloudRight {
0% {
top: 100px;
left: 500px;
opacity: 0;
}
20% {
top: 120px;
left: 460px;
opacity: 1;
}
80% {
top: 180px;
left: 340px;
opacity: 1;
}
100% {
top: 200px;
left: 300px;
opacity: 0;
}
}
}
}
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 150px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #1482f0;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
} }
100% { 100% {
transform: translateY(0); top: 200px;
opacity: 1; left: 300px;
opacity: 0;
} }
} }
} }
} }
.bullshit {
position: relative;
float: left;
width: 300px;
padding: 150px 0;
overflow: hidden;
&__oops {
font-size: 32px;
font-weight: bold;
line-height: 40px;
color: #1482f0;
opacity: 0;
margin-bottom: 20px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
}
&__headline {
font-size: 20px;
line-height: 24px;
color: #1482f0;
opacity: 0;
margin-bottom: 10px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.1s;
animation-fill-mode: forwards;
}
&__info {
font-size: 13px;
line-height: 21px;
color: grey;
opacity: 0;
margin-bottom: 30px;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.2s;
animation-fill-mode: forwards;
}
&__return-home {
display: block;
float: left;
width: 110px;
height: 36px;
background: #1482f0;
border-radius: 100px;
text-align: center;
color: #ffffff;
opacity: 0;
font-size: 14px;
line-height: 36px;
cursor: pointer;
animation-name: slideUp;
animation-duration: 0.5s;
animation-delay: 0.3s;
animation-fill-mode: forwards;
}
@keyframes slideUp {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
}
}
</style> </style>

View File

@ -120,141 +120,141 @@
</template> </template>
<script> <script>
import Tinymce from 'components/Tinymce' import Tinymce from 'components/Tinymce'
import Upload from 'components/Upload/singleImage3' import Upload from 'components/Upload/singleImage3'
import MDinput from 'components/MDinput'; import MDinput from 'components/MDinput';
import { validateURL } from 'utils/validate'; import { validateURL } from 'utils/validate';
import { getArticle } from 'api/article'; import { getArticle } from 'api/article';
import { userSearch } from 'api/remoteSearch'; import { userSearch } from 'api/remoteSearch';
export default { export default {
name: 'articleDetail', name: 'articleDetail',
components: { Tinymce, MDinput, Upload }, components: { Tinymce, MDinput, Upload },
data() { data() {
const validateRequire = (rule, value, callback) => { const validateRequire = (rule, value, callback) => {
if (value === '') { if (value === '') {
this.$message({
message: rule.field + '为必传项',
type: 'error'
});
callback(null)
} else {
callback()
}
};
const validateSourceUri = (rule, value, callback) => {
if (value) {
if (validateURL(value)) {
callback()
} else {
this.$message({ this.$message({
message: rule.field + '为必传项', message: '外链url填写不正确',
type: 'error' type: 'error'
}); });
callback(null) callback(null)
} else {
callback()
} }
}; } else {
const validateSourceUri = (rule, value, callback) => { callback()
if (value) { }
if (validateURL(value)) { };
callback() return {
} else { postForm: {
this.$message({ title: '', //
message: '外链url填写不正确', content: '', //
type: 'error' content_short: '', //
}); source_uri: '', //
callback(null) image_uri: '', //
} source_name: '', //
} else { display_time: undefined, //
callback() id: undefined,
} platforms: ['a-platform']
}; },
return { fetchSuccess: true,
postForm: { loading: false,
title: '', // userLIstOptions: [],
content: '', // platformsOptions: [
content_short: '', //
source_uri: '', //
image_uri: '', //
source_name: '', //
display_time: undefined, //
id: undefined,
platforms: ['a-platform']
},
fetchSuccess: true,
loading: false,
userLIstOptions: [],
platformsOptions: [
{ key: 'a-platform', name: 'a-platform' }, { key: 'a-platform', name: 'a-platform' },
{ key: 'b-platform', name: 'b-platform' }, { key: 'b-platform', name: 'b-platform' },
{ key: 'c-platform', name: 'c-platform' } { key: 'c-platform', name: 'c-platform' }
], ],
rules: { rules: {
image_uri: [{ validator: validateRequire }], image_uri: [{ validator: validateRequire }],
title: [{ validator: validateRequire }], title: [{ validator: validateRequire }],
content: [{ validator: validateRequire }], content: [{ validator: validateRequire }],
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }] source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
}
}
},
computed: {
contentShortLength() {
return this.postForm.content_short.length
},
isEdit() {
return this.$route.meta.isEdit // meta
// return this.$route.path.indexOf('edit') !== -1 //
}
},
created() {
if (this.isEdit) {
this.fetchData();
}
},
methods: {
fetchData() {
getArticle().then(response => {
this.postForm = response.data;
}).catch(err => {
this.fetchSuccess = false;
console.log(err);
});
},
submitForm() {
this.postForm.display_time = parseInt(this.display_time / 1000);
console.log(this.postForm)
this.$refs.postForm.validate(valid => {
if (valid) {
this.loading = true;
this.$notify({
title: '成功',
message: '发布文章成功',
type: 'success',
duration: 2000
});
this.postForm.status = 'published';
this.loading = false;
} else {
console.log('error submit!!');
return false;
}
});
},
draftForm() {
if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
this.$message({
message: '请填写必要的标题和内容',
type: 'warning'
});
return;
}
this.$message({
message: '保存成功',
type: 'success',
showClose: true,
duration: 1000
});
this.postForm.status = 'draft';
},
getRemoteUserList(query) {
userSearch(query).then(response => {
if (!response.data.items) return;
console.log(response)
this.userLIstOptions = response.data.items.map(v => ({
key: v.name
}));
})
} }
} }
},
computed: {
contentShortLength() {
return this.postForm.content_short.length
},
isEdit() {
return this.$route.meta.isEdit // meta
// return this.$route.path.indexOf('edit') !== -1 //
}
},
created() {
if (this.isEdit) {
this.fetchData();
}
},
methods: {
fetchData() {
getArticle().then(response => {
this.postForm = response.data;
}).catch(err => {
this.fetchSuccess = false;
console.log(err);
});
},
submitForm() {
this.postForm.display_time = parseInt(this.display_time / 1000);
console.log(this.postForm)
this.$refs.postForm.validate(valid => {
if (valid) {
this.loading = true;
this.$notify({
title: '成功',
message: '发布文章成功',
type: 'success',
duration: 2000
});
this.postForm.status = 'published';
this.loading = false;
} else {
console.log('error submit!!');
return false;
}
});
},
draftForm() {
if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
this.$message({
message: '请填写必要的标题和内容',
type: 'warning'
});
return;
}
this.$message({
message: '保存成功',
type: 'success',
showClose: true,
duration: 1000
});
this.postForm.status = 'draft';
},
getRemoteUserList(query) {
userSearch(query).then(response => {
if (!response.data.items) return;
console.log(response)
this.userLIstOptions = response.data.items.map(v => ({
key: v.name
}));
})
}
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss"; @import "src/styles/mixin.scss";

View File

@ -60,64 +60,64 @@
</template> </template>
<script> <script>
import { fetchList } from 'api/article_table'; import { fetchList } from 'api/article_table';
import Sortable from 'sortablejs' import Sortable from 'sortablejs'
export default { export default {
name: 'drag-table_demo', name: 'drag-table_demo',
data() { data() {
return { return {
list: null, list: null,
total: null, total: null,
listLoading: true, listLoading: true,
listQuery: { listQuery: {
page: 1, page: 1,
limit: 10 limit: 10
},
sortable: null,
olderList: [],
newList: []
}
},
created() {
this.getList();
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'gray',
deleted: 'danger'
};
return statusMap[status]
}
},
methods: {
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.list = response.data.items;
this.total = response.data.total;
this.listLoading = false;
this.olderList = this.list.map(v => v.id);
this.newList = this.olderList.slice();
this.$nextTick(() => {
this.setSort()
})
})
}, },
setSort() { sortable: null,
const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]; olderList: [],
this.sortable = Sortable.create(el, { newList: []
}
},
created() {
this.getList();
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'gray',
deleted: 'danger'
};
return statusMap[status]
}
},
methods: {
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.list = response.data.items;
this.total = response.data.total;
this.listLoading = false;
this.olderList = this.list.map(v => v.id);
this.newList = this.olderList.slice();
this.$nextTick(() => {
this.setSort()
})
})
},
setSort() {
const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0];
this.sortable = Sortable.create(el, {
// handle: '.drag-handler', // handle: '.drag-handler',
onEnd: evt => { onEnd: evt => {
const tempIndex = this.newList.splice(evt.oldIndex, 1)[0]; const tempIndex = this.newList.splice(evt.oldIndex, 1)[0];
this.newList.splice(evt.newIndex, 0, tempIndex); this.newList.splice(evt.newIndex, 0, tempIndex);
} }
}); });
}
} }
} }
}
</script> </script>
<style > <style >

View File

@ -1,10 +1,10 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<div style='margin:0 0 5px 20px'>固定表头 按照表头顺序排序</div> <div style='margin:0 0 5px 20px'>固定表头 按照表头顺序排序</div>
<fixed-thead/> <fixed-thead></fixed-thead>
<div style='margin:30px 0 5px 20px'>不固定表头 按照点击顺序排序</div> <div style='margin:30px 0 5px 20px'>不固定表头 按照点击顺序排序</div>
<unfixed-thead/> <unfixed-thead></unfixed-thead>
</div> </div>
</template> </template>

View File

@ -23,7 +23,7 @@
<el-table-column width="100px" label="重要性"> <el-table-column width="100px" label="重要性">
<template scope="scope"> <template scope="scope">
<icon-svg v-for="n in +scope.row.importance" icon-class="wujiaoxing" class="meta-item__icon" :key="n" ></icon-svg> <icon-svg v-for="n in +scope.row.importance" icon-class="wujiaoxing" class="meta-item__icon" :key="n"></icon-svg>
</template> </template>
</el-table-column> </el-table-column>
@ -52,44 +52,44 @@
</template> </template>
<script> <script>
import { fetchList } from 'api/article_table'; import { fetchList } from 'api/article_table';
export default { export default {
name: 'inline_edit-table_demo', name: 'inline_edit-table_demo',
data() { data() {
return { return {
list: null, list: null,
listLoading: true, listLoading: true,
listQuery: { listQuery: {
page: 1, page: 1,
limit: 10 limit: 10
}
}
},
created() {
this.getList();
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'gray',
deleted: 'danger'
};
return statusMap[status]
}
},
methods: {
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.list = response.data.items.map(v => {
v.edit = false;
return v
});
this.listLoading = false;
})
} }
} }
},
created() {
this.getList();
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'gray',
deleted: 'danger'
};
return statusMap[status]
}
},
methods: {
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.list = response.data.items.map(v => {
v.edit = false;
return v
});
this.listLoading = false;
})
}
} }
}
</script> </script>

View File

@ -60,7 +60,7 @@
<el-table-column width="80px" label="重要性"> <el-table-column width="80px" label="重要性">
<template scope="scope"> <template scope="scope">
<icon-svg v-for="n in +scope.row.importance" icon-class="wujiaoxing" class="meta-item__icon" :key="n" ></icon-svg> <icon-svg v-for="n in +scope.row.importance" icon-class="wujiaoxing" class="meta-item__icon" :key="n"></icon-svg>
</template> </template>
</el-table-column> </el-table-column>
@ -150,199 +150,199 @@
</template> </template>
<script> <script>
import { fetchList, fetchPv } from 'api/article_table'; import { fetchList, fetchPv } from 'api/article_table';
import { parseTime } from 'utils'; import { parseTime } from 'utils';
const calendarTypeOptions = [ const calendarTypeOptions = [
{ key: 'CN', display_name: '中国' }, { key: 'CN', display_name: '中国' },
{ key: 'US', display_name: '美国' }, { key: 'US', display_name: '美国' },
{ key: 'JP', display_name: '日本' }, { key: 'JP', display_name: '日本' },
{ key: 'EU', display_name: '欧元区' } { key: 'EU', display_name: '欧元区' }
]; ];
// arr to obj // arr to obj
const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => { const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
acc[cur.key] = cur.display_name; acc[cur.key] = cur.display_name;
return acc return acc
}, {}); }, {});
export default { export default {
name: 'table_demo', name: 'table_demo',
data() { data() {
return { return {
list: null, list: null,
total: null, total: null,
listLoading: true, listLoading: true,
listQuery: { listQuery: {
page: 1, page: 1,
limit: 20, limit: 20,
importance: undefined, importance: undefined,
title: undefined, title: undefined,
type: undefined, type: undefined,
sort: '+id' sort: '+id'
}, },
temp: { temp: {
id: undefined, id: undefined,
importance: 0, importance: 0,
remark: '', remark: '',
timestamp: 0, timestamp: 0,
title: '', title: '',
type: '', type: '',
status: 'published' status: 'published'
}, },
importanceOptions: [1, 2, 3], importanceOptions: [1, 2, 3],
calendarTypeOptions, calendarTypeOptions,
sortOptions: [{ label: '按ID升序列', key: '+id' }, { label: '按ID降序', key: '-id' }], sortOptions: [{ label: '按ID升序列', key: '+id' }, { label: '按ID降序', key: '-id' }],
statusOptions: ['published', 'draft', 'deleted'], statusOptions: ['published', 'draft', 'deleted'],
dialogFormVisible: false, dialogFormVisible: false,
dialogStatus: '', dialogStatus: '',
textMap: { textMap: {
update: '编辑', update: '编辑',
create: '创建' create: '创建'
}, },
dialogPvVisible: false, dialogPvVisible: false,
pvData: [], pvData: [],
showAuditor: false, showAuditor: false,
tableKey: 0 tableKey: 0
} }
},
created() {
this.getList();
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'gray',
deleted: 'danger'
};
return statusMap[status]
}, },
created() { typeFilter(type) {
return calendarTypeKeyValue[type]
}
},
methods: {
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.list = response.data.items;
this.total = response.data.total;
this.listLoading = false;
})
},
handleFilter() {
this.getList(); this.getList();
}, },
filters: { handleSizeChange(val) {
statusFilter(status) { this.listQuery.limit = val;
const statusMap = { this.getList();
published: 'success',
draft: 'gray',
deleted: 'danger'
};
return statusMap[status]
},
typeFilter(type) {
return calendarTypeKeyValue[type]
}
}, },
methods: { handleCurrentChange(val) {
getList() { this.listQuery.page = val;
this.listLoading = true; this.getList();
fetchList(this.listQuery).then(response => { },
this.list = response.data.items; timeFilter(time) {
this.total = response.data.total; if (!time[0]) {
this.listLoading = false; this.listQuery.start = undefined;
}) this.listQuery.end = undefined;
}, return;
handleFilter() {
this.getList();
},
handleSizeChange(val) {
this.listQuery.limit = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.page = val;
this.getList();
},
timeFilter(time) {
if (!time[0]) {
this.listQuery.start = undefined;
this.listQuery.end = undefined;
return;
}
this.listQuery.start = parseInt(+time[0] / 1000);
this.listQuery.end = parseInt((+time[1] + 3600 * 1000 * 24) / 1000);
},
handleModifyStatus(row, status) {
this.$message({
message: '操作成功',
type: 'success'
});
row.status = status;
},
handleCreate() {
this.resetTemp();
this.dialogStatus = 'create';
this.dialogFormVisible = true;
},
handleUpdate(row) {
this.temp = Object.assign({}, row);
this.dialogStatus = 'update';
this.dialogFormVisible = true;
},
handleDelete(row) {
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
});
const index = this.list.indexOf(row);
this.list.splice(index, 1);
},
create() {
this.temp.id = parseInt(Math.random() * 100) + 1024;
this.temp.timestamp = +new Date();
this.temp.author = '原创作者';
this.list.unshift(this.temp);
this.dialogFormVisible = false;
this.$notify({
title: '成功',
message: '创建成功',
type: 'success',
duration: 2000
});
},
update() {
this.temp.timestamp = +this.temp.timestamp;
for (const v of this.list) {
if (v.id === this.temp.id) {
const index = this.list.indexOf(v);
this.list.splice(index, 1, this.temp);
break;
}
}
this.dialogFormVisible = false;
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
});
},
resetTemp() {
this.temp = {
id: undefined,
importance: 0,
remark: '',
timestamp: 0,
title: '',
status: 'published',
type: ''
};
},
handleFetchPv(pv) {
fetchPv(pv).then(response => {
this.pvData = response.data.pvData;
this.dialogPvVisible = true;
})
},
handleDownload() {
require.ensure([], () => {
const { export_json_to_excel } = require('vendor/Export2Excel');
const tHeader = ['时间', '地区', '类型', '标题', '重要性'];
const filterVal = ['timestamp', 'province', 'type', 'title', 'importance'];
const data = this.formatJson(filterVal, this.list);
export_json_to_excel(tHeader, data, 'table数据');
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
} }
this.listQuery.start = parseInt(+time[0] / 1000);
this.listQuery.end = parseInt((+time[1] + 3600 * 1000 * 24) / 1000);
},
handleModifyStatus(row, status) {
this.$message({
message: '操作成功',
type: 'success'
});
row.status = status;
},
handleCreate() {
this.resetTemp();
this.dialogStatus = 'create';
this.dialogFormVisible = true;
},
handleUpdate(row) {
this.temp = Object.assign({}, row);
this.dialogStatus = 'update';
this.dialogFormVisible = true;
},
handleDelete(row) {
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
});
const index = this.list.indexOf(row);
this.list.splice(index, 1);
},
create() {
this.temp.id = parseInt(Math.random() * 100) + 1024;
this.temp.timestamp = +new Date();
this.temp.author = '原创作者';
this.list.unshift(this.temp);
this.dialogFormVisible = false;
this.$notify({
title: '成功',
message: '创建成功',
type: 'success',
duration: 2000
});
},
update() {
this.temp.timestamp = +this.temp.timestamp;
for (const v of this.list) {
if (v.id === this.temp.id) {
const index = this.list.indexOf(v);
this.list.splice(index, 1, this.temp);
break;
}
}
this.dialogFormVisible = false;
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
});
},
resetTemp() {
this.temp = {
id: undefined,
importance: 0,
remark: '',
timestamp: 0,
title: '',
status: 'published',
type: ''
};
},
handleFetchPv(pv) {
fetchPv(pv).then(response => {
this.pvData = response.data.pvData;
this.dialogPvVisible = true;
})
},
handleDownload() {
require.ensure([], () => {
const { export_json_to_excel } = require('vendor/Export2Excel');
const tHeader = ['时间', '地区', '类型', '标题', '重要性'];
const filterVal = ['timestamp', 'province', 'type', 'title', 'importance'];
const data = this.formatJson(filterVal, this.list);
export_json_to_excel(tHeader, data, 'table数据');
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
} }
} }
}
</script> </script>

View File

@ -34,38 +34,41 @@
</template> </template>
<script> <script>
import { getList } from 'api/article'; import { getList } from 'api/article';
export default {
data() { export default {
return { data() {
list: null, return {
listLoading: true list: null,
} listLoading: true
}, }
created() {
this.fetchData();
},
methods: {
fetchData() {
this.listLoading = true;
getList(this.listQuery).then(response => {
this.list = response.data;
this.listLoading = false;
})
}, },
handleDownload() { created() {
require.ensure([], () => { this.fetchData();
const { export_json_to_excel } = require('vendor/Export2Excel');
const tHeader = ['序号', '文章标题', '作者', '阅读数', '发布时间'];
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time'];
const list = this.list;
const data = this.formatJson(filterVal, list);
export_json_to_excel(tHeader, data, '列表excel');
})
}, },
formatJson(filterVal, jsonData) { methods: {
return jsonData.map(v => filterVal.map(j => v[j])) fetchData() {
this.listLoading = true;
getList(this.listQuery).then(response => {
this.list = response.data;
this.listLoading = false;
})
},
handleDownload() {
require.ensure([], () => {
const {
export_json_to_excel
} = require('vendor/Export2Excel');
const tHeader = ['序号', '文章标题', '作者', '阅读数', '发布时间'];
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time'];
const list = this.list;
const data = this.formatJson(filterVal, list);
export_json_to_excel(tHeader, data, '列表excel');
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]))
}
} }
} };
};
</script> </script>

View File

@ -12,7 +12,7 @@
<li><a target='_blank' href="https://juejin.im/post/593121aa0ce4630057f70d35">手摸手带你用 vue 撸后台 系列三 (实战篇)</a></li> <li><a target='_blank' href="https://juejin.im/post/593121aa0ce4630057f70d35">手摸手带你用 vue 撸后台 系列三 (实战篇)</a></li>
<li><a target='_blank' href="https://segmentfault.com/a/1190000009090836">手摸手带你封装一个vue component</a></li> <li><a target='_blank' href="https://segmentfault.com/a/1190000009090836">手摸手带你封装一个vue component</a></li>
</ul> </ul>
</code> </code>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,18 +1,18 @@
<template> <template>
<section class="app-main" style="min-height: 100%"> <section class="app-main" style="min-height: 100%">
<transition name="fade" mode="out-in"> <transition name="fade" mode="out-in">
<router-view :key="key"></router-view> <router-view :key="key"></router-view>
</transition> </transition>
</section> </section>
</template> </template>
<script> <script>
export default { export default {
name: 'AppMain', name: 'AppMain',
computed: { computed: {
key() { key() {
return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date() return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date()
}
}
} }
}
}
</script> </script>

View File

@ -1,80 +1,80 @@
<template> <template>
<div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}"> <div class="app-wrapper" :class="{hideSidebar:!sidebar.opened}">
<div class="sidebar-wrapper"> <div class="sidebar-wrapper">
<Sidebar class="sidebar-container" /> <sidebar class="sidebar-container"></sidebar>
</div> </div>
<div class="main-container"> <div class="main-container">
<Navbar/> <navbar></navbar>
<App-main/> <app-main></app-main>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { Navbar, Sidebar, AppMain } from 'views/layout'; import { Navbar, Sidebar, AppMain } from 'views/layout';
export default { export default {
name: 'layout', name: 'layout',
components: { components: {
Navbar, Navbar,
Sidebar, Sidebar,
AppMain AppMain
}, },
computed: { computed: {
sidebar() { sidebar() {
return this.$store.state.app.sidebar; return this.$store.state.app.sidebar;
}
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss"; @import "src/styles/mixin.scss";
.app-wrapper { .app-wrapper {
@include clearfix; @include clearfix;
position: relative; position: relative;
height: 100%; height: 100%;
width: 100%; width: 100%;
&.hideSidebar { &.hideSidebar {
.sidebar-wrapper { .sidebar-wrapper {
transform: translate(-140px, 0); transform: translate(-140px, 0);
.sidebar-container { .sidebar-container {
transform: translate(132px, 0); transform: translate(132px, 0);
} }
&:hover { &:hover {
transform: translate(0, 0); transform: translate(0, 0);
.sidebar-container { .sidebar-container {
transform: translate(0, 0); transform: translate(0, 0);
} }
} }
} }
.main-container{ .main-container {
margin-left: 40px; margin-left: 40px;
} }
} }
.sidebar-wrapper { .sidebar-wrapper {
width: 180px; width: 180px;
position: fixed; position: fixed;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 1001; z-index: 1001;
overflow: hidden; overflow: hidden;
transition: all .28s ease-out; transition: all .28s ease-out;
} }
.sidebar-container { .sidebar-container {
transition: all .28s ease-out; transition: all .28s ease-out;
position: absolute; position: absolute;
top: 0; top: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
right: -17px; right: -17px;
overflow-y: scroll; overflow-y: scroll;
} }
.main-container { .main-container {
min-height: 100%; min-height: 100%;
transition: all .28s ease-out; transition: all .28s ease-out;
margin-left: 180px; margin-left: 180px;
} }
} }
</style> </style>

View File

@ -8,42 +8,42 @@
</template> </template>
<script> <script>
export default { export default {
created() { created() {
this.getBreadcrumb() this.getBreadcrumb()
}, },
data() { data() {
return { return {
levelList: null levelList: null
} }
}, },
methods: { methods: {
getBreadcrumb() { getBreadcrumb() {
let matched = this.$route.matched.filter(item => item.name); let matched = this.$route.matched.filter(item => item.name);
const first = matched[0]; const first = matched[0];
if (first && (first.name !== '首页' || first.path !== '')) { if (first && (first.name !== '首页' || first.path !== '')) {
matched = [{ name: '首页', path: '/' }].concat(matched) matched = [{ name: '首页', path: '/' }].concat(matched)
}
this.levelList = matched;
}
},
watch: {
$route() {
this.getBreadcrumb();
} }
this.levelList = matched;
}
},
watch: {
$route() {
this.getBreadcrumb();
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.app-levelbar.el-breadcrumb { .app-levelbar.el-breadcrumb {
display: inline-block; display: inline-block;
font-size: 14px; font-size: 14px;
line-height: 50px; line-height: 50px;
margin-left: 10px; margin-left: 10px;
.no-redirect{ .no-redirect {
color: #97a8be; color: #97a8be;
cursor:text; cursor: text;
}
} }
}
</style> </style>

View File

@ -1,119 +1,119 @@
<template> <template>
<el-menu class="navbar" mode="horizontal"> <el-menu class="navbar" mode="horizontal">
<hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger> <hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger>
<levelbar></levelbar> <levelbar></levelbar>
<tabs-view></tabs-view> <tabs-view></tabs-view>
<error-log v-if="log.length>0" class="errLog-container" :logsList="log"></error-log> <error-log v-if="log.length>0" class="errLog-container" :logsList="log"></error-log>
<screenfull class='screenfull'></screenfull> <screenfull class='screenfull'></screenfull>
<el-dropdown class="avatar-container" trigger="click"> <el-dropdown class="avatar-container" trigger="click">
<div class="avatar-wrapper"> <div class="avatar-wrapper">
<img class="user-avatar" :src="avatar+'?imageView2/1/w/80/h/80'"> <img class="user-avatar" :src="avatar+'?imageView2/1/w/80/h/80'">
<i class="el-icon-caret-bottom"></i> <i class="el-icon-caret-bottom"></i>
</div> </div>
<el-dropdown-menu class="user-dropdown" slot="dropdown"> <el-dropdown-menu class="user-dropdown" slot="dropdown">
<router-link class='inlineBlock' to="/"> <router-link class='inlineBlock' to="/">
<el-dropdown-item> <el-dropdown-item>
首页 首页
</el-dropdown-item> </el-dropdown-item>
</router-link> </router-link>
<a target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/"> <a target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">
<el-dropdown-item> <el-dropdown-item>
项目地址 项目地址
</el-dropdown-item> </el-dropdown-item>
</a> </a>
<el-dropdown-item divided><span @click="logout" style="display:block;">退出登录</span></el-dropdown-item> <el-dropdown-item divided><span @click="logout" style="display:block;">退出登录</span></el-dropdown-item>
</el-dropdown-menu> </el-dropdown-menu>
</el-dropdown> </el-dropdown>
</el-menu> </el-menu>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import Levelbar from './Levelbar'; import Levelbar from './Levelbar';
import TabsView from './TabsView'; import TabsView from './TabsView';
import Hamburger from 'components/Hamburger'; import Hamburger from 'components/Hamburger';
import Screenfull from 'components/Screenfull'; import Screenfull from 'components/Screenfull';
import ErrorLog from 'components/ErrLog'; import ErrorLog from 'components/ErrLog';
import errLogStore from 'store/errLog'; import errLogStore from 'store/errLog';
export default { export default {
components: { components: {
Levelbar, Levelbar,
TabsView, TabsView,
Hamburger, Hamburger,
ErrorLog, ErrorLog,
Screenfull Screenfull
},
data() {
return {
log: errLogStore.state.errLog
}
},
computed: {
...mapGetters([
'sidebar',
'name',
'avatar'
])
},
methods: {
toggleSideBar() {
this.$store.dispatch('ToggleSideBar')
}, },
data() { logout() {
return { this.$store.dispatch('LogOut').then(() => {
log: errLogStore.state.errLog location.reload();// vue-router bug
} });
},
computed: {
...mapGetters([
'sidebar',
'name',
'avatar'
])
},
methods: {
toggleSideBar() {
this.$store.dispatch('ToggleSideBar')
},
logout() {
this.$store.dispatch('LogOut').then(() => {
location.reload();// vue-router bug
});
}
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.navbar { .navbar {
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
border-radius: 0px !important; border-radius: 0px !important;
.hamburger-container { .hamburger-container {
line-height: 58px; line-height: 58px;
height: 50px; height: 50px;
float: left; float: left;
padding: 0 10px; padding: 0 10px;
} }
.errLog-container { .errLog-container {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
right: 150px; right: 150px;
} }
.screenfull{ .screenfull {
position: absolute; position: absolute;
right: 90px; right: 90px;
top: 16px; top: 16px;
color: red; color: red;
} }
.avatar-container { .avatar-container {
height: 50px; height: 50px;
display: inline-block; display: inline-block;
position: absolute; position: absolute;
right: 35px; right: 35px;
.avatar-wrapper { .avatar-wrapper {
cursor: pointer; cursor: pointer;
margin-top:5px; margin-top: 5px;
position: relative; position: relative;
.user-avatar { .user-avatar {
width: 40px; width: 40px;
height: 40px; height: 40px;
border-radius: 10px; border-radius: 10px;
} }
.el-icon-caret-bottom { .el-icon-caret-bottom {
position: absolute; position: absolute;
right: -20px; right: -20px;
top: 25px; top: 25px;
font-size: 12px; font-size: 12px;
} }
} }
} }
} }
</style> </style>

View File

@ -1,24 +1,24 @@
<template> <template>
<el-menu mode="vertical" theme="dark" :default-active="$route.path"> <el-menu mode="vertical" theme="dark" :default-active="$route.path">
<sidebar-item :routes='permission_routers'></sidebar-item> <sidebar-item :routes='permission_routers'></sidebar-item>
</el-menu> </el-menu>
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import SidebarItem from './SidebarItem'; import SidebarItem from './SidebarItem';
export default { export default {
components: { SidebarItem }, components: { SidebarItem },
computed: { computed: {
...mapGetters([ ...mapGetters([
'permission_routers' 'permission_routers'
]) ])
}
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.el-menu { .el-menu {
min-height: 100%; min-height: 100%;
} }
</style> </style>

View File

@ -1,47 +1,47 @@
<template> <template>
<div> <div>
<template v-for="item in routes"> <template v-for="item in routes">
<router-link v-if="!item.hidden&&item.noDropdown&&item.children.length>0" :to="item.path+'/'+item.children[0].path"> <router-link v-if="!item.hidden&&item.noDropdown&&item.children.length>0" :to="item.path+'/'+item.children[0].path">
<el-menu-item :index="item.path+'/'+item.children[0].path"> <el-menu-item :index="item.path+'/'+item.children[0].path">
<icon-svg v-if='item.icon' :icon-class="item.icon" ></icon-svg>{{item.children[0].name}} <icon-svg v-if='item.icon' :icon-class="item.icon"></icon-svg>{{item.children[0].name}}
</el-menu-item> </el-menu-item>
</router-link> </router-link>
<el-submenu :index="item.name" v-if="!item.noDropdown&&!item.hidden"> <el-submenu :index="item.name" v-if="!item.noDropdown&&!item.hidden">
<template slot="title"> <template slot="title">
<icon-svg v-if='item.icon' :icon-class="item.icon" ></icon-svg> {{item.name}} <icon-svg v-if='item.icon' :icon-class="item.icon"></icon-svg> {{item.name}}
</template> </template>
<template v-for="child in item.children" v-if='!child.hidden'> <template v-for="child in item.children" v-if='!child.hidden'>
<sidebar-item class='menu-indent' v-if='child.children&&child.children.length>0' :routes='[child]'> </sidebar-item> <sidebar-item class='menu-indent' v-if='child.children&&child.children.length>0' :routes='[child]'> </sidebar-item>
<router-link v-else class="menu-indent" :to="item.path+'/'+child.path"> <router-link v-else class="menu-indent" :to="item.path+'/'+child.path">
<el-menu-item :index="item.path+'/'+child.path"> <el-menu-item :index="item.path+'/'+child.path">
{{child.name}} {{child.name}}
</el-menu-item> </el-menu-item>
</router-link> </router-link>
</template> </template>
</el-submenu> </el-submenu>
</template> </template>
</div> </div>
</template> </template>
<script> <script>
export default {
export default { name: 'SidebarItem',
name: 'SidebarItem', props: {
props: { routes: {
routes: { type: Array
type: Array
}
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.svg-icon { .svg-icon {
margin-right: 10px; margin-right: 10px;
} }
.hideSidebar .menu-indent{
display: block; .hideSidebar .menu-indent {
text-indent: 10px; display: block;
} text-indent: 10px;
}
</style> </style>

View File

@ -5,48 +5,47 @@
{{tag.name}} {{tag.name}}
</el-tag> </el-tag>
</router-link> </router-link>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
computed: { computed: {
visitedViews() { visitedViews() {
return this.$store.state.app.visitedViews.slice(-6) return this.$store.state.app.visitedViews.slice(-6)
} }
},
methods: {
closeViewTabs(view, $event) {
this.$store.dispatch('delVisitedViews', view)
$event.preventDefault()
}, },
methods: { generateRoute() {
closeViewTabs(view, $event) { if (this.$route.matched[this.$route.matched.length - 1].name) {
this.$store.dispatch('delVisitedViews', view) return this.$route.matched[this.$route.matched.length - 1]
$event.preventDefault()
},
generateRoute() {
if (this.$route.matched[this.$route.matched.length - 1].name) {
return this.$route.matched[this.$route.matched.length - 1]
}
this.$route.matched[0].path = '/'
return this.$route.matched[0]
},
addViewTabs() {
this.$store.dispatch('addVisitedViews', this.generateRoute())
} }
this.$route.matched[0].path = '/'
return this.$route.matched[0]
}, },
watch: { addViewTabs() {
$route() { this.$store.dispatch('addVisitedViews', this.generateRoute())
this.addViewTabs() }
} },
watch: {
$route() {
this.addViewTabs()
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.tabs-view-container{ .tabs-view-container {
display: inline-block; display: inline-block;
vertical-align: top; vertical-align: top;
margin-left: 10px; margin-left: 10px;
.tabs-view{ .tabs-view {
margin-left: 10px; margin-left: 10px;
} }
} }
</style> </style>

View File

@ -20,72 +20,74 @@
<div class='tips'>admin账号为:admin@wallstreetcn.com 密码随便填</div> <div class='tips'>admin账号为:admin@wallstreetcn.com 密码随便填</div>
<div class='tips'>editor账号:editor@wallstreetcn.com 密码随便填</div> <div class='tips'>editor账号:editor@wallstreetcn.com 密码随便填</div>
</el-form> </el-form>
<el-dialog title="第三方验证" :visible.sync="showDialog"> <el-dialog title="第三方验证" :visible.sync="showDialog">
邮箱登录成功,请选择第三方验证 邮箱登录成功,请选择第三方验证
<socialSign></socialSign> <social-sign></social-sign>
</el-dialog> </el-dialog>
</div> </div>
</template> </template>
<script> <script>
import { isWscnEmail } from 'utils/validate'; import { isWscnEmail } from 'utils/validate';
import socialSign from './socialsignin'; import socialSign from './socialsignin';
export default { export default {
components: { socialSign }, components: { socialSign },
name: 'login', name: 'login',
data() { data() {
const validateEmail = (rule, value, callback) => { const validateEmail = (rule, value, callback) => {
if (!isWscnEmail(value)) { if (!isWscnEmail(value)) {
callback(new Error('请输入正确的合法邮箱')); callback(new Error('请输入正确的合法邮箱'));
} else { } else {
callback(); callback();
}
};
const validatePass = (rule, value, callback) => {
if (value.length < 6) {
callback(new Error('密码不能小于6位'));
} else {
callback();
}
};
return {
loginForm: {
email: 'admin@wallstreetcn.com',
password: ''
},
loginRules: {
email: [
{ required: true, trigger: 'blur', validator: validateEmail }
],
password: [
{ required: true, trigger: 'blur', validator: validatePass }
]
},
loading: false,
showDialog: false
} }
}, };
methods: { const validatePass = (rule, value, callback) => {
handleLogin() { if (value.length < 6) {
this.$refs.loginForm.validate(valid => { callback(new Error('密码不能小于6位'));
if (valid) { } else {
this.loading = true; callback();
this.$store.dispatch('LoginByEmail', this.loginForm).then(() => { }
this.loading = false; };
this.$router.push({ path: '/' }); return {
// this.showDialog = true; loginForm: {
}).catch(err => { email: 'admin@wallstreetcn.com',
this.$message.error(err); password: ''
this.loading = false;
});
} else {
console.log('error submit!!');
return false;
}
});
}, },
afterQRScan() { loginRules: {
email: [
{ required: true, trigger: 'blur', validator: validateEmail }
],
password: [
{ required: true, trigger: 'blur', validator: validatePass }
]
},
loading: false,
showDialog: false
}
},
methods: {
handleLogin() {
this.$refs.loginForm.validate(valid => {
if (valid) {
this.loading = true;
this.$store.dispatch('LoginByEmail', this.loginForm).then(() => {
this.loading = false;
this.$router.push({ path: '/' });
// this.showDialog = true;
}).catch(err => {
this.$message.error(err);
this.loading = false;
});
} else {
console.log('error submit!!');
return false;
}
});
},
afterQRScan() {
// const hash = window.location.hash.slice(1); // const hash = window.location.hash.slice(1);
// const hashObj = getQueryObject(hash); // const hashObj = getQueryObject(hash);
// const originUrl = window.location.origin; // const originUrl = window.location.origin;
@ -102,80 +104,75 @@
// this.$router.push({ path: '/' }); // this.$router.push({ path: '/' });
// }); // });
// } // }
}
},
created() {
// window.addEventListener('hashchange', this.afterQRScan);
},
destroyed() {
// window.removeEventListener('hashchange', this.afterQRScan);
} }
},
created() {
// window.addEventListener('hashchange', this.afterQRScan);
},
destroyed() {
// window.removeEventListener('hashchange', this.afterQRScan);
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss"> <style rel="stylesheet/scss" lang="scss">
@import "src/styles/mixin.scss"; @import "src/styles/mixin.scss";
.tips{ .tips {
font-size: 14px; font-size: 14px;
color: #fff;
margin-bottom: 5px;
}
.login-container {
@include relative;
height: 100vh;
background-color: #2d3a4b;
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px #293444 inset !important;
-webkit-text-fill-color: #fff !important;
}
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: #eeeeee;
height: 47px;
}
.el-input {
display: inline-block;
height: 47px;
width: 85%;
}
.svg-container {
padding: 6px 5px 6px 15px;
color: #889aa4;
}
.title {
font-size: 26px;
font-weight: 400;
color: #eeeeee;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
.login-form {
position: absolute;
left: 0;
right: 0;
width: 400px;
padding: 35px 35px 15px 35px;
margin: 120px auto;
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
.forget-pwd {
color: #fff; color: #fff;
margin-bottom: 5px;
} }
.login-container { }
@include relative;
height: 100vh;
background-color: #2d3a4b;
input:-webkit-autofill {
-webkit-box-shadow: 0 0 0px 1000px #293444 inset !important;
-webkit-text-fill-color: #fff !important;
}
input {
background: transparent;
border: 0px;
-webkit-appearance: none;
border-radius: 0px;
padding: 12px 5px 12px 15px;
color: #eeeeee;
height: 47px;
}
.el-input {
display: inline-block;
height: 47px;
width: 85%;
}
.svg-container {
padding: 6px 5px 6px 15px;
color: #889aa4;
}
.title {
font-size: 26px;
font-weight: 400;
color: #eeeeee;
margin: 0px auto 40px auto;
text-align: center;
font-weight: bold;
}
.login-form {
position: absolute;
left: 0;
right: 0;
width: 400px;
padding: 35px 35px 15px 35px;
margin: 120px auto;
}
.el-form-item {
border: 1px solid rgba(255, 255, 255, 0.1);
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
color: #454545;
}
.forget-pwd {
color: #fff;
}
}
</style> </style>

View File

@ -1,66 +1,68 @@
<template> <template>
<div class="social-signup-container"> <div class="social-signup-container">
<div class="sign-btn" @click="wechatHandleClick('wechat')"> <div class="sign-btn" @click="wechatHandleClick('wechat')">
<span class="wx-svg-container"><icon-svg icon-class="weixin" class="icon"></icon-svg></span> <span class="wx-svg-container"><icon-svg icon-class="weixin" class="icon"></icon-svg></span>
</div> </div>
<div class="sign-btn" @click="tencentHandleClick('tencent')"> <div class="sign-btn" @click="tencentHandleClick('tencent')">
<span class="qq-svg-container"><icon-svg icon-class="QQ" class="icon"></icon-svg></span> QQ <span class="qq-svg-container"><icon-svg icon-class="QQ" class="icon"></icon-svg></span> QQ
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import openWindow from 'utils/openWindow'; import openWindow from 'utils/openWindow';
export default { export default {
name: 'social-signin', name: 'social-signin',
methods: { methods: {
wechatHandleClick(thirdpart) { wechatHandleClick(thirdpart) {
this.$store.commit('SET_AUTH_TYPE', thirdpart); this.$store.commit('SET_AUTH_TYPE', thirdpart);
const appid = 'xxxxx'; const appid = 'xxxxx';
const redirect_uri = encodeURIComponent('xxx/redirect?redirect=' + window.location.origin + '/authredirect'); const redirect_uri = encodeURIComponent('xxx/redirect?redirect=' + window.location.origin + '/authredirect');
const url = 'https://open.weixin.qq.com/connect/qrconnect?appid=' + appid + '&redirect_uri=' + redirect_uri + '&response_type=code&scope=snsapi_login#wechat_redirect'; const url = 'https://open.weixin.qq.com/connect/qrconnect?appid=' + appid + '&redirect_uri=' + redirect_uri + '&response_type=code&scope=snsapi_login#wechat_redirect';
openWindow(url, thirdpart, 540, 540); openWindow(url, thirdpart, 540, 540);
}, },
tencentHandleClick(thirdpart) { tencentHandleClick(thirdpart) {
this.$store.commit('SET_AUTH_TYPE', thirdpart); this.$store.commit('SET_AUTH_TYPE', thirdpart);
const client_id = 'xxxxx'; const client_id = 'xxxxx';
const redirect_uri = encodeURIComponent('xxx/redirect?redirect=' + window.location.origin + '/authredirect'); const redirect_uri = encodeURIComponent('xxx/redirect?redirect=' + window.location.origin + '/authredirect');
const url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=' + client_id + '&redirect_uri=' + redirect_uri; const url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=' + client_id + '&redirect_uri=' + redirect_uri;
openWindow(url, thirdpart, 540, 540); openWindow(url, thirdpart, 540, 540);
}
} }
} }
}
</script> </script>
<style rel="stylesheet/scss" lang="scss" scoped> <style rel="stylesheet/scss" lang="scss" scoped>
.social-signup-container { .social-signup-container {
margin: 20px 0; margin: 20px 0;
.sign-btn { .sign-btn {
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
} }
.icon { .icon {
color: #fff; color: #fff;
font-size: 30px; font-size: 30px;
margin-top: 6px; margin-top: 6px;
} }
.wx-svg-container, .qq-svg-container { .wx-svg-container,
display: inline-block; .qq-svg-container {
width: 40px; display: inline-block;
height: 40px; width: 40px;
line-height: 40px; height: 40px;
text-align: center; line-height: 40px;
padding-top: 1px; text-align: center;
border-radius: 4px; padding-top: 1px;
margin-bottom: 20px; border-radius: 4px;
margin-right: 5px; margin-bottom: 20px;
} margin-right: 5px;
.wx-svg-container { }
background-color: #8dc349; .wx-svg-container {
} background-color: #8dc349;
.qq-svg-container { }
background-color: #6BA2D6; .qq-svg-container {
margin-left: 50px; background-color: #6BA2D6;
} margin-left: 50px;
} }
}
</style> </style>

View File

@ -9,24 +9,24 @@
</template> </template>
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
export default{ export default{
data() { data() {
return { return {
role: '' role: ''
} }
}, },
computed: { computed: {
...mapGetters([ ...mapGetters([
'roles' 'roles'
]) ])
}, },
watch: { watch: {
role(val) { role(val) {
this.$store.dispatch('ChangeRole', val).then(() => { this.$store.dispatch('ChangeRole', val).then(() => {
this.$router.push({ path: '/permission/index?' + +new Date() }); this.$router.push({ path: '/permission/index?' + +new Date() });
}) })
}
} }
} }
}
</script> </script>

View File

@ -1,10 +1,5 @@
<template> <template>
<el-upload <el-upload action="https://upload.qbox.me" :data="dataObj" drag :multiple="true" :before-upload="beforeUpload">
action="https://upload.qbox.me"
:data="dataObj"
drag
:multiple="true"
:before-upload="beforeUpload">
<i class="el-icon-upload"></i> <i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div> <div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
</el-upload> </el-upload>
@ -12,33 +7,33 @@
<script> <script>
import { getToken } from 'api/qiniu'; // token Access Key,Secret Key,buckettoken import { getToken } from 'api/qiniu'; // token Access Key,Secret Key,buckettoken
// sdk https://developer.qiniu.com/sdk#official-sdk // sdk https://developer.qiniu.com/sdk#official-sdk
export default{ export default{
data() { data() {
return { return {
dataObj: { token: '', key: '' }, dataObj: { token: '', key: '' },
image_uri: [], image_uri: [],
fileList: [] fileList: []
} }
}, },
methods: { methods: {
beforeUpload() { beforeUpload() {
const _self = this; const _self = this;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
getToken().then(response => { getToken().then(response => {
const key = response.data.qiniu_key; const key = response.data.qiniu_key;
const token = response.data.qiniu_token; const token = response.data.qiniu_token;
_self._data.dataObj.token = token; _self._data.dataObj.token = token;
_self._data.dataObj.key = key; _self._data.dataObj.key = key;
resolve(true); resolve(true);
}).catch(err => { }).catch(err => {
console.log(err) console.log(err)
reject(false) reject(false)
});
}); });
} });
} }
} }
}
</script> </script>

View File

@ -45,31 +45,48 @@
<script> <script>
import { toggleClass } from 'utils'; import { toggleClass } from 'utils';
export default { export default {
data() { data() {
return { return {
theme: false, theme: false,
tags: [ tags: [{
{ name: '标签一', type: '' }, name: '标签一',
{ name: '标签二', type: 'gray' }, type: ''
{ name: '标签三', type: 'primary' }, },
{ name: '标签四', type: 'success' }, {
{ name: '标签五', type: 'warning' }, name: '标签二',
{ name: '标签六', type: 'danger' } type: 'gray'
], },
inputVisible: false, {
inputValue: '' name: '标签三',
} type: 'primary'
}, },
watch: { {
theme() { name: '标签四',
toggleClass(document.body, 'custom-theme') type: 'success'
},
{
name: '标签五',
type: 'warning'
},
{
name: '标签六',
type: 'danger'
}
],
inputVisible: false,
inputValue: ''
}
},
watch: {
theme() {
toggleClass(document.body, 'custom-theme')
// this.$store.dispatch('setTheme', value); // this.$store.dispatch('setTheme', value);
}
} }
} };
};
</script> </script>
<style scoped> <style scoped>