commit
9afc46ccf1
|
@ -118,6 +118,7 @@ Understanding and learning this knowledge in advance will greatly help the use o
|
||||||
- Avatar Upload
|
- Avatar Upload
|
||||||
- Back To Top
|
- Back To Top
|
||||||
- Drag Dialog
|
- Drag Dialog
|
||||||
|
- Drag Select
|
||||||
- Drag Kanban
|
- Drag Kanban
|
||||||
- Drag List
|
- Drag List
|
||||||
- SplitPane
|
- SplitPane
|
||||||
|
@ -198,6 +199,14 @@ If you find this project useful, you can buy author a glass of juice :tropical_d
|
||||||
|
|
||||||
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
||||||
|
|
||||||
|
## Browsers support
|
||||||
|
|
||||||
|
Modern browsers and Internet Explorer 10+.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| --------- | --------- | --------- | --------- |
|
||||||
|
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
|
|
|
@ -130,6 +130,7 @@
|
||||||
- 头像上传
|
- 头像上传
|
||||||
- 返回顶部
|
- 返回顶部
|
||||||
- 拖拽Dialog
|
- 拖拽Dialog
|
||||||
|
- 拖拽Select
|
||||||
- 拖拽看板
|
- 拖拽看板
|
||||||
- 列表拖拽
|
- 列表拖拽
|
||||||
- SplitPane
|
- SplitPane
|
||||||
|
@ -210,6 +211,14 @@ Detailed changes for each release are documented in the [release notes](https://
|
||||||
|
|
||||||
[Paypal Me](https://www.paypal.me/panfree23)
|
[Paypal Me](https://www.paypal.me/panfree23)
|
||||||
|
|
||||||
|
## Browsers support
|
||||||
|
|
||||||
|
Modern browsers and Internet Explorer 10+.
|
||||||
|
|
||||||
|
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)</br>Safari |
|
||||||
|
| --------- | --------- | --------- | --------- |
|
||||||
|
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vue-element-admin",
|
"name": "vue-element-admin",
|
||||||
"version": "3.9.1",
|
"version": "3.9.3",
|
||||||
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
||||||
"author": "Pan <panfree23@gmail.com>",
|
"author": "Pan <panfree23@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<transition-group name="breadcrumb">
|
<transition-group name="breadcrumb">
|
||||||
<el-breadcrumb-item v-for="(item,index) in levelList" v-if="item.meta.title" :key="item.path">
|
<el-breadcrumb-item v-for="(item,index) in levelList" v-if="item.meta.title" :key="item.path">
|
||||||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ generateTitle(item.meta.title) }}</span>
|
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ generateTitle(item.meta.title) }}</span>
|
||||||
<router-link v-else :to="item.redirect||item.path">{{ generateTitle(item.meta.title) }}</router-link>
|
<a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
|
||||||
</el-breadcrumb-item>
|
</el-breadcrumb-item>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</el-breadcrumb>
|
</el-breadcrumb>
|
||||||
|
@ -30,12 +30,8 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
generateTitle,
|
generateTitle,
|
||||||
getBreadcrumb() {
|
getBreadcrumb() {
|
||||||
const { params } = this.$route
|
|
||||||
let matched = this.$route.matched.filter(item => {
|
let matched = this.$route.matched.filter(item => {
|
||||||
if (item.name) {
|
if (item.name) {
|
||||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
|
||||||
var toPath = pathToRegexp.compile(item.path)
|
|
||||||
item.path = toPath(params)
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -44,6 +40,20 @@ export default {
|
||||||
matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
|
matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
|
||||||
}
|
}
|
||||||
this.levelList = matched
|
this.levelList = matched
|
||||||
|
},
|
||||||
|
pathCompile(path) {
|
||||||
|
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||||
|
const { params } = this.$route
|
||||||
|
var toPath = pathToRegexp.compile(path)
|
||||||
|
return toPath(params)
|
||||||
|
},
|
||||||
|
handleLink(item) {
|
||||||
|
const { redirect, path } = item
|
||||||
|
if (redirect) {
|
||||||
|
this.$router.push(redirect)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$router.push(this.pathCompile(path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import { debounce } from '@/utils'
|
import { debounce } from '@/utils'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
sidebarElm: null
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.__resizeHandler = debounce(() => {
|
this.__resizeHandler = debounce(() => {
|
||||||
if (this.chart) {
|
if (this.chart) {
|
||||||
|
@ -9,14 +14,13 @@ export default {
|
||||||
}, 100)
|
}, 100)
|
||||||
window.addEventListener('resize', this.__resizeHandler)
|
window.addEventListener('resize', this.__resizeHandler)
|
||||||
|
|
||||||
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
this.sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||||
sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler)
|
this.sidebarElm && this.sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
window.removeEventListener('resize', this.__resizeHandler)
|
window.removeEventListener('resize', this.__resizeHandler)
|
||||||
|
|
||||||
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
this.sidebarElm && this.sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler)
|
||||||
sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler)
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
sidebarResizeHandler(e) {
|
sidebarResizeHandler(e) {
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
<template>
|
||||||
|
<el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
|
||||||
|
<slot/>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Sortable from 'sortablejs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DragSelect',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectVal: {
|
||||||
|
get() {
|
||||||
|
return [...this.value]
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('input', [...val])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.setSort()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setSort() {
|
||||||
|
const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
|
||||||
|
this.sortable = Sortable.create(el, {
|
||||||
|
ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
|
||||||
|
setData: function(dataTransfer) {
|
||||||
|
dataTransfer.setData('Text', '')
|
||||||
|
// to avoid Firefox bug
|
||||||
|
// Detail see : https://github.com/RubaXa/Sortable/issues/1012
|
||||||
|
},
|
||||||
|
onEnd: evt => {
|
||||||
|
const targetRow = this.value.splice(evt.oldIndex, 1)[0]
|
||||||
|
this.value.splice(evt.newIndex, 0, targetRow)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.drag-select >>> .sortable-ghost{
|
||||||
|
opacity: .8;
|
||||||
|
color: #fff!important;
|
||||||
|
background: #42b983!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drag-select >>> .el-tag{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -6,6 +6,7 @@
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
|
<el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
|
||||||
<el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
|
<el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="language==='es'" command="es">Español</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
<template>
|
||||||
|
<div :class="{'hidden':hidden}" class="pagination-container">
|
||||||
|
<el-pagination
|
||||||
|
:background="background"
|
||||||
|
:current-page.sync="currentPage"
|
||||||
|
:page-size.sync="pageSize"
|
||||||
|
:layout="layout"
|
||||||
|
:total="total"
|
||||||
|
v-bind="$attrs"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { scrollTo } from '@/utils/scrollTo'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Pagination',
|
||||||
|
props: {
|
||||||
|
total: {
|
||||||
|
required: true,
|
||||||
|
type: Number
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
default: 20
|
||||||
|
},
|
||||||
|
pageSizes: {
|
||||||
|
type: Array,
|
||||||
|
default() {
|
||||||
|
return [10, 20, 30, 50]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
layout: {
|
||||||
|
type: String,
|
||||||
|
default: 'total, sizes, prev, pager, next, jumper'
|
||||||
|
},
|
||||||
|
background: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
autoScroll: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
hidden: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
currentPage: {
|
||||||
|
get() {
|
||||||
|
return this.page
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('update:page', val)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pageSize: {
|
||||||
|
get() {
|
||||||
|
return this.limit
|
||||||
|
},
|
||||||
|
set(val) {
|
||||||
|
this.$emit('update:limit', val)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.$emit('pagination', { page: this.currentPage, limit: val })
|
||||||
|
if (this.autoScroll) {
|
||||||
|
scrollTo(0, 800)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
this.$emit('pagination', { page: val, limit: this.pageSize })
|
||||||
|
if (this.autoScroll) {
|
||||||
|
scrollTo(0, 800)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.pagination-container {
|
||||||
|
background: #fff;
|
||||||
|
padding: 32px 16px;
|
||||||
|
}
|
||||||
|
.pagination-container.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -5,7 +5,7 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const padding = 15 // tag's padding
|
const tagAndTagSpacing = 4 // tagAndTagSpacing
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ScrollPane',
|
name: 'ScrollPane',
|
||||||
|
@ -20,18 +20,54 @@ export default {
|
||||||
const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
|
const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
|
||||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
||||||
},
|
},
|
||||||
moveToTarget($target) {
|
moveToTarget(currentTag) {
|
||||||
const $container = this.$refs.scrollContainer.$el
|
const $container = this.$refs.scrollContainer.$el
|
||||||
const $containerWidth = $container.offsetWidth
|
const $containerWidth = $container.offsetWidth
|
||||||
const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
|
const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
|
||||||
const $targetLeft = $target.offsetLeft
|
const tagList = this.$parent.$refs.tag
|
||||||
const $targetWidth = $target.offsetWidth
|
|
||||||
if ($targetLeft > $containerWidth) {
|
let firstTag = null
|
||||||
// tag in the right
|
let lastTag = null
|
||||||
$scrollWrapper.scrollLeft = $targetLeft - $containerWidth + $targetWidth + padding
|
let prevTag = null
|
||||||
|
let nextTag = null
|
||||||
|
|
||||||
|
// find first tag and last tag
|
||||||
|
if (tagList.length > 0) {
|
||||||
|
firstTag = tagList[0]
|
||||||
|
lastTag = tagList[tagList.length - 1]
|
||||||
|
}
|
||||||
|
|
||||||
|
// find preTag and nextTag
|
||||||
|
for (let i = 0; i < tagList.length; i++) {
|
||||||
|
if (tagList[i] === currentTag) {
|
||||||
|
if (i === 0) {
|
||||||
|
nextTag = tagList[i].length > 1 && tagList[i + 1]
|
||||||
|
} else if (i === tagList.length - 1) {
|
||||||
|
prevTag = tagList[i].length > 1 && tagList[i - 1]
|
||||||
} else {
|
} else {
|
||||||
// tag in the left
|
prevTag = tagList[i - 1]
|
||||||
$scrollWrapper.scrollLeft = $targetLeft - padding
|
nextTag = tagList[i + 1]
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstTag === currentTag) {
|
||||||
|
$scrollWrapper.scrollLeft = 0
|
||||||
|
} else if (lastTag === currentTag) {
|
||||||
|
$scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
|
||||||
|
} else {
|
||||||
|
// the tag's offsetLeft after of nextTag
|
||||||
|
const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
|
||||||
|
|
||||||
|
// the tag's offsetLeft before of prevTag
|
||||||
|
const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
|
||||||
|
|
||||||
|
if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
|
||||||
|
$scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
|
||||||
|
} else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
|
||||||
|
$scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Here is a list of the toolbar
|
// Here is a list of the toolbar
|
||||||
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
||||||
|
|
||||||
const toolbar = ['bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
|
const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
|
||||||
|
|
||||||
export default toolbar
|
export default toolbar
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
|
|
||||||
如果不提供,将使用默认的[evalFunc](./eval.js)
|
如果不提供,将使用默认的[evalFunc](./eval.js)
|
||||||
|
|
||||||
如果提供了evalFunc,那么会用提供的evalFunc去解析data,并返回treeTable渲染所需要的值。如何编写一个evalFunc,请参考[*eval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/TreeTable/eval.js)或[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)
|
如果提供了evalFunc,那么会用提供的evalFunc去解析data,并返回treeTable渲染所需要的值。如何编写一个evalFunc,请参考[*eval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/TreeTable/eval.js)或[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customEval.js)
|
||||||
|
|
||||||
#### evalArgs
|
#### evalArgs
|
||||||
解析函数的参数,是一个数组
|
解析函数的参数,是一个数组
|
||||||
|
@ -76,12 +76,12 @@
|
||||||
|
|
||||||
如果你的解析函数参数只有`(this.data, this.expandAll)`,那么就可以不用填写evalArgs了
|
如果你的解析函数参数只有`(this.data, this.expandAll)`,那么就可以不用填写evalArgs了
|
||||||
|
|
||||||
具体可参考[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)的函数参数和[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue)的`evalArgs`属性值
|
具体可参考[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customEval.js)的函数参数和[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customTreeTable.vue)的`evalArgs`属性值
|
||||||
|
|
||||||
## slot
|
## slot
|
||||||
这是一个自定义列的插槽。
|
这是一个自定义列的插槽。
|
||||||
|
|
||||||
默认情况下,treeTable只有一行行展示数据的功能。但是一般情况下,我们会要给行加上一个操作按钮或者根据当行数据展示不同的样式,这时我们就需要自定义列了。请参考[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue),[实例效果](http://panjiachen.github.io/vue-element-admin/#/example/table/custom-tree-table)
|
默认情况下,treeTable只有一行行展示数据的功能。但是一般情况下,我们会要给行加上一个操作按钮或者根据当行数据展示不同的样式,这时我们就需要自定义列了。请参考[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customTreeTable.vue),[实例效果](https://panjiachen.github.io/vue-element-admin/#/table/tree-table)
|
||||||
|
|
||||||
`slot`和`columns属性`可同时存在,columns里面的数据列会在slot自定义列的左边展示
|
`slot`和`columns属性`可同时存在,columns里面的数据列会在slot自定义列的左边展示
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ export default {
|
||||||
componentMixin: 'Mixin',
|
componentMixin: 'Mixin',
|
||||||
backToTop: 'BackToTop',
|
backToTop: 'BackToTop',
|
||||||
dragDialog: 'Drag Dialog',
|
dragDialog: 'Drag Dialog',
|
||||||
|
dragSelect: 'Drag Select',
|
||||||
dragKanban: 'Drag Kanban',
|
dragKanban: 'Drag Kanban',
|
||||||
charts: 'Charts',
|
charts: 'Charts',
|
||||||
keyboardChart: 'Keyboard Chart',
|
keyboardChart: 'Keyboard Chart',
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
export default {
|
||||||
|
route: {
|
||||||
|
dashboard: 'Panel de control',
|
||||||
|
introduction: 'Introducción',
|
||||||
|
documentation: 'Documentación',
|
||||||
|
guide: 'Guía',
|
||||||
|
permission: 'Permisos',
|
||||||
|
pagePermission: 'Permisos de la página',
|
||||||
|
directivePermission: 'Permisos de la directiva',
|
||||||
|
icons: 'Iconos',
|
||||||
|
components: 'Componentes',
|
||||||
|
componentIndex: 'Introducción',
|
||||||
|
tinymce: 'Tinymce',
|
||||||
|
markdown: 'Markdown',
|
||||||
|
jsonEditor: 'Editor JSON',
|
||||||
|
dndList: 'Lista Dnd',
|
||||||
|
splitPane: 'Panel dividido',
|
||||||
|
avatarUpload: 'Subir avatar',
|
||||||
|
dropzone: 'Subir ficheros',
|
||||||
|
sticky: 'Sticky',
|
||||||
|
countTo: 'CountTo',
|
||||||
|
componentMixin: 'Mixin',
|
||||||
|
backToTop: 'Ir arriba',
|
||||||
|
dragDialog: 'Drag Dialog',
|
||||||
|
dragSelect: 'Drag Select',
|
||||||
|
dragKanban: 'Drag Kanban',
|
||||||
|
charts: 'Gráficos',
|
||||||
|
keyboardChart: 'Keyboard Chart',
|
||||||
|
lineChart: 'Gráfico de líneas',
|
||||||
|
mixChart: 'Mix Chart',
|
||||||
|
example: 'Ejemplo',
|
||||||
|
nested: 'Rutas anidadass',
|
||||||
|
menu1: 'Menu 1',
|
||||||
|
'menu1-1': 'Menu 1-1',
|
||||||
|
'menu1-2': 'Menu 1-2',
|
||||||
|
'menu1-2-1': 'Menu 1-2-1',
|
||||||
|
'menu1-2-2': 'Menu 1-2-2',
|
||||||
|
'menu1-3': 'Menu 1-3',
|
||||||
|
menu2: 'Menu 2',
|
||||||
|
Table: 'Tabla',
|
||||||
|
dynamicTable: 'Tabla dinámica',
|
||||||
|
dragTable: 'Arrastrar tabla',
|
||||||
|
inlineEditTable: 'Editor',
|
||||||
|
complexTable: 'Complex Table',
|
||||||
|
treeTable: 'Tree Table',
|
||||||
|
customTreeTable: 'Custom TreeTable',
|
||||||
|
tab: 'Pestaña',
|
||||||
|
form: 'Formulario',
|
||||||
|
createArticle: 'Crear artículo',
|
||||||
|
editArticle: 'Editar artículo',
|
||||||
|
articleList: 'Listado de artículos',
|
||||||
|
errorPages: 'Páginas de error',
|
||||||
|
page401: '401',
|
||||||
|
page404: '404',
|
||||||
|
errorLog: 'Registro de errores',
|
||||||
|
excel: 'Excel',
|
||||||
|
exportExcel: 'Exportar a Excel',
|
||||||
|
selectExcel: 'Export seleccionado',
|
||||||
|
uploadExcel: 'Subir Excel',
|
||||||
|
zip: 'Zip',
|
||||||
|
exportZip: 'Exportar a Zip',
|
||||||
|
theme: 'Tema',
|
||||||
|
clipboardDemo: 'Clipboard',
|
||||||
|
i18n: 'I18n',
|
||||||
|
externalLink: 'Enlace externo'
|
||||||
|
},
|
||||||
|
navbar: {
|
||||||
|
logOut: 'Salir',
|
||||||
|
dashboard: 'Panel de control',
|
||||||
|
github: 'Github',
|
||||||
|
screenfull: 'Pantalla completa',
|
||||||
|
theme: 'Tema',
|
||||||
|
size: 'Tamaño global'
|
||||||
|
},
|
||||||
|
login: {
|
||||||
|
title: 'Formulario de acceso',
|
||||||
|
logIn: 'Acceso',
|
||||||
|
username: 'Usuario',
|
||||||
|
password: 'Contraseña',
|
||||||
|
any: 'nada',
|
||||||
|
thirdparty: 'Conectar con',
|
||||||
|
thirdpartyTips: 'No se puede simular en local, así que combine su propia simulación de negocios. ! !'
|
||||||
|
},
|
||||||
|
documentation: {
|
||||||
|
documentation: 'Documentación',
|
||||||
|
github: 'Repositorio Github'
|
||||||
|
},
|
||||||
|
permission: {
|
||||||
|
roles: 'Tus permisos',
|
||||||
|
switchRoles: 'Cambiar permisos'
|
||||||
|
},
|
||||||
|
guide: {
|
||||||
|
description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',
|
||||||
|
button: 'Ver guía'
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
documentation: 'Documentación',
|
||||||
|
tinymceTips: 'Rich text editor is a core part of management system, but at the same time is a place with lots of problems. In the process of selecting rich texts, I also walked a lot of detours. The common rich text editors in the market are basically used, and the finally chose Tinymce. See documentation for more detailed rich text editor comparisons and introductions.',
|
||||||
|
dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.',
|
||||||
|
stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.',
|
||||||
|
backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner',
|
||||||
|
backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally',
|
||||||
|
imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.'
|
||||||
|
},
|
||||||
|
table: {
|
||||||
|
dynamicTips1: 'Fixed header, sorted by header order',
|
||||||
|
dynamicTips2: 'Not fixed header, sorted by click order',
|
||||||
|
dragTips1: 'Orden por defecto',
|
||||||
|
dragTips2: 'The after dragging order',
|
||||||
|
title: 'Título',
|
||||||
|
importance: 'Importancia',
|
||||||
|
type: 'Tipo',
|
||||||
|
remark: 'Remark',
|
||||||
|
search: 'Buscar',
|
||||||
|
add: 'Añadir',
|
||||||
|
export: 'Exportar',
|
||||||
|
reviewer: 'reviewer',
|
||||||
|
id: 'ID',
|
||||||
|
date: 'Fecha',
|
||||||
|
author: 'Autor',
|
||||||
|
readings: 'Lector',
|
||||||
|
status: 'Estado',
|
||||||
|
actions: 'Acciones',
|
||||||
|
edit: 'Editar',
|
||||||
|
publish: 'Publicar',
|
||||||
|
draft: 'Draft',
|
||||||
|
delete: 'Eliminar',
|
||||||
|
cancel: 'Cancelar',
|
||||||
|
confirm: 'Confirmar'
|
||||||
|
},
|
||||||
|
errorLog: {
|
||||||
|
tips: 'Please click the bug icon in the upper right corner',
|
||||||
|
description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.',
|
||||||
|
documentation: 'Documento de introducción'
|
||||||
|
},
|
||||||
|
excel: {
|
||||||
|
export: 'Exportar',
|
||||||
|
selectedExport: 'Exportar seleccionados',
|
||||||
|
placeholder: 'Por favor escribe un nombre de fichero'
|
||||||
|
},
|
||||||
|
zip: {
|
||||||
|
export: 'Exportar',
|
||||||
|
placeholder: 'Por favor escribe un nombre de fichero'
|
||||||
|
},
|
||||||
|
theme: {
|
||||||
|
change: 'Cambiar tema',
|
||||||
|
documentation: 'Documentación del tema',
|
||||||
|
tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.'
|
||||||
|
},
|
||||||
|
tagsView: {
|
||||||
|
refresh: 'Actualizar',
|
||||||
|
close: 'Cerrar',
|
||||||
|
closeOthers: 'Cerrar otros',
|
||||||
|
closeAll: 'Cerrar todos'
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,8 +3,10 @@ import VueI18n from 'vue-i18n'
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
|
import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
|
||||||
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
|
import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
|
||||||
|
import elementEsLocale from 'element-ui/lib/locale/lang/es'// element-ui lang
|
||||||
import enLocale from './en'
|
import enLocale from './en'
|
||||||
import zhLocale from './zh'
|
import zhLocale from './zh'
|
||||||
|
import esLocale from './es'
|
||||||
|
|
||||||
Vue.use(VueI18n)
|
Vue.use(VueI18n)
|
||||||
|
|
||||||
|
@ -16,12 +18,16 @@ const messages = {
|
||||||
zh: {
|
zh: {
|
||||||
...zhLocale,
|
...zhLocale,
|
||||||
...elementZhLocale
|
...elementZhLocale
|
||||||
|
},
|
||||||
|
es: {
|
||||||
|
...esLocale,
|
||||||
|
...elementEsLocale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const i18n = new VueI18n({
|
const i18n = new VueI18n({
|
||||||
// set locale
|
// set locale
|
||||||
// options: en or zh
|
// options: en | zh | es
|
||||||
locale: Cookies.get('language') || 'en',
|
locale: Cookies.get('language') || 'en',
|
||||||
// set locale messages
|
// set locale messages
|
||||||
messages
|
messages
|
||||||
|
|
|
@ -22,6 +22,7 @@ export default {
|
||||||
componentMixin: '小组件',
|
componentMixin: '小组件',
|
||||||
backToTop: '返回顶部',
|
backToTop: '返回顶部',
|
||||||
dragDialog: '拖拽 Dialog',
|
dragDialog: '拖拽 Dialog',
|
||||||
|
dragSelect: '拖拽 Select',
|
||||||
dragKanban: '可拖拽看板',
|
dragKanban: '可拖拽看板',
|
||||||
charts: '图表',
|
charts: '图表',
|
||||||
keyboardChart: '键盘图表',
|
keyboardChart: '键盘图表',
|
||||||
|
|
|
@ -4,6 +4,16 @@ import articleAPI from './article'
|
||||||
import remoteSearchAPI from './remoteSearch'
|
import remoteSearchAPI from './remoteSearch'
|
||||||
import transactionAPI from './transaction'
|
import transactionAPI from './transaction'
|
||||||
|
|
||||||
|
// 修复在使用 MockJS 情况下,设置 withCredentials = true,且未被拦截的跨域请求丢失 Cookies 的问题
|
||||||
|
// https://github.com/nuysoft/Mock/issues/300
|
||||||
|
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
|
||||||
|
Mock.XHR.prototype.send = function() {
|
||||||
|
if (this.custom.xhr) {
|
||||||
|
this.custom.xhr.withCredentials = this.withCredentials || false
|
||||||
|
}
|
||||||
|
this.proxy_send(...arguments)
|
||||||
|
}
|
||||||
|
|
||||||
// Mock.setup({
|
// Mock.setup({
|
||||||
// timeout: '350-600'
|
// timeout: '350-600'
|
||||||
// })
|
// })
|
||||||
|
|
|
@ -78,6 +78,12 @@ const componentsRouter = {
|
||||||
name: 'DragDialogDemo',
|
name: 'DragDialogDemo',
|
||||||
meta: { title: 'dragDialog' }
|
meta: { title: 'dragDialog' }
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'drag-select',
|
||||||
|
component: () => import('@/views/components-demo/dragSelect'),
|
||||||
|
name: 'DragSelectDemo',
|
||||||
|
meta: { title: 'dragSelect' }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'dnd-list',
|
path: 'dnd-list',
|
||||||
component: () => import('@/views/components-demo/dndList'),
|
component: () => import('@/views/components-demo/dndList'),
|
||||||
|
|
|
@ -164,17 +164,6 @@ export function objectMerge(target, source) {
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scrollTo(element, to, duration) {
|
|
||||||
if (duration <= 0) return
|
|
||||||
const difference = to - element.scrollTop
|
|
||||||
const perTick = (difference / duration) * 10
|
|
||||||
setTimeout(() => {
|
|
||||||
element.scrollTop = element.scrollTop + perTick
|
|
||||||
if (element.scrollTop === to) return
|
|
||||||
scrollTo(element, to, duration - 10)
|
|
||||||
}, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function toggleClass(element, className) {
|
export function toggleClass(element, className) {
|
||||||
if (!element || !className) {
|
if (!element || !className) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
Math.easeInOutQuad = function(t, b, c, d) {
|
||||||
|
t /= d / 2
|
||||||
|
if (t < 1) {
|
||||||
|
return c / 2 * t * t + b
|
||||||
|
}
|
||||||
|
t--
|
||||||
|
return -c / 2 * (t * (t - 2) - 1) + b
|
||||||
|
}
|
||||||
|
|
||||||
|
// requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
|
||||||
|
var requestAnimFrame = (function() {
|
||||||
|
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
|
||||||
|
})()
|
||||||
|
|
||||||
|
// because it's so fucking difficult to detect the scrolling element, just move them all
|
||||||
|
function move(amount) {
|
||||||
|
document.documentElement.scrollTop = amount
|
||||||
|
document.body.parentNode.scrollTop = amount
|
||||||
|
document.body.scrollTop = amount
|
||||||
|
}
|
||||||
|
|
||||||
|
function position() {
|
||||||
|
return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
|
||||||
|
}
|
||||||
|
|
||||||
|
export function scrollTo(to, duration, callback) {
|
||||||
|
const start = position()
|
||||||
|
const change = to - start
|
||||||
|
const increment = 20
|
||||||
|
let currentTime = 0
|
||||||
|
duration = (typeof (duration) === 'undefined') ? 500 : duration
|
||||||
|
var animateScroll = function() {
|
||||||
|
// increment the time
|
||||||
|
currentTime += increment
|
||||||
|
// find the value with the quadratic in-out easing function
|
||||||
|
var val = Math.easeInOutQuad(currentTime, start, change, duration)
|
||||||
|
// move the document.body
|
||||||
|
move(val)
|
||||||
|
// do the animation unless its over
|
||||||
|
if (currentTime < duration) {
|
||||||
|
requestAnimFrame(animateScroll)
|
||||||
|
} else {
|
||||||
|
if (callback && typeof (callback) === 'function') {
|
||||||
|
// the animation is done so lets callback
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
animateScroll()
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
<template>
|
||||||
|
<div class="components-container">
|
||||||
|
|
||||||
|
<el-drag-select v-model="value" style="width:500px;" multiple placeholder="请选择">
|
||||||
|
<el-option v-for="item in options" :label="item.label" :value="item.value" :key="item.value" />
|
||||||
|
</el-drag-select>
|
||||||
|
|
||||||
|
<div style="margin-top:30px;">
|
||||||
|
<el-tag v-for="item of value" :key="item" style="margin-right:15px;">{{ item }}</el-tag>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ElDragSelect from '@/components/DragSelect' // base on element-ui
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DragSelectDemo',
|
||||||
|
components: { ElDragSelect },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ['Apple', 'Banana', 'Orange'],
|
||||||
|
options: [{
|
||||||
|
value: 'Apple',
|
||||||
|
label: 'Apple'
|
||||||
|
}, {
|
||||||
|
value: 'Banana',
|
||||||
|
label: 'Banana'
|
||||||
|
}, {
|
||||||
|
value: 'Orange',
|
||||||
|
label: 'Orange'
|
||||||
|
}, {
|
||||||
|
value: 'Pear',
|
||||||
|
label: 'Pear'
|
||||||
|
}, {
|
||||||
|
value: 'Strawberry',
|
||||||
|
label: 'Strawberry'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -32,7 +32,8 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
chart: null
|
chart: null,
|
||||||
|
sidebarElm: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -55,8 +56,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 监听侧边栏的变化
|
// 监听侧边栏的变化
|
||||||
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
this.sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||||
sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler)
|
this.sidebarElm && this.sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler)
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
if (!this.chart) {
|
if (!this.chart) {
|
||||||
|
@ -66,8 +67,7 @@ export default {
|
||||||
window.removeEventListener('resize', this.__resizeHandler)
|
window.removeEventListener('resize', this.__resizeHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
this.sidebarElm && this.sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler)
|
||||||
sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler)
|
|
||||||
|
|
||||||
this.chart.dispose()
|
this.chart.dispose()
|
||||||
this.chart = null
|
this.chart = null
|
||||||
|
|
|
@ -143,7 +143,8 @@ export default {
|
||||||
title: [{ validator: validateRequire }],
|
title: [{ validator: validateRequire }],
|
||||||
content: [{ validator: validateRequire }],
|
content: [{ validator: validateRequire }],
|
||||||
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
|
source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
|
||||||
}
|
},
|
||||||
|
tempRoute: {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -161,6 +162,11 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.postForm = Object.assign({}, defaultForm)
|
this.postForm = Object.assign({}, defaultForm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Why need to make a copy of this.$route here?
|
||||||
|
// Because if you enter this page and quickly switch tag, may be in the execution of the setTagsViewTitle function, this.$route is no longer pointing to the current page
|
||||||
|
// https://github.com/PanJiaChen/vue-element-admin/issues/1221
|
||||||
|
this.tempRoute = Object.assign({}, this.$route)
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fetchData(id) {
|
fetchData(id) {
|
||||||
|
@ -178,7 +184,7 @@ export default {
|
||||||
},
|
},
|
||||||
setTagsViewTitle() {
|
setTagsViewTitle() {
|
||||||
const title = this.lang === 'zh' ? '编辑文章' : 'Edit Article'
|
const title = this.lang === 'zh' ? '编辑文章' : 'Edit Article'
|
||||||
const route = Object.assign({}, this.$route, { title: `${title}-${this.postForm.id}` })
|
const route = Object.assign({}, this.tempRoute, { title: `${title}-${this.postForm.id}` })
|
||||||
this.$store.dispatch('updateVisitedView', route)
|
this.$store.dispatch('updateVisitedView', route)
|
||||||
},
|
},
|
||||||
submitForm() {
|
submitForm() {
|
||||||
|
|
|
@ -50,26 +50,18 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<div class="pagination-container">
|
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
|
||||||
<el-pagination
|
|
||||||
:current-page="listQuery.page"
|
|
||||||
:page-sizes="[10,20,30, 50]"
|
|
||||||
:page-size="listQuery.limit"
|
|
||||||
:total="total"
|
|
||||||
background
|
|
||||||
layout="total, sizes, prev, pager, next, jumper"
|
|
||||||
@size-change="handleSizeChange"
|
|
||||||
@current-change="handleCurrentChange"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fetchList } from '@/api/article'
|
import { fetchList } from '@/api/article'
|
||||||
|
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ArticleList',
|
name: 'ArticleList',
|
||||||
|
components: { Pagination },
|
||||||
filters: {
|
filters: {
|
||||||
statusFilter(status) {
|
statusFilter(status) {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<el-radio-group v-model="lang" size="small">
|
<el-radio-group v-model="lang" size="small">
|
||||||
<el-radio label="zh" border>简体中文</el-radio>
|
<el-radio label="zh" border>简体中文</el-radio>
|
||||||
<el-radio label="en" border>English</el-radio>
|
<el-radio label="en" border>English</el-radio>
|
||||||
|
<el-radio label="es" border>Español</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
<el-tag style="margin-top:15px;display:block;" type="info">{{ $t('i18nView.note') }}</el-tag>
|
<el-tag style="margin-top:15px;display:block;" type="info">{{ $t('i18nView.note') }}</el-tag>
|
||||||
</div>
|
</div>
|
||||||
|
@ -101,6 +102,7 @@ export default {
|
||||||
if (!this.$i18n.getLocaleMessage('en')[viewName]) {
|
if (!this.$i18n.getLocaleMessage('en')[viewName]) {
|
||||||
this.$i18n.mergeLocaleMessage('en', local.en)
|
this.$i18n.mergeLocaleMessage('en', local.en)
|
||||||
this.$i18n.mergeLocaleMessage('zh', local.zh)
|
this.$i18n.mergeLocaleMessage('zh', local.zh)
|
||||||
|
this.$i18n.mergeLocaleMessage('es', local.es)
|
||||||
}
|
}
|
||||||
this.setOptions() // set default select options
|
this.setOptions() // set default select options
|
||||||
},
|
},
|
||||||
|
|
|
@ -39,5 +39,25 @@ export default {
|
||||||
two: 'Two',
|
two: 'Two',
|
||||||
three: 'Three'
|
three: 'Three'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
es: {
|
||||||
|
i18nView: {
|
||||||
|
title: 'Switch Language',
|
||||||
|
note: 'The internationalization of this project is based on vue-i18n',
|
||||||
|
datePlaceholder: 'Pick a day',
|
||||||
|
selectPlaceholder: 'Select',
|
||||||
|
tableDate: 'tableDate',
|
||||||
|
tableName: 'tableName',
|
||||||
|
tableAddress: 'tableAddress',
|
||||||
|
default: 'default:',
|
||||||
|
primary: 'primary',
|
||||||
|
success: 'success',
|
||||||
|
info: 'info',
|
||||||
|
warning: 'warning',
|
||||||
|
danger: 'danger',
|
||||||
|
one: 'One',
|
||||||
|
two: 'Two',
|
||||||
|
three: 'Three'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -130,15 +130,16 @@ export default {
|
||||||
height: 50px;
|
height: 50px;
|
||||||
margin-right: 30px;
|
margin-right: 30px;
|
||||||
.avatar-wrapper {
|
.avatar-wrapper {
|
||||||
cursor: pointer;
|
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
position: relative;
|
position: relative;
|
||||||
.user-avatar {
|
.user-avatar {
|
||||||
|
cursor: pointer;
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
.el-icon-caret-bottom {
|
.el-icon-caret-bottom {
|
||||||
|
cursor: pointer;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -20px;
|
right: -20px;
|
||||||
top: 25px;
|
top: 25px;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
v-for="tag in visitedViews"
|
v-for="tag in visitedViews"
|
||||||
ref="tag"
|
ref="tag"
|
||||||
:class="isActive(tag)?'active':''"
|
:class="isActive(tag)?'active':''"
|
||||||
:to="tag.fullPath"
|
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
|
||||||
:key="tag.path"
|
:key="tag.path"
|
||||||
tag="span"
|
tag="span"
|
||||||
class="tags-view-item"
|
class="tags-view-item"
|
||||||
|
@ -76,7 +76,7 @@ export default {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
for (const tag of tags) {
|
for (const tag of tags) {
|
||||||
if (tag.to.path === this.$route.path) {
|
if (tag.to.path === this.$route.path) {
|
||||||
this.$refs.scrollPane.moveToTarget(tag.$el)
|
this.$refs.scrollPane.moveToTarget(tag)
|
||||||
|
|
||||||
// when query is different then update
|
// when query is different then update
|
||||||
if (tag.to.fullPath !== this.$route.fullPath) {
|
if (tag.to.fullPath !== this.$route.fullPath) {
|
||||||
|
@ -121,11 +121,21 @@ export default {
|
||||||
this.$router.push('/')
|
this.$router.push('/')
|
||||||
},
|
},
|
||||||
openMenu(tag, e) {
|
openMenu(tag, e) {
|
||||||
|
const menuMinWidth = 105
|
||||||
|
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
|
||||||
|
const offsetWidth = this.$el.offsetWidth // container width
|
||||||
|
const maxLeft = offsetWidth - menuMinWidth // left boundary
|
||||||
|
const left = e.clientX - offsetLeft + 15 // 15: margin right
|
||||||
|
|
||||||
|
if (left > maxLeft) {
|
||||||
|
this.left = maxLeft
|
||||||
|
} else {
|
||||||
|
this.left = left
|
||||||
|
}
|
||||||
|
this.top = e.clientY
|
||||||
|
|
||||||
this.visible = true
|
this.visible = true
|
||||||
this.selectedTag = tag
|
this.selectedTag = tag
|
||||||
const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
|
|
||||||
this.left = e.clientX - offsetLeft + 15 // 15: margin right
|
|
||||||
this.top = e.clientY
|
|
||||||
},
|
},
|
||||||
closeMenu() {
|
closeMenu() {
|
||||||
this.visible = false
|
this.visible = false
|
||||||
|
|
|
@ -24,8 +24,9 @@
|
||||||
border
|
border
|
||||||
fit
|
fit
|
||||||
highlight-current-row
|
highlight-current-row
|
||||||
style="width: 100%;">
|
style="width: 100%;"
|
||||||
<el-table-column :label="$t('table.id')" align="center" width="65">
|
@sort-change="sortChange">
|
||||||
|
<el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="65">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{ scope.row.id }}</span>
|
<span>{{ scope.row.id }}</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -80,9 +81,7 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<div class="pagination-container">
|
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
|
||||||
<el-pagination v-show="total>0" :current-page="listQuery.page" :page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" :total="total" background layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" @current-change="handleCurrentChange"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
|
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
|
||||||
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;">
|
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;">
|
||||||
|
@ -130,8 +129,9 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
|
import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
|
||||||
import waves from '@/directive/waves' // 水波纹指令
|
import waves from '@/directive/waves' // Waves directive
|
||||||
import { parseTime } from '@/utils'
|
import { parseTime } from '@/utils'
|
||||||
|
import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
|
||||||
|
|
||||||
const calendarTypeOptions = [
|
const calendarTypeOptions = [
|
||||||
{ key: 'CN', display_name: 'China' },
|
{ key: 'CN', display_name: 'China' },
|
||||||
|
@ -148,9 +148,8 @@ const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ComplexTable',
|
name: 'ComplexTable',
|
||||||
directives: {
|
components: { Pagination },
|
||||||
waves
|
directives: { waves },
|
||||||
},
|
|
||||||
filters: {
|
filters: {
|
||||||
statusFilter(status) {
|
statusFilter(status) {
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
|
@ -168,7 +167,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
tableKey: 0,
|
tableKey: 0,
|
||||||
list: null,
|
list: null,
|
||||||
total: null,
|
total: 0,
|
||||||
listLoading: true,
|
listLoading: true,
|
||||||
listQuery: {
|
listQuery: {
|
||||||
page: 1,
|
page: 1,
|
||||||
|
@ -228,14 +227,6 @@ export default {
|
||||||
this.listQuery.page = 1
|
this.listQuery.page = 1
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
},
|
||||||
handleSizeChange(val) {
|
|
||||||
this.listQuery.limit = val
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
handleCurrentChange(val) {
|
|
||||||
this.listQuery.page = val
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
handleModifyStatus(row, status) {
|
handleModifyStatus(row, status) {
|
||||||
this.$message({
|
this.$message({
|
||||||
message: '操作成功',
|
message: '操作成功',
|
||||||
|
@ -243,6 +234,20 @@ export default {
|
||||||
})
|
})
|
||||||
row.status = status
|
row.status = status
|
||||||
},
|
},
|
||||||
|
sortChange(data) {
|
||||||
|
const { prop, order } = data
|
||||||
|
if (prop === 'id') {
|
||||||
|
this.sortByID(order)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sortByID(order) {
|
||||||
|
if (order === 'ascending') {
|
||||||
|
this.listQuery.sort = '+id'
|
||||||
|
} else {
|
||||||
|
this.listQuery.sort = '-id'
|
||||||
|
}
|
||||||
|
this.handleFilter()
|
||||||
|
},
|
||||||
resetTemp() {
|
resetTemp() {
|
||||||
this.temp = {
|
this.temp = {
|
||||||
id: undefined,
|
id: undefined,
|
||||||
|
|
Loading…
Reference in New Issue