1、数据清理任务增加清理报表数据逻辑

2、删除前端无用的文件
This commit is contained in:
aoshiguchen
2022-11-24 13:50:48 +08:00
parent be00799276
commit 1bd8fabce6
41 changed files with 44 additions and 3098 deletions
-40
View File
@@ -1,40 +0,0 @@
import request from '@/utils/request'
export function fetchList(query) {
return request({
url: '/article/list',
method: 'get',
params: query
})
}
export function fetchArticle() {
return request({
url: '/article/detail',
method: 'get'
})
}
export function fetchPv(pv) {
return request({
url: '/article/pv',
method: 'get',
params: { pv }
})
}
export function createArticle(data) {
return request({
url: '/article/create',
method: 'post',
data
})
}
export function updateArticle(data) {
return request({
url: '/article/update',
method: 'post',
data
})
}
-8
View File
@@ -1,8 +0,0 @@
import request from '@/utils/request'
export function getToken() {
return request({
url: '/qiniu/upload/token', // 假地址 自行替换
method: 'get'
})
}
@@ -1,9 +0,0 @@
import request from '@/utils/request'
export function userSearch(name) {
return request({
url: '/search/user',
method: 'get',
params: { name }
})
}
-201
View File
@@ -29,17 +29,6 @@ export const constantRouterMap = [
{ path: '/authredirect', component: _import('login/authredirect'), hidden: true },
{ path: '/404', component: _import('errorPage/404'), hidden: true },
{ path: '/401', component: _import('errorPage/401'), hidden: true },
// {
// path: '',
// component: Layout,
// redirect: 'dashboard',
// children: [{
// path: 'dashboard',
// component: _import('dashboard/index'),
// name: 'dashboard',
// meta: { title: 'dashboard', icon: 'dashboard', noCache: true }
// }]
// },
{
path: '',
component: Layout,
@@ -51,18 +40,6 @@ export const constantRouterMap = [
meta: { title: 'home', icon: 'dashboard', noCache: true }
}]
}
// , {
// path: '/documentation',
// component: Layout,
// redirect: '/documentation/index',
// children: [{
// path: 'index',
// component: _import('documentation/index'),
// name: 'documentation',
// meta: { title: 'documentation', icon: 'documentation', noCache: true }
// }]
// }
]
export default new Router({
@@ -72,184 +49,6 @@ export default new Router({
})
export const asyncRouterMap = [
// {
// path: '/permission',
// component: Layout,
// redirect: '/permission/index',
// meta: { roles: ['admin'] }, // you can set roles in root nav
// children: [{
// path: 'index',
// component: _import('permission/index'),
// name: 'permission',
// meta: {
// title: 'permission',
// icon: 'lock',
// roles: ['admin'] // or you can only set roles in sub nav
// }
// }]
// },
//
// {
// path: '/icon',
// component: Layout,
// children: [{
// path: 'index',
// component: _import('svg-icons/index'),
// name: 'icons',
// meta: { title: 'icons', icon: 'icon', noCache: true }
// }]
// },
//
// {
// path: '/components',
// component: Layout,
// redirect: 'noredirect',
// name: 'component-demo',
// meta: {
// title: 'components',
// icon: 'component'
// },
// children: [
// { path: 'tinymce', component: _import('components-demo/tinymce'), name: 'tinymce-demo', meta: { title: 'tinymce' }},
// { path: 'markdown', component: _import('components-demo/markdown'), name: 'markdown-demo', meta: { title: 'markdown' }},
// { path: 'json-editor', component: _import('components-demo/jsonEditor'), name: 'jsonEditor-demo', meta: { title: 'jsonEditor' }},
// { path: 'dnd-list', component: _import('components-demo/dndList'), name: 'dndList-demo', meta: { title: 'dndList' }},
// { path: 'splitpane', component: _import('components-demo/splitpane'), name: 'splitpane-demo', meta: { title: 'splitPane' }},
// { path: 'avatar-upload', component: _import('components-demo/avatarUpload'), name: 'avatarUpload-demo', meta: { title: 'avatarUpload' }},
// { path: 'dropzone', component: _import('components-demo/dropzone'), name: 'dropzone-demo', meta: { title: 'dropzone' }},
// { path: 'sticky', component: _import('components-demo/sticky'), name: 'sticky-demo', meta: { title: 'sticky' }},
// { path: 'count-to', component: _import('components-demo/countTo'), name: 'countTo-demo', meta: { title: 'countTo' }},
// { path: 'mixin', component: _import('components-demo/mixin'), name: 'componentMixin-demo', meta: { title: 'componentMixin' }},
// { path: 'back-to-top', component: _import('components-demo/backToTop'), name: 'backToTop-demo', meta: { title: 'backToTop' }}
// ]
// },
//
// {
// path: '/charts',
// component: Layout,
// redirect: 'noredirect',
// name: 'charts',
// meta: {
// title: 'charts',
// icon: 'chart'
// },
// children: [
// { path: 'keyboard', component: _import('charts/keyboard'), name: 'keyboardChart', meta: { title: 'keyboardChart', noCache: true }},
// { path: 'line', component: _import('charts/line'), name: 'lineChart', meta: { title: 'lineChart', noCache: true }},
// { path: 'mixchart', component: _import('charts/mixChart'), name: 'mixChart', meta: { title: 'mixChart', noCache: true }}
// ]
// },
//
// {
// path: '/example',
// component: Layout,
// redirect: '/example/table/complex-table',
// name: 'example',
// meta: {
// title: 'example',
// icon: 'example'
// },
// children: [
// {
// path: '/example/table',
// component: _import('example/table/index'),
// redirect: '/example/table/complex-table',
// name: 'Table',
// meta: {
// title: 'Table',
// icon: 'table'
// },
// children: [
// { path: 'dynamic-table', component: _import('example/table/dynamicTable/index'), name: 'dynamicTable', meta: { title: 'dynamicTable' }},
// { path: 'drag-table', component: _import('example/table/dragTable'), name: 'dragTable', meta: { title: 'dragTable' }},
// { path: 'inline-edit-table', component: _import('example/table/inlineEditTable'), name: 'inlineEditTable', meta: { title: 'inlineEditTable' }},
// { path: 'complex-table', component: _import('example/table/complexTable'), name: 'complexTable', meta: { title: 'complexTable' }}
// ]
// },
// { path: 'tab/index', icon: 'tab', component: _import('example/tab/index'), name: 'tab', meta: { title: 'tab' }}
// ]
// },
//
// {
// path: '/form',
// component: Layout,
// redirect: 'noredirect',
// name: 'form',
// meta: {
// title: 'form',
// icon: 'form'
// },
// children: [
// { path: 'create-form', component: _import('form/create'), name: 'createForm', meta: { title: 'createForm', icon: 'table' }},
// { path: 'edit-form', component: _import('form/edit'), name: 'editForm', meta: { title: 'editForm', icon: 'table' }}
// ]
// },
//
// {
// path: '/error',
// component: Layout,
// redirect: 'noredirect',
// name: 'errorPages',
// meta: {
// title: 'errorPages',
// icon: '404'
// },
// children: [
// { path: '401', component: _import('errorPage/401'), name: 'page401', meta: { title: 'page401', noCache: true }},
// { path: '404', component: _import('errorPage/404'), name: 'page404', meta: { title: 'page404', noCache: true }}
// ]
// },
//
// {
// path: '/error-log',
// component: Layout,
// redirect: 'noredirect',
// children: [{ path: 'log', component: _import('errorLog/index'), name: 'errorLog', meta: { title: 'errorLog', icon: 'bug' }}]
// },
//
// {
// path: '/excel',
// component: Layout,
// redirect: '/excel/export-excel',
// name: 'excel',
// meta: {
// title: 'excel',
// icon: 'excel'
// },
// children: [
// { path: 'export-excel', component: _import('excel/exportExcel'), name: 'exportExcel', meta: { title: 'exportExcel' }},
// { path: 'export-selected-excel', component: _import('excel/selectExcel'), name: 'selectExcel', meta: { title: 'selectExcel' }},
// { path: 'upload-excel', component: _import('excel/uploadExcel'), name: 'uploadExcel', meta: { title: 'uploadExcel' }}
// ]
// },
//
// {
// path: '/zip',
// component: Layout,
// redirect: '/zip/download',
// children: [{ path: 'download', component: _import('zip/index'), name: 'exportZip', meta: { title: 'exportZip', icon: 'zip' }}]
// },
//
// {
// path: '/theme',
// component: Layout,
// redirect: 'noredirect',
// children: [{ path: 'index', component: _import('theme/index'), name: 'theme', meta: { title: 'theme', icon: 'theme' }}]
// },
//
// {
// path: '/clipboard',
// component: Layout,
// redirect: 'noredirect',
// children: [{ path: 'index', component: _import('clipboard/index'), name: 'clipboardDemo', meta: { title: 'clipboardDemo', icon: 'clipboard' }}]
// },
//
// {
// path: '/i18n',
// component: Layout,
// children: [{ path: 'index', component: _import('i18n-demo/index'), name: 'i18n', meta: { title: 'i18n', icon: 'international' }}]
// },
{ path: '*', redirect: '/404', hidden: true },
{
path: '/proxy',
@@ -1,24 +0,0 @@
<template>
<div class='chart-container'>
<chart height='100%' width='100%'></chart>
</div>
</template>
<script>
import Chart from '@/components/Charts/keyboard'
export default {
name: 'keyboardChart',
components: { Chart }
}
</script>
<style scoped>
.chart-container{
position: relative;
padding: 20px;
width: 100%;
height: 85vh;
}
</style>
@@ -1,24 +0,0 @@
<template>
<div class='chart-container'>
<chart height='100%' width='100%'></chart>
</div>
</template>
<script>
import Chart from '@/components/Charts/lineMarker'
export default {
name: 'lineChart',
components: { Chart }
}
</script>
<style scoped>
.chart-container{
position: relative;
padding:20px;
width: 100%;
height:85vh;
}
</style>
@@ -1,24 +0,0 @@
<template>
<div class='chart-container'>
<chart height='100%' width='100%'></chart>
</div>
</template>
<script>
import Chart from '@/components/Charts/mixChart'
export default {
name: 'mixChart',
components: { Chart }
}
</script>
<style scoped>
.chart-container{
position: relative;
padding: 20px;
width: 100%;
height:85vh;
}
</style>
@@ -1,45 +0,0 @@
<template>
<div class="app-container">
<el-tabs v-model="activeName">
<el-tab-pane label="use clipboard directly" name="directly">
<el-input v-model="inputData" placeholder="Please input" style='width:400px;'></el-input>
<el-button type="primary" icon="document" @click='handleCopy(inputData,$event)'>copy</el-button>
</el-tab-pane>
<el-tab-pane label="use clipboard by v-directive" name="v-directive">
<el-input v-model="inputData" placeholder="Please input" style='width:400px;'></el-input>
<el-button type="primary" icon="document" v-clipboard:copy='inputData' v-clipboard:success='clipboardSuccess'>copy</el-button>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import clip from '@/utils/clipboard' // use clipboard directly
import clipboard from '@/directive/clipboard/index.js' // use clipboard by v-directive
export default {
name: 'clipboardDemo',
directives: {
clipboard
},
data() {
return {
activeName: 'directly',
inputData: 'https://github.com/PanJiaChen/vue-element-admin'
}
},
methods: {
handleCopy(text, event) {
clip(text, event)
},
clipboardSuccess() {
this.$message({
message: '复制成功',
type: 'success',
duration: 1500
})
}
}
}
</script>
@@ -1,52 +0,0 @@
<template>
<div class="components-container">
<code>This is based on
<a class="link-type" href="//github.com/dai-siki/vue-image-crop-upload"> vue-image-crop-upload</a>.
{{$t('components.imageUploadTips')}}
</code>
<pan-thumb :image="image"></pan-thumb>
<el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">Change avatar
</el-button>
<image-cropper :width="300" :height="300" url="https://httpbin.org/post" @close='close' @crop-upload-success="cropSuccess" langType="en"
:key="imagecropperKey" v-show="imagecropperShow"></image-cropper>
</div>
</template>
<script>
import ImageCropper from '@/components/ImageCropper'
import PanThumb from '@/components/PanThumb'
export default {
name: 'avatarUpload-demo',
components: { ImageCropper, PanThumb },
data() {
return {
imagecropperShow: false,
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
}
}
}
</script>
<style scoped>
.avatar{
width: 200px;
height: 200px;
border-radius: 50%;
}
</style>
@@ -1,150 +0,0 @@
<template>
<div class="components-container">
<code>{{$t('components.backToTopTips1')}}</code>
<code>{{$t('components.backToTopTips2')}}</code>
<div class="placeholder-container">
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
</div>
<!--可自定义按钮的样式show/hide临界点返回的位置 -->
<!--如需文字提示可在外部添加element的<el-tooltip></el-tooltip>元素 -->
<el-tooltip placement="top" content="tooltip">
<back-to-top transitionName="fade" :customStyle="myBackToTopStyle" :visibilityHeight="300" :backPosition="50"></back-to-top>
</el-tooltip>
</div>
</template>
<script>
import BackToTop from '@/components/BackToTop'
export default {
name: 'backToTop-demo',
components: { BackToTop },
data() {
return {
myBackToTopStyle: {
right: '50px',
bottom: '50px',
width: '40px',
height: '40px',
'border-radius': '4px',
'line-height': '45px', // 请保持与高度一致以垂直居中 Please keep consistent with height to center vertically
background: '#e7eaf1'// 按钮的背景颜色 The background color of the button
}
}
}
}
</script>
<style scoped>
.placeholder-container div {
margin: 10px;
}
</style>
@@ -1,205 +0,0 @@
<template>
<div class="components-container">
<p class="warn-content">
<a href="https://github.com/PanJiaChen/vue-countTo" target="_blank">countTo-component</a>
</p>
<count-to ref="example" class="example" :start-val="_startVal" :end-val="_endVal" :duration="_duration" :decimals="_decimals"
:separator="_separator" :prefix="_prefix" :suffix="_suffix" :autoplay="false"></count-to>
<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="endValInput">endVal:
<input type="number" v-model.number="setEndVal" name="endVaInput" />
</label>
<label class="label" for="durationInput">duration:
<input type="number" v-model.number="setDuration" name="durationInput" />
</label>
<div class="startBtn example-btn" @click="start">开始</div>
<div class="pause-resume-btn example-btn" @click="pauseResume">暂停/恢复</div>
<br/>
<label class="label" for="decimalsInput">decimals:
<input type="number" v-model.number="setDecimals" name="decimalsInput" />
</label>
<label class="label" for="separatorInput">separator:
<input v-model="setSeparator" name="separatorInput" />
</label>
<label class="label" for="prefixInput">prefix:
<input v-model="setPrefix" name="prefixInput" />
</label>
<label class="label" for="suffixInput">suffix:
<input v-model="setSuffix" name="suffixInput" />
</label>
</div>
<code>&lt;count-to :start-val=&#x27;{{_startVal}}&#x27; :end-val=&#x27;{{_endVal}}&#x27; :duration=&#x27;{{_duration}}&#x27;
:decimals=&#x27;{{_decimals}}&#x27; :separator=&#x27;{{_separator}}&#x27; :prefix=&#x27;{{_prefix}}&#x27; :suffix=&#x27;{{_suffix}}&#x27;
:autoplay=false&gt;</code>
</div>
</template>
<script>
import countTo from 'vue-count-to'
export default {
name: 'countTo-demo',
components: { countTo },
data() {
return {
setStartVal: 0,
setEndVal: 2017,
setDuration: 4000,
setDecimals: 0,
setSeparator: ',',
setSuffix: ' rmb',
setPrefix: '¥ '
}
},
computed: {
_startVal() {
if (this.setStartVal) {
return this.setStartVal
} else {
return 0
}
},
_endVal() {
if (this.setEndVal) {
return this.setEndVal
} else {
return 0
}
},
_duration() {
if (this.setDuration) {
return this.setDuration
} else {
return 100
}
},
_decimals() {
if (this.setDecimals) {
if (this.setDecimals < 0 || this.setDecimals > 20) {
alert('digits argument must be between 0 and 20')
return 0
}
return this.setDecimals
} else {
return 0
}
},
_separator() {
return this.setSeparator
},
_suffix() {
return this.setSuffix
},
_prefix() {
return this.setPrefix
}
},
methods: {
start() {
this.$refs.example.start()
},
pauseResume() {
this.$refs.example.pauseResume()
}
}
}
</script>
<style scoped>
.example-btn {
display: inline-block;
margin-bottom: 0;
font-weight: 500;
text-align: center;
-ms-touch-action: manipulation;
touch-action: manipulation;
cursor: pointer;
background-image: none;
border: 1px solid transparent;
white-space: nowrap;
line-height: 1.5;
padding: 4px 15px;
font-size: 12px;
border-radius: 4px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1);
transition: all .3s cubic-bezier(.645, .045, .355, 1);
position: relative;
color: rgba(0, 0, 0, .65);
background-color: #fff;
border-color: #d9d9d9;
}
.example-btn:hover {
color: #4AB7BD;
background-color: #fff;
border-color: #4AB7BD;
}
.example {
font-size: 50px;
color: #F6416C;
display: block;
margin: 10px 0;
text-align: center;
font-size: 80px;
font-weight: 500;
}
.label {
color: #2f4f4f;
font-size: 16px;
display: inline-block;
margin: 15px 30px 15px 0;
}
input {
position: relative;
display: inline-block;
padding: 4px 7px;
width: 70px;
height: 28px;
cursor: text;
font-size: 12px;
line-height: 1.5;
color: rgba(0, 0, 0, .65);
background-color: #fff;
background-image: none;
border: 1px solid #d9d9d9;
border-radius: 4px;
-webkit-transition: all .3s;
transition: all .3s;
}
.startBtn {
margin-left: 20px;
font-size: 20px;
color: #30B08F;
background-color: #fff;
}
.startBtn:hover {
background-color: #30B08F;
color: #fff;
border-color: #30B08F;
}
.pause-resume-btn {
font-size: 20px;
color: #E65D6E;
background-color: #fff;
}
.pause-resume-btn:hover {
background-color: #E65D6E;
color: #fff;
border-color: #E65D6E;
}
</style>
@@ -1,40 +0,0 @@
<template>
<div class="components-container">
<code>drag-list base on
<a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a>
</code>
<div class="editor-container">
<dnd-list :list1="list1" :list2="list2" list1Title="List" list2Title="Article pool"></dnd-list>
</div>
</div>
</template>
<script>
import DndList from '@/components/DndList'
import { fetchList } from '@/api/article'
export default {
name: 'dndList-demo',
components: { DndList },
data() {
return {
list1: [],
list2: []
}
},
created() {
this.getData()
},
methods: {
getData() {
this.listLoading = true
fetchList().then(response => {
this.list1 = response.data.items.splice(0, 5)
this.list2 = response.data.items
})
}
}
}
</script>
@@ -1,32 +0,0 @@
<template>
<div class="components-container">
<code>
Based on <a class="link-type" href="https://github.com/rowanwins/vue-dropzone"> dropzone </a>.
{{$t('components.dropzoneTips')}}
</code>
<div class="editor-container">
<dropzone v-on:dropzone-removedFile="dropzoneR" v-on:dropzone-success="dropzoneS" id="myVueDropzone" url="https://httpbin.org/post"></dropzone>
</div>
</div>
</template>
<script>
import Dropzone from '@/components/Dropzone'
export default {
name: 'dropzone-demo',
components: { Dropzone },
methods: {
dropzoneS(file) {
console.log(file)
this.$message({ message: 'Upload success', type: 'success' })
},
dropzoneR(file) {
console.log(file)
this.$message({ message: 'Delete success', type: 'success' })
}
}
}
</script>
@@ -1,32 +0,0 @@
<template>
<div class="components-container">
<code>JsonEditor is base on <a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirrorr</a> , lint base on json-lint </code>
<div class="editor-container">
<json-editor ref="jsonEditor" v-model="value"></json-editor>
</div>
</div>
</template>
<script>
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":"能源化工"}]'
export default {
name: 'jsonEditor-demo',
components: { JsonEditor },
data() {
return {
value: JSON.parse(jsonData)
}
}
}
</script>
<style scoped>
.editor-container{
position: relative;
height: 100%;
}
</style>
@@ -1,49 +0,0 @@
<template>
<div class="components-container">
<code>Markdown is based on
<a href="https://github.com/sparksuite/simplemde-markdown-editor" target="_blank">simplemde-markdown-editor</a> Simply encapsulated in Vue.
<a target="_blank" href="https://segmentfault.com/a/1190000009762198#articleHeader14">
相关文章 </a>
</code>
<div class="editor-container">
<markdown-editor id="contentEditor" ref="contentEditor" v-model="content" :height="300" :zIndex="20"></markdown-editor>
</div>
<el-button @click="markdown2Html" style="margin-top:80px;" type="primary" icon="el-icon-document">To HTML</el-button>
<div v-html="html"></div>
</div>
</template>
<script>
import MarkdownEditor from '@/components/MarkdownEditor'
const content = `
**this is test**
* vue
* element
* webpack
## Simplemde
`
export default {
name: 'markdown-demo',
components: { MarkdownEditor },
data() {
return {
content: content,
html: ''
}
},
methods: {
markdown2Html() {
import('showdown').then(showdown => {
const converter = new showdown.Converter()
this.html = converter.makeHtml(this.content)
})
}
}
}
</script>
@@ -1,154 +0,0 @@
<template>
<div class="mixin-components-container">
<el-row>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Buttons</span>
</div>
<div style="margin-bottom:50px;">
<el-col :span="4" class="text-center">
<router-link class="pan-btn blue-btn" to="/components/index">Components</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn light-blue-btn" to="/charts/index">Charts</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn pink-btn" to="/excel/download">Excel</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn green-btn" to="/example/table/complex-table">Table</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn tiffany-btn" to="/form/edit-form">Form</router-link>
</el-col>
<el-col :span="4" class="text-center">
<router-link class="pan-btn yellow-btn" to="/theme/index">Theme</router-link>
</el-col>
</div>
</el-card>
</el-row>
<el-row :gutter="20" style="margin-top:50px;">
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Material Design 的input</span>
</div>
<div style="height:100px;">
<el-form :model="demo" :rules="demoRules">
<el-form-item prop="title">
<md-input icon="search" name="title" placeholder="输入标题" v-model="demo.title">标题</md-input>
</el-form-item>
</el-form>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>图片hover效果</span>
</div>
<div class="component-item">
<pan-thumb width="100px" height="100px" image="https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191">
vue-element-admin
</pan-thumb>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>水波纹 waves v-directive</span>
</div>
<div class="component-item">
<el-button v-waves type="primary">水波纹效果</el-button>
</div>
</el-card>
</el-col>
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>hover text</span>
</div>
<div class="component-item">
<mallki className="mallki-text" text="vue-element-admin"></mallki>
</div>
</el-card>
</el-col>
</el-row>
<el-row :gutter="20" style="margin-top:50px;">
<el-col :span="6">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>Share</span>
</div>
<div class="component-item" style="height:420px;">
<dropdown-menu style="margin:0 auto;" title='系列文章' :items='articleList'></dropdown-menu>
</div>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import PanThumb from '@/components/PanThumb'
import MdInput from '@/components/MDinput'
import Mallki from '@/components/TextHoverEffect/Mallki'
import DropdownMenu from '@/components/Share/dropdownMenu'
import waves from '@/directive/waves/index.js' // 水波纹指令
export default {
name: 'componentMixin-demo',
components: {
PanThumb,
MdInput,
Mallki,
DropdownMenu
},
directives: {
waves
},
data() {
const validate = (rule, value, callback) => {
if (value.length !== 6) {
callback(new Error('请输入六个字符'))
} else {
callback()
}
}
return {
demo: {
title: ''
},
demoRules: {
title: [{ required: true, trigger: 'change', validator: validate }]
},
articleList: [
{ title: '基础篇', href: 'https://segmentfault.com/a/1190000009275424' },
{ title: '登录权限篇', href: 'https://segmentfault.com/a/1190000009506097' },
{ title: '实战篇', href: 'https://segmentfault.com/a/1190000009762198' },
{ title: 'vueAdmin-template 篇', href: 'https://segmentfault.com/a/1190000010043013' },
{ title: '自行封装 component', href: 'https://segmentfault.com/a/1190000009090836' },
{ title: '优雅的使用 icon', href: 'https://segmentfault.com/a/https://segmentfault.com/a/1190000012213278' }
]
}
}
}
</script>
<style scoped>
.mixin-components-container {
background-color: #f0f2f5;
padding: 30px;
min-height: calc(100vh - 84px);
}
.component-item{
min-height: 100px;
}
</style>
@@ -1,67 +0,0 @@
<template>
<div class="components-container">
<code><strong>SplitPane</strong> If you've used
<a href="http://codepen.io/" target="_blank"> codepen</a>,
<a href="https://jsfiddle.net/" target="_blank"> jsfiddle </a>will not be unfamiliar.
<a href="https://github.com/PanJiaChen/vue-split-pane" target='_blank'> Github repository</a>
</code>
<split-pane v-on:resize="resize" split="vertical">
<template slot="paneL">
<div class="left-container"></div>
</template>
<template slot="paneR">
<split-pane split="horizontal">
<template slot="paneL">
<div class="top-container"></div>
</template>
<template slot="paneR">
<div class="bottom-container"></div>
</template>
</split-pane>
</template>
</split-pane>
</div>
</template>
<script>
import splitPane from 'vue-splitpane'
export default {
name: 'splitpane-demo',
components: { splitPane },
methods: {
resize() {
console.log('resize')
}
}
}
</script>
<style scoped>
.components-container {
position: relative;
height: 100vh;
}
.left-container {
background-color: #F38181;
height: 100%;
}
.right-container {
background-color: #FCE38A;
height: 200px;
}
.top-container {
background-color: #FCE38A;
width: 100%;
height: 100%;
}
.bottom-container {
width: 100%;
background-color: #95E1D3;
height: 100%;
}
</style>
@@ -1,130 +0,0 @@
<template>
<div>
<sticky className="sub-navbar">
<el-dropdown trigger="click">
<el-button plain>
Platform<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-border" slot="dropdown">
<el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
<el-checkbox v-for="item in platformsOptions" :label="item.key" :key="item.key">
{{item.name}}
</el-checkbox>
</el-checkbox-group>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown trigger="click">
<el-button plain>
Link<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding no-border" style="width:300px" slot="dropdown">
<el-input placeholder="Please enter the content" v-model="url">
<template slot="prepend">Url</template>
</el-input>
</el-dropdown-menu>
</el-dropdown>
<div class="time-container">
<el-date-picker v-model="time" type="datetime" :picker-options="pickerOptions" format="yyyy-MM-dd HH:mm:ss" placeholder="Release time">
</el-date-picker>
</div>
<el-button style="margin-left: 10px;" type="success">publish
</el-button>
</sticky>
<div class="components-container">
<code>Sticky header, {{$t('components.stickyTips')}}</code>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
<div>placeholder</div>
</div>
</div>
</template>
<script>
import Sticky from '@/components/Sticky'
export default {
name: 'sticky-demo',
components: { Sticky },
data() {
return {
time: '',
url: '',
platforms: ['a-platform'],
platformsOptions: [
{ key: 'a-platform', name: 'platformA' },
{ key: 'b-platform', name: 'platformB' },
{ key: 'c-platform', name: 'platformC' }
],
pickerOptions: {
disabledDate(time) {
return time.getTime() > Date.now()
}
}
}
}
}
</script>
<style scoped>
.components-container div {
margin: 10px;
}
.time-container {
display: inline-block;
}
</style>
@@ -1,41 +0,0 @@
<template>
<div class="components-container">
<code>
{{$t('components.tinymceTips')}}
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/#/rich-editor"> {{$t('components.documentation')}}</a>
</code>
<div>
<tinymce :height="300" v-model="content"></tinymce>
</div>
<div class="editor-content" v-html="content"></div>
</div>
</template>
<script>
import Tinymce from '@/components/Tinymce'
export default {
name: 'tinymce-demo',
components: { Tinymce },
data() {
return {
content:
`<h1 style="text-align: center;">Welcome to the TinyMCE demo!</h1>
<ul>
<li>Our <a href="//www.tinymce.com/docs/">documentation</a> is a great resource for learning how to configure TinyMCE.</li>
<li>Have a specific question? Visit the <a href="https://community.tinymce.com/forum/">Community Forum</a>.</li>
<li>We also offer enterprise grade support as part of <a href="https://tinymce.com/pricing">TinyMCE premium subscriptions</a>.</li>
</ul>
`
}
}
}
</script>
<style scoped>
.editor-content{
margin-top: 20px;
}
</style>
@@ -1,47 +0,0 @@
<template>
<div class="app-container documentation-container">
<a class="document-btn" target='_blank' href="https://panjiachen.github.io/vue-element-admin-site/#/">{{$t('documentation.documentation')}}</a>
<a class="document-btn" target='_blank' href="https://github.com/PanJiaChen/vue-element-admin/">{{$t('documentation.github')}}</a>
<dropdown-menu style="float:left;margin-left:50px;" title='系列文章' :items='articleList'></dropdown-menu>
</div>
</template>
<script>
import DropdownMenu from '@/components/Share/dropdownMenu'
export default {
name: 'documentation',
components: { DropdownMenu },
data() {
return {
articleList: [
{ title: '基础篇', href: 'https://segmentfault.com/a/1190000009275424' },
{ title: '登录权限篇', href: 'https://segmentfault.com/a/1190000009506097' },
{ title: '实战篇', href: 'https://segmentfault.com/a/1190000009762198' },
{ title: 'vueAdmin-template 篇', href: 'https://segmentfault.com/a/1190000010043013' },
{ title: '自行封装 component', href: 'https://segmentfault.com/a/1190000009090836' },
{ title: '优雅的使用 icon', href: 'https://segmentfault.com/a/https://segmentfault.com/a/1190000012213278' }
]
}
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.documentation-container {
margin: 50px;
.document-btn {
float: left;
margin-left: 50px;
vertical-align: middle;
display: block;
cursor: pointer;
background: black;
color: white;
height: 60px;
width: 200px;
line-height: 60px;
font-size: 20px;
text-align: center;
}
}
</style>
@@ -1,98 +0,0 @@
<template>
<el-table :data="list" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="65" v-loading="loading"
element-loading-text="请给我点时间">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="180px" align="center" label="Date">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column min-width="300px" label="Title">
<template slot-scope="scope">
<span>{{scope.row.title}}</span>
<el-tag>{{scope.row.type}}</el-tag>
</template>
</el-table-column>
<el-table-column width="110px" align="center" label="Author">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="120px" label="Importance">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column align="center" label="Readings" width="95">
<template slot-scope="scope">
<span>{{scope.row.pageviews}}</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
</el-table>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
props: {
type: {
type: String,
default: 'CN'
}
},
data() {
return {
list: null,
listQuery: {
page: 1,
limit: 5,
type: this.type,
sort: '+id'
},
loading: false
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.loading = true
this.$emit('create') // for test
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.loading = false
})
}
}
}
</script>
@@ -1,44 +0,0 @@
<template>
<div class="tab-container">
<el-tag>mounted times {{createdTimes}}</el-tag>
<el-tabs style='margin-top:15px;' v-model="activeName" type="border-card">
<el-tab-pane v-for="item in tabMapOptions" :label="item.label" :key='item.key' :name="item.key">
<keep-alive>
<tab-pane v-if='activeName==item.key' :type='item.key' @create='showCreatedTimes'></tab-pane>
</keep-alive>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import tabPane from './components/tabPane'
export default {
name: 'tab',
components: { tabPane },
data() {
return {
tabMapOptions: [
{ label: 'China', key: 'CN' },
{ label: 'USA', key: 'US' },
{ label: 'Japan', key: 'JP' },
{ label: 'Eurozone', key: 'EU' }
],
activeName: 'CN',
createdTimes: 0
}
},
methods: {
showCreatedTimes() {
this.createdTimes = this.createdTimes + 1
}
}
}
</script>
<style scoped>
.tab-container{
margin: 30px;
}
</style>
@@ -1,354 +0,0 @@
<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" :placeholder="$t('table.title')" v-model="listQuery.title">
</el-input>
<el-select clearable style="width: 90px" class="filter-item" v-model="listQuery.importance" :placeholder="$t('table.importance')">
<el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item">
</el-option>
</el-select>
<el-select clearable class="filter-item" style="width: 130px" v-model="listQuery.type" :placeholder="$t('table.type')">
<el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key">
</el-option>
</el-select>
<el-select @change='handleFilter' style="width: 140px" class="filter-item" v-model="listQuery.sort">
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key">
</el-option>
</el-select>
<el-button class="filter-item" type="primary" v-waves icon="el-icon-search" @click="handleFilter">{{$t('table.search')}}</el-button>
<el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="el-icon-edit">{{$t('table.add')}}</el-button>
<el-button class="filter-item" type="primary" :loading="downloadLoading" v-waves icon="el-icon-download" @click="handleDownload">{{$t('table.export')}}</el-button>
<el-checkbox class="filter-item" style='margin-left:15px;' @change='tableKey=tableKey+1' v-model="showReviewer">{{$t('table.reviewer')}}</el-checkbox>
</div>
<el-table :key='tableKey' :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row
style="width: 100%">
<el-table-column align="center" :label="$t('table.id')" width="65">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="150px" align="center" :label="$t('table.date')">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column min-width="150px" :label="$t('table.title')">
<template slot-scope="scope">
<span class="link-type" @click="handleUpdate(scope.row)">{{scope.row.title}}</span>
<el-tag>{{scope.row.type | typeFilter}}</el-tag>
</template>
</el-table-column>
<el-table-column width="110px" align="center" :label="$t('table.author')">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="110px" v-if='showReviewer' align="center" :label="$t('table.reviewer')">
<template slot-scope="scope">
<span style='color:red;'>{{scope.row.reviewer}}</span>
</template>
</el-table-column>
<el-table-column width="80px" :label="$t('table.importance')">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" class="meta-item__icon" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.readings')" width="95">
<template slot-scope="scope">
<span v-if="scope.row.pageviews" class="link-type" @click='handleFetchPv(scope.row.pageviews)'>{{scope.row.pageviews}}</span>
<span v-else>0</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" :label="$t('table.status')" width="100">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" :label="$t('table.actions')" width="230" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button type="primary" size="mini" @click="handleUpdate(scope.row)">{{$t('table.edit')}}</el-button>
<el-button v-if="scope.row.status!='published'" size="mini" type="success" @click="handleModifyStatus(scope.row,'published')">{{$t('table.publish')}}
</el-button>
<el-button v-if="scope.row.status!='draft'" size="mini" @click="handleModifyStatus(scope.row,'draft')">{{$t('table.draft')}}
</el-button>
<el-button v-if="scope.row.status!='deleted'" size="mini" type="danger" @click="handleModifyStatus(scope.row,'deleted')">{{$t('table.delete')}}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination-container">
<el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="listQuery.page"
:page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :rules="rules" ref="dataForm" :model="temp" label-position="left" label-width="70px" style='width: 400px; margin-left:50px;'>
<el-form-item :label="$t('table.type')" prop="type">
<el-select class="filter-item" v-model="temp.type" placeholder="Please select">
<el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('table.date')" prop="timestamp">
<el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date">
</el-date-picker>
</el-form-item>
<el-form-item :label="$t('table.title')" prop="title">
<el-input v-model="temp.title"></el-input>
</el-form-item>
<el-form-item :label="$t('table.status')">
<el-select class="filter-item" v-model="temp.status" placeholder="Please select">
<el-option v-for="item in statusOptions" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('table.importance')">
<el-rate style="margin-top:8px;" v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max='3'></el-rate>
</el-form-item>
<el-form-item :label="$t('table.remark')">
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4}" placeholder="Please input" v-model="temp.remark">
</el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">{{$t('table.cancel')}}</el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="createData">{{$t('table.confirm')}}</el-button>
<el-button v-else type="primary" @click="updateData">{{$t('table.confirm')}}</el-button>
</div>
</el-dialog>
<el-dialog title="Reading statistics" :visible.sync="dialogPvVisible">
<el-table :data="pvData" border fit highlight-current-row style="width: 100%">
<el-table-column prop="key" label="Channel"> </el-table-column>
<el-table-column prop="pv" label="Pv"> </el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogPvVisible = false">{{$t('table.confirm')}}</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
import waves from '@/directive/waves' // 水波纹指令
import { parseTime } from '@/utils'
const calendarTypeOptions = [
{ key: 'CN', display_name: 'China' },
{ key: 'US', display_name: 'USA' },
{ key: 'JP', display_name: 'Japan' },
{ key: 'EU', display_name: 'Eurozone' }
]
// arr to obj ,such as { CN : "China", US : "USA" }
const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
acc[cur.key] = cur.display_name
return acc
}, {})
export default {
name: 'complexTable',
directives: {
waves
},
data() {
return {
tableKey: 0,
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 20,
importance: undefined,
title: undefined,
type: undefined,
sort: '+id'
},
importanceOptions: [1, 2, 3],
calendarTypeOptions,
sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
statusOptions: ['published', 'draft', 'deleted'],
showReviewer: false,
temp: {
id: undefined,
importance: 1,
remark: '',
timestamp: new Date(),
title: '',
type: '',
status: 'published'
},
dialogFormVisible: false,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create'
},
dialogPvVisible: false,
pvData: [],
rules: {
type: [{ required: true, message: 'type is required', trigger: 'change' }],
timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
title: [{ required: true, message: 'title is required', trigger: 'blur' }]
},
downloadLoading: false
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
},
typeFilter(type) {
return calendarTypeKeyValue[type]
}
},
created() {
this.getList()
},
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.listQuery.page = 1
this.getList()
},
handleSizeChange(val) {
this.listQuery.limit = val
this.getList()
},
handleCurrentChange(val) {
this.listQuery.page = val
this.getList()
},
handleModifyStatus(row, status) {
this.$message({
message: '操作成功',
type: 'success'
})
row.status = status
},
resetTemp() {
this.temp = {
id: undefined,
importance: 1,
remark: '',
timestamp: new Date(),
title: '',
status: 'published',
type: ''
}
},
handleCreate() {
this.resetTemp()
this.dialogStatus = 'create'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
createData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
this.temp.author = 'vue-element-admin'
createArticle(this.temp).then(() => {
this.list.unshift(this.temp)
this.dialogFormVisible = false
this.$notify({
title: '成功',
message: '创建成功',
type: 'success',
duration: 2000
})
})
}
})
},
handleUpdate(row) {
this.temp = Object.assign({}, row) // copy obj
this.temp.timestamp = new Date(this.temp.timestamp)
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
updateData() {
this.$refs['dataForm'].validate((valid) => {
if (valid) {
const tempData = Object.assign({}, this.temp)
tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
updateArticle(tempData).then(() => {
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
})
})
}
})
},
handleDelete(row) {
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
})
const index = this.list.indexOf(row)
this.list.splice(index, 1)
},
handleFetchPv(pv) {
fetchPv(pv).then(response => {
this.pvData = response.data.pvData
this.dialogPvVisible = true
})
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
const data = this.formatJson(filterVal, this.list)
excel.export_json_to_excel(tHeader, data, 'table-list')
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
}
}
}
</script>
@@ -1,147 +0,0 @@
<template>
<div class="app-container calendar-list-container">
<!-- Note that row-key is necessary to get a correct row order. -->
<el-table :data="list" row-key="id" v-loading.body="listLoading" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="65">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="180px" align="center" label="Date">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column min-width="300px" label="Title">
<template slot-scope="scope">
<span>{{scope.row.title}}</span>
</template>
</el-table-column>
<el-table-column width="110px" align="center" label="Author">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="100px" label="Importance">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" class="icon-star" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column align="center" label="Readings" width="95">
<template slot-scope="scope">
<span>{{scope.row.pageviews}}</span>
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" label="Drag" width="80">
<template slot-scope="scope">
<svg-icon class='drag-handler' icon-class="drag"></svg-icon>
</template>
</el-table-column>
</el-table>
<!-- $t is vue-i18n global function to translate lang (lang in @/lang) -->
<div class='show-d'>{{$t('table.dragTips1')}} : &nbsp; {{ oldList}}</div>
<div class='show-d'>{{$t('table.dragTips2')}} : {{newList}}</div>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
import Sortable from 'sortablejs'
export default {
name: 'dragTable',
data() {
return {
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 10
},
sortable: null,
oldList: [],
newList: []
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.total = response.data.total
this.listLoading = false
this.oldList = this.list.map(v => v.id)
this.newList = this.oldList.slice()
this.$nextTick(() => {
this.setSort()
})
})
},
setSort() {
const el = document.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
this.sortable = Sortable.create(el, {
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
onEnd: evt => {
const targetRow = this.list.splice(evt.oldIndex, 1)[0]
this.list.splice(evt.newIndex, 0, targetRow)
// for show the changes, you can delete in you code
const tempIndex = this.newList.splice(evt.oldIndex, 1)[0]
this.newList.splice(evt.newIndex, 0, tempIndex)
}
})
}
}
}
</script>
<style>
.sortable-ghost{
opacity: .8;
color: #fff!important;
background: #42b983!important;
}
</style>
<style scoped>
.icon-star{
margin-right:2px;
}
.drag-handler{
width: 20px;
height: 20px;
cursor: pointer;
}
.show-d{
margin-top: 15px;
}
</style>
@@ -1,58 +0,0 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-checkbox-group v-model="checkboxVal">
<el-checkbox label="apple">apple</el-checkbox>
<el-checkbox label="banana">banana</el-checkbox>
<el-checkbox label="orange">orange</el-checkbox>
</el-checkbox-group>
</div>
<el-table :data="tableData" :key='key' border fit highlight-current-row style="width: 100%">
<el-table-column prop="name" label="fruitName" width="180"></el-table-column>
<el-table-column :key='fruit' v-for='fruit in formThead' :label="fruit">
<template slot-scope="scope">
{{scope.row[fruit]}}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
const defaultFormThead = ['apple', 'banana']
export default {
data() {
return {
tableData: [
{
name: 'fruit-1',
apple: 'apple-10',
banana: 'banana-10',
orange: 'orange-10'
},
{
name: 'fruit-2',
apple: 'apple-20',
banana: 'banana-20',
orange: 'orange-20'
}
],
key: 1, // table key
formTheadOptions: ['apple', 'banana', 'orange'],
checkboxVal: defaultFormThead, // checkboxVal
formThead: defaultFormThead // 默认表头 Default header
}
},
watch: {
checkboxVal(valArr) {
this.formThead = this.formTheadOptions.filter(i => valArr.indexOf(i) >= 0)
this.key = this.key + 1// 为了保证table 每次都会重渲 In order to ensure the table will be re-rendered each time
}
}
}
</script>
@@ -1,20 +0,0 @@
<template>
<div class="app-container">
<div style='margin:0 0 5px 20px'>{{$t('table.dynamicTips1')}}</div>
<fixed-thead></fixed-thead>
<div style='margin:30px 0 5px 20px'>{{$t('table.dynamicTips2')}}</div>
<unfixed-thead></unfixed-thead>
</div>
</template>
<script>
import fixedThead from './fixedThead'
import unfixedThead from './unfixedThead'
export default {
name: 'dynamicTable',
components: { fixedThead, unfixedThead }
}
</script>
@@ -1,47 +0,0 @@
<template>
<div class="app-container">
<div class="filter-container">
<el-checkbox-group v-model="formThead">
<el-checkbox label="apple">apple</el-checkbox>
<el-checkbox label="banana">banana</el-checkbox>
<el-checkbox label="orange">orange</el-checkbox>
</el-checkbox-group>
</div>
<el-table :data="tableData" border fit highlight-current-row style="width: 100%">
<el-table-column prop="name" label="fruitName" width="180">
</el-table-column>
<el-table-column :key='fruit' v-for='fruit in formThead' :label="fruit">
<template slot-scope="scope">
{{scope.row[fruit]}}
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
export default {
data() {
return {
tableData: [
{
name: 'fruit-1',
apple: 'apple-10',
banana: 'banana-10',
orange: 'orange-10'
},
{
name: 'fruit-2',
apple: 'apple-20',
banana: 'banana-20',
orange: 'orange-20'
}
],
formThead: ['apple', 'banana']
}
}
}
</script>
@@ -1,18 +0,0 @@
<template>
<transition name="fade" mode="out-in">
<keep-alive :include='cachedViews'>
<router-view></router-view>
</keep-alive>
</transition>
</template>
<script>
export default {
name: 'TableMain',
computed: {
cachedViews() {
return this.$store.state.tagsView.cachedViews
}
}
}
</script>
@@ -1,129 +0,0 @@
<template>
<div class="app-container calendar-list-container">
<el-table :data="list" v-loading.body="listLoading" border fit highlight-current-row style="width: 100%">
<el-table-column align="center" label="ID" width="80">
<template slot-scope="scope">
<span>{{scope.row.id}}</span>
</template>
</el-table-column>
<el-table-column width="180px" align="center" label="Date">
<template slot-scope="scope">
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column width="120px" align="center" label="Author">
<template slot-scope="scope">
<span>{{scope.row.author}}</span>
</template>
</el-table-column>
<el-table-column width="100px" label="Importance">
<template slot-scope="scope">
<svg-icon v-for="n in +scope.row.importance" icon-class="star" class="meta-item__icon" :key="n"></svg-icon>
</template>
</el-table-column>
<el-table-column class-name="status-col" label="Status" width="110">
<template slot-scope="scope">
<el-tag :type="scope.row.status | statusFilter">{{scope.row.status}}</el-tag>
</template>
</el-table-column>
<el-table-column min-width="300px" label="Title">
<template slot-scope="scope">
<template v-if="scope.row.edit">
<el-input class="edit-input" size="small" v-model="scope.row.title"></el-input>
<el-button class='cancel-btn' size="small" icon="el-icon-refresh" type="warning" @click="cancelEdit(scope.row)">cancel</el-button>
</template>
<span v-else>{{ scope.row.title }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="Actions" width="120">
<template slot-scope="scope">
<el-button v-if="scope.row.edit" type="success" @click="confirmEdit(scope.row)" size="small" icon="el-icon-circle-check-outline">Ok</el-button>
<el-button v-else type="primary" @click='scope.row.edit=!scope.row.edit' size="small" icon="el-icon-edit">Edit</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
name: 'inlineEditTable',
data() {
return {
list: null,
listLoading: true,
listQuery: {
page: 1,
limit: 10
}
}
},
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
},
created() {
this.getList()
},
methods: {
getList() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
const items = response.data.items
this.list = items.map(v => {
this.$set(v, 'edit', false) // https://vuejs.org/v2/guide/reactivity.html
v.originalTitle = v.title // will be used when user click the cancel botton
return v
})
this.listLoading = false
})
},
cancelEdit(row) {
row.title = row.originalTitle
row.edit = false
this.$message({
message: 'The title has been restored to the original value',
type: 'warning'
})
},
confirmEdit(row) {
row.edit = false
row.originalTitle = row.title
this.$message({
message: 'The title has been edited',
type: 'success'
})
}
}
}
</script>
<style scoped>
.edit-input {
padding-right: 100px;
}
.cancel-btn {
position: absolute;
right: 15px;
top: 10px;
}
</style>
@@ -1,84 +0,0 @@
<template>
<!-- $t is vue-i18n global function to translate lang -->
<div class="app-container">
<el-input style='width:340px;' :placeholder="$t('excel.placeholder')" prefix-icon="el-icon-document" v-model="filename"></el-input>
<el-button style='margin-bottom:20px;' type="primary" icon="document" @click="handleDownload" :loading="downloadLoading">{{$t('excel.export')}} excel</el-button>
<el-table :data="list" v-loading.body="listLoading" element-loading-text="拼命加载中" border fit highlight-current-row>
<el-table-column align="center" label='Id' width="95">
<template slot-scope="scope">
{{scope.$index}}
</template>
</el-table-column>
<el-table-column label="Title">
<template slot-scope="scope">
{{scope.row.title}}
</template>
</el-table-column>
<el-table-column label="Author" width="110" align="center">
<template slot-scope="scope">
<el-tag>{{scope.row.author}}</el-tag>
</template>
</el-table-column>
<el-table-column label="Readings" width="115" align="center">
<template slot-scope="scope">
{{scope.row.pageviews}}
</template>
</el-table-column>
<el-table-column align="center" label="Date" width="220">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span>{{scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
import { parseTime } from '@/utils'
export default {
name: 'exportExcel',
data() {
return {
list: null,
listLoading: true,
downloadLoading: false,
filename: ''
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.listLoading = true
fetchList().then(response => {
this.list = response.data.items
this.listLoading = false
})
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.list
const data = this.formatJson(filterVal, list)
excel.export_json_to_excel(tHeader, data, this.filename)
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
}
}
}
</script>
@@ -1,91 +0,0 @@
<template>
<div class="app-container">
<!-- $t is vue-i18n global function to translate lang -->
<el-input style='width:340px;' :placeholder="$t('excel.placeholder')" prefix-icon="el-icon-document" v-model="filename"></el-input>
<el-button style='margin-bottom:20px' type="primary" icon="document" @click="handleDownload" :loading="downloadLoading">{{$t('excel.selectedExport')}}</el-button>
<el-table :data="list" v-loading.body="listLoading" element-loading-text="拼命加载中" border fit highlight-current-row @selection-change="handleSelectionChange"
ref="multipleTable">
<el-table-column type="selection" align="center"></el-table-column>
<el-table-column align="center" label='Id' width="95">
<template slot-scope="scope">
{{scope.$index}}
</template>
</el-table-column>
<el-table-column label="Title">
<template slot-scope="scope">
{{scope.row.title}}
</template>
</el-table-column>
<el-table-column label="Author" width="110" align="center">
<template slot-scope="scope">
<el-tag>{{scope.row.author}}</el-tag>
</template>
</el-table-column>
<el-table-column label="Readings" width="115" align="center">
<template slot-scope="scope">
{{scope.row.pageviews}}
</template>
</el-table-column>
<el-table-column align="center" label="PDate" width="220">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span>{{scope.row.display_time}}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
name: 'selectExcel',
data() {
return {
list: null,
listLoading: true,
multipleSelection: [],
downloadLoading: false,
filename: ''
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.listLoading = true
fetchList(this.listQuery).then(response => {
this.list = response.data.items
this.listLoading = false
})
},
handleSelectionChange(val) {
this.multipleSelection = val
},
handleDownload() {
if (this.multipleSelection.length) {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.multipleSelection
const data = this.formatJson(filterVal, list)
excel.export_json_to_excel(tHeader, data, this.filename)
this.$refs.multipleTable.clearSelection()
this.downloadLoading = false
})
} else {
this.$message({
message: 'Please select at least one item',
type: 'warning'
})
}
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]))
}
}
}
</script>
@@ -1,30 +0,0 @@
<template>
<div class="app-container">
<upload-excel-component @on-selected-file='selected'></upload-excel-component>
<el-table :data="tableData" border highlight-current-row style="width: 100%;margin-top:20px;">
<el-table-column v-for='item of tableHeader' :prop="item" :label="item" :key='item'>
</el-table-column>
</el-table>
</div>
</template>
<script>
import UploadExcelComponent from '@/components/UploadExcel/index.vue'
export default {
name: 'uploadExcel',
components: { UploadExcelComponent },
data() {
return {
tableData: [],
tableHeader: []
}
},
methods: {
selected(data) {
this.tableData = data.results
this.tableHeader = data.header
}
}
}
</script>
@@ -1,314 +0,0 @@
<template>
<div class="createPost-container">
<el-form class="form-container" :model="postForm" :rules="rules" ref="postForm">
<sticky :className="'sub-navbar '+postForm.status">
<template v-if="fetchSuccess">
<router-link style="margin-right:15px;" v-show='isEdit' :to="{ path:'create-form'}">
<el-button type="info">创建form</el-button>
</router-link>
<el-dropdown trigger="click">
<el-button plain>{{!postForm.comment_disabled?'评论已打开':'评论已关闭'}}
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding" slot="dropdown">
<el-dropdown-item>
<el-radio-group style="padding: 10px;" v-model="postForm.comment_disabled">
<el-radio :label="true">关闭评论</el-radio>
<el-radio :label="false">打开评论</el-radio>
</el-radio-group>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown trigger="click">
<el-button plain>平台
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-border" slot="dropdown">
<el-checkbox-group v-model="postForm.platforms" style="padding: 5px 15px;">
<el-checkbox v-for="item in platformsOptions" :label="item.key" :key="item.key">
{{item.name}}
</el-checkbox>
</el-checkbox-group>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown trigger="click">
<el-button plain>
外链
<i class="el-icon-caret-bottom el-icon--right"></i>
</el-button>
<el-dropdown-menu class="no-padding no-border" style="width:300px" slot="dropdown">
<el-form-item label-width="0px" style="margin-bottom: 0px" prop="source_uri">
<el-input placeholder="请输入内容" v-model="postForm.source_uri">
<template slot="prepend">填写url</template>
</el-input>
</el-form-item>
</el-dropdown-menu>
</el-dropdown>
<el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm()">发布
</el-button>
<el-button v-loading="loading" type="warning" @click="draftForm">草稿</el-button>
</template>
<template v-else>
<el-tag>发送异常错误,刷新页面,或者联系程序员</el-tag>
</template>
</sticky>
<div class="createPost-main-container">
<el-row>
<el-col :span="21">
<el-form-item style="margin-bottom: 40px;" prop="title">
<MDinput name="name" v-model="postForm.title" required :maxlength="100">
标题
</MDinput>
<span v-show="postForm.title.length>=26" class='title-prompt'>app可能会显示不全</span>
</el-form-item>
<div class="postInfo-container">
<el-row>
<el-col :span="8">
<el-form-item label-width="45px" label="作者:" class="postInfo-container-item">
<multiselect v-model="postForm.author" :options="userLIstOptions" @search-change="getRemoteUserList" placeholder="搜索用户" selectLabel="选择"
deselectLabel="删除" track-by="key" :internalSearch="false" label="key">
<span slot='noResult'>无结果</span>
</multiselect>
</el-form-item>
</el-col>
<el-col :span="8">
<el-tooltip class="item" effect="dark" content="将替换作者" placement="top">
<el-form-item label-width="50px" label="来源:" class="postInfo-container-item">
<el-input placeholder="将替换作者" style='min-width:150px;' v-model="postForm.source_name">
</el-input>
</el-form-item>
</el-tooltip>
</el-col>
<el-col :span="8">
<el-form-item label-width="80px" label="发布时间:" class="postInfo-container-item">
<el-date-picker v-model="postForm.display_time" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="选择日期时间">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</div>
</el-col>
</el-row>
<el-form-item style="margin-bottom: 40px;" label-width="45px" label="摘要:">
<el-input type="textarea" class="article-textarea" :rows="1" autosize placeholder="请输入内容" v-model="postForm.content_short">
</el-input>
<span class="word-counter" v-show="contentShortLength">{{contentShortLength}}</span>
</el-form-item>
<div class="editor-container">
<tinymce :height=400 ref="editor" v-model="postForm.content"></tinymce>
</div>
<div style="margin-bottom: 20px;">
<Upload v-model="postForm.image_uri"></Upload>
</div>
</div>
</el-form>
</div>
</template>
<script>
import Tinymce from '@/components/Tinymce'
import Upload from '@/components/Upload/singleImage3'
import MDinput from '@/components/MDinput'
import Multiselect from 'vue-multiselect'// 使用的一个多选框组件,element-ui的select不能满足所有需求
import 'vue-multiselect/dist/vue-multiselect.min.css'// 多选框组件css
import Sticky from '@/components/Sticky' // 粘性header组件
import { validateURL } from '@/utils/validate'
import { fetchArticle } from '@/api/article'
import { userSearch } from '@/api/remoteSearch'
const defaultForm = {
status: 'draft',
title: '', // 文章题目
content: '', // 文章内容
content_short: '', // 文章摘要
source_uri: '', // 文章外链
image_uri: '', // 文章图片
source_name: '', // 文章外部作者
display_time: undefined, // 前台展示时间
id: undefined,
platforms: ['a-platform'],
comment_disabled: false
}
export default {
name: 'articleDetail',
components: { Tinymce, MDinput, Upload, Multiselect, Sticky },
props: {
isEdit: {
type: Boolean,
default: false
}
},
data() {
const validateRequire = (rule, value, callback) => {
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({
message: '外链url填写不正确',
type: 'error'
})
callback(null)
}
} else {
callback()
}
}
return {
postForm: Object.assign({}, defaultForm),
fetchSuccess: true,
loading: false,
userLIstOptions: [],
platformsOptions: [
{ key: 'a-platform', name: 'a-platform' },
{ key: 'b-platform', name: 'b-platform' },
{ key: 'c-platform', name: 'c-platform' }
],
rules: {
image_uri: [{ validator: validateRequire }],
title: [{ validator: validateRequire }],
content: [{ validator: validateRequire }],
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
}
}
},
computed: {
contentShortLength() {
return this.postForm.content_short.length
}
},
created() {
if (this.isEdit) {
this.fetchData()
} else {
this.postForm = Object.assign({}, defaultForm)
}
},
methods: {
fetchData() {
fetchArticle().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>
<style rel="stylesheet/scss" lang="scss" scoped>
@import "src/styles/mixin.scss";
.title-prompt{
position: absolute;
right: 0px;
font-size: 12px;
top:10px;
color:#ff4949;
}
.createPost-container {
position: relative;
.createPost-main-container {
padding: 40px 45px 20px 50px;
.postInfo-container {
position: relative;
@include clearfix;
margin-bottom: 10px;
.postInfo-container-item {
float: left;
}
}
.editor-container {
min-height: 500px;
margin: 0 0 30px;
.editor-upload-btn-container {
text-align: right;
margin-right: 10px;
.editor-upload-btn {
display: inline-block;
}
}
}
}
.word-counter {
width: 40px;
position: absolute;
right: -10px;
top: 0px;
}
}
</style>
@@ -1,13 +0,0 @@
<template>
<article-detail :is-edit='false'></article-detail>
</template>
<script>
import ArticleDetail from './components/ArticleDetail'
export default {
name: 'createForm',
components: { ArticleDetail }
}
</script>
@@ -1,13 +0,0 @@
<template>
<article-detail :is-edit='true'></article-detail>
</template>
<script>
import ArticleDetail from './components/ArticleDetail'
export default {
name: 'editForm',
components: { ArticleDetail }
}
</script>
@@ -1,111 +0,0 @@
<template>
<div>
<el-card class="box-card" style="margin-top:40px;">
<div slot="header" class="clearfix">
<svg-icon icon-class="international" />
<span style='margin-left:10px;'>{{$t('i18nView.title')}}</span>
</div>
<div>
<el-radio-group v-model="lang" size="small">
<el-radio label="zh" border>简体中文</el-radio>
<el-radio label="en" border>English</el-radio>
</el-radio-group>
<el-tag style='margin-top:15px;display:block;' type="info">{{$t('i18nView.note')}}</el-tag>
</div>
</el-card>
<el-row :gutter="20" style="margin:100px 15px 50px;">
<el-col :span="12">
<div class="block">
<el-date-picker v-model="date" type="date" :placeholder="$t('i18nView.datePlaceholder')"></el-date-picker>
</div>
<div class="block">
<el-pagination background :current-page="currentPage" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next"
:total="400">
</el-pagination>
</div>
<div class="block">
<el-button class="item-btn" size="small">{{$t('i18nView.default')}}</el-button>
<el-button class="item-btn" size="small" type="primary">{{$t('i18nView.primary')}}</el-button>
<el-button class="item-btn" size="small" type="success">{{$t('i18nView.success')}}</el-button>
<el-button class="item-btn" size="small" type="info">{{$t('i18nView.info')}}</el-button>
<el-button class="item-btn" size="small" type="warning">{{$t('i18nView.warning')}}</el-button>
<el-button class="item-btn" size="small" type="danger">{{$t('i18nView.danger')}}</el-button>
</div>
</el-col>
<el-col :span="12">
<el-table :data="tableData" fit highlight-current-row border style="width: 100%">
<el-table-column prop="name" :label="$t('i18nView.tableName')" width="100" align="center"></el-table-column>
<el-table-column prop="date" :label="$t('i18nView.tableDate')" width="120" align="center"></el-table-column>
<el-table-column prop="address" :label="$t('i18nView.tableAddress')"></el-table-column>
</el-table>
</el-col>
</el-row>
</div>
</template>
<script>
import local from './local'
const viewName = 'i18nView'
export default {
name: 'i18n',
data() {
return {
date: '',
currentPage: 5,
tableData: [{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}]
}
},
created() {
if (!this.$i18n.getLocaleMessage('en')[viewName]) {
this.$i18n.mergeLocaleMessage('en', local.en)
this.$i18n.mergeLocaleMessage('zh', local.zh)
}
},
computed: {
lang: {
get() {
return this.$store.state.app.language
},
set(lang) {
this.$i18n.locale = lang
this.$store.dispatch('setLanguage', lang)
}
}
}
}
</script>
<style scoped>
.box-card {
width: 600px;
margin: 20px auto;
}
.item-btn{
margin-bottom: 15px;
margin-left: 0px;
}
.block {
padding: 25px;
}
</style>
@@ -1,36 +0,0 @@
export default {
zh: {
i18nView: {
title: '切换语言',
note: '目前只翻译了当前页面和侧边栏和导航,未完待续,敬请期待...',
datePlaceholder: '请选择日期',
tableDate: '日期',
tableName: '姓名',
tableAddress: '地址',
default: '默认按钮',
primary: '主要按钮',
success: '成功按钮',
info: '信息按钮',
warning: '警告按钮',
danger: '危险按钮'
}
},
en: {
i18nView: {
title: 'Switch Language',
note: 'Currently only translated the i18n page and the sidebar and levelbar, please look forword to...',
datePlaceholder: 'Pick a day',
tableDate: 'tableDate',
tableName: 'tableName',
tableAddress: 'tableAddress',
default: 'default:',
primary: 'primary',
success: 'success',
info: 'info',
warning: 'warning',
danger: 'danger'
}
}
}
@@ -1,40 +0,0 @@
<template>
<el-upload action="https://upload.qbox.me" :data="dataObj" drag :multiple="true" :before-upload="beforeUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
</el-upload>
</template>
<script>
import { getToken } from '@/api/qiniu'
// 获取七牛token 后端通过Access Key,Secret Key,bucket等生成token
// 七牛官方sdk https://developer.qiniu.com/sdk#official-sdk
export default{
data() {
return {
dataObj: { token: '', key: '' },
image_uri: [],
fileList: []
}
},
methods: {
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
resolve(true)
}).catch(err => {
console.log(err)
reject(false)
})
})
}
}
}
</script>
@@ -1,77 +0,0 @@
<template>
<div class="app-container">
<!-- $t is vue-i18n global function to translate lang -->
<el-input style='width:300px;' :placeholder="$t('zip.placeholder')" prefix-icon="el-icon-document" v-model="filename"></el-input>
<el-button style='margin-bottom:20px;' type="primary" icon="document" @click="handleDownload" :loading="downloadLoading">{{$t('zip.export')}} zip</el-button>
<el-table :data="list" v-loading.body="listLoading" element-loading-text="拼命加载中" border fit highlight-current-row>
<el-table-column align="center" label='ID' width="95">
<template slot-scope="scope">
{{scope.$index}}
</template>
</el-table-column>
<el-table-column label="Title">
<template slot-scope="scope">
{{scope.row.title}}
</template>
</el-table-column>
<el-table-column label="Author" width="95" align="center">
<template slot-scope="scope">
<el-tag>{{scope.row.author}}</el-tag>
</template>
</el-table-column>
<el-table-column label="Readings" width="115" align="center">
<template slot-scope="scope">
{{scope.row.pageviews}}
</template>
</el-table-column>
<el-table-column align="center" label="Date" width="220">
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span>{{scope.row.display_time}}</span>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { fetchList } from '@/api/article'
export default {
name: 'exportZip',
data() {
return {
list: null,
listLoading: true,
downloadLoading: false,
filename: ''
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.listLoading = true
fetchList().then(response => {
this.list = response.data.items
this.listLoading = false
})
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Zip').then(zip => {
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.list
const data = this.formatJson(filterVal, list)
zip.export_txt_to_zip(tHeader, data, this.filename, this.filename)
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]))
}
}
}
</script>
@@ -42,4 +42,14 @@ public interface DataCleanMapper extends SqlMapper {
@Delete("delete from `client_connect_record` where create_time < ?")
void cleanClientConnectRecord(long date);
@Delete("delete from `flow_report_minute` where create_time < ?")
void cleanFlowMinuteReport(long date);
@Delete("delete from `flow_report_hour` where create_time < ?")
void cleanFlowHourReport(long date);
@Delete("delete from `flow_report_day` where create_time < ?")
void cleanFlowDayReport(long date);
}
@@ -64,6 +64,19 @@ public class DataCleanJob implements IJobHandler {
*/
private static final Integer CLIENT_CONNECT_RECORD_KEEP_DAYS = 30;
/**
* 流量统计分钟报表记录保留天数
*/
private static final Integer FLOW_MINUTE_REPORT_KEEP_DAYS = 2;
/**
* 流量统计小时报表记录保留天数
*/
private static final Integer FLOW_HOUR_REPORT_KEEP_DAYS = 90;
/**
* 流量统计天报表记录保留天数
*/
private static final Integer FLOW_DAY_REPORT_KEEP_DAYS = 400;
@Override
public void execute(String s) throws Exception {
JobParams jobParams = getParams(s);
@@ -85,6 +98,24 @@ public class DataCleanJob implements IJobHandler {
log.info("清理客户端连接日志 date:{}", sdf.format(date));
dataCleanMapper.cleanClientConnectRecord(date.getTime());
}
{
Date date = DateUtil.addDate(new Date(), Calendar.DATE, -1 * jobParams.getFlowMinuteReportKeepDays());
log.info("清理流通统计分钟报表日志 date:{}", sdf.format(date));
dataCleanMapper.cleanFlowMinuteReport(date.getTime());
}
{
Date date = DateUtil.addDate(new Date(), Calendar.DATE, -1 * jobParams.getFlowHourReportKeepDays());
log.info("清理流通统计小时报表日志 date:{}", sdf.format(date));
dataCleanMapper.cleanFlowHourReport(date.getTime());
}
{
Date date = DateUtil.addDate(new Date(), Calendar.DATE, -1 * jobParams.getFlowDayReportKeepDays());
log.info("清理流通统计日报表日志 date:{}", sdf.format(date));
dataCleanMapper.cleanFlowDayReport(date.getTime());
}
}
public static JobParams getParams(String s) {
@@ -107,5 +138,8 @@ public class DataCleanJob implements IJobHandler {
private Integer jobLogKeepDays;
private Integer userLoginRecordKeepDays;
private Integer clientConnectRecordKeepDays;
private Integer flowMinuteReportKeepDays;
private Integer flowHourReportKeepDays;
private Integer flowDayReportKeepDays;
}
}