mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-02 07:27:01 +00:00
[Update] 解决排序问题
This commit is contained in:
parent
f6702c701d
commit
3873e7ceaf
@ -14,6 +14,7 @@
|
||||
@selection-change="selectStrategy.onSelectionChange"
|
||||
@select="selectStrategy.onSelect"
|
||||
@select-all="selectStrategy.onSelectAll($event, selectable)"
|
||||
@sort-change="onSortChange"
|
||||
>
|
||||
<!--TODO 不用jsx写, 感觉template逻辑有点不清晰了-->
|
||||
<template v-if="isTree">
|
||||
@ -103,6 +104,7 @@
|
||||
:is="col.formatter"
|
||||
:row="row"
|
||||
:col="col"
|
||||
:cell-value="row[col.prop]"
|
||||
>
|
||||
</div>
|
||||
<template v-else>
|
||||
@ -717,7 +719,7 @@ export default {
|
||||
extraQuery: {
|
||||
type: Object,
|
||||
default() {
|
||||
return undefined
|
||||
return {}
|
||||
}
|
||||
},
|
||||
/**
|
||||
@ -1230,6 +1232,19 @@ export default {
|
||||
iconShow(index, record) {
|
||||
// return index ===0 && record.children && record.children.length > 0;
|
||||
return record[this.treeChildKey] && record[this.treeChildKey].length > 0
|
||||
},
|
||||
onSortChange({ column, prop, order }) {
|
||||
if (!this.extraQuery) {
|
||||
this.extraQuery = {}
|
||||
}
|
||||
if (!order) {
|
||||
delete this.extraQuery['sort']
|
||||
delete this.extraQuery['direction']
|
||||
} else {
|
||||
this.extraQuery['sort'] = prop
|
||||
this.extraQuery['direction'] = order
|
||||
}
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
src/components/DataTable/formatters/ChoicesFormatter.vue
Normal file
32
src/components/DataTable/formatters/ChoicesFormatter.vue
Normal file
@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div>
|
||||
<i :class="'fa ' + iconClass"></i>
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import BaseFormatter from './base'
|
||||
export default {
|
||||
name: 'ChoicesFormatter',
|
||||
extends: [BaseFormatter],
|
||||
data() {
|
||||
return {
|
||||
defaultIconChoices: {
|
||||
true: 'fa-check text-primary',
|
||||
false: 'fa-times text-danger'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconClass() {
|
||||
const key = !!this.cellValue
|
||||
return this.defaultIconChoices[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<el-link :type="col.type || 'success'" @click="goDetail">{{ cellValue }}</el-link>
|
||||
<el-link class="detail" :type="col.type || 'success'" @click="goDetail">{{ cellValue }}</el-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@ -30,5 +30,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.detail {
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
|
26
src/components/DataTable/formatters/DisplayFormatter.vue
Normal file
26
src/components/DataTable/formatters/DisplayFormatter.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<span>{{ display }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DisplayFormatter',
|
||||
props: {
|
||||
col: Object,
|
||||
row: Object
|
||||
},
|
||||
data() {
|
||||
let displayKey = this.col.displayKey
|
||||
if (!displayKey) {
|
||||
displayKey = this.col.prop + '_display'
|
||||
}
|
||||
return {
|
||||
display: this.row[displayKey]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
27
src/components/DataTable/formatters/base.vue
Normal file
27
src/components/DataTable/formatters/base.vue
Normal file
@ -0,0 +1,27 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'BaseFormatter',
|
||||
props: {
|
||||
row: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
col: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
cellValue: {
|
||||
type: [String, Boolean, Number, Object],
|
||||
default: null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
3
src/components/DataTable/formatters/index.js
Normal file
3
src/components/DataTable/formatters/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
export { default as DetailFormatter } from './DetailFormatter'
|
||||
export { default as DisplayFormatter } from './DisplayFormatter'
|
||||
export { default as ChoicesFormatter } from './ChoicesFormatter'
|
@ -23,7 +23,8 @@ export default {
|
||||
axiosConfig: {
|
||||
raw: 1,
|
||||
params: {
|
||||
display: 1
|
||||
display: 1,
|
||||
draw: 1
|
||||
}
|
||||
},
|
||||
defaultAlign: 'left',
|
||||
@ -58,9 +59,10 @@ export default {
|
||||
},
|
||||
pageCount: 5,
|
||||
paginationLayout: 'total, sizes, prev, pager, next',
|
||||
paginationSize: 15,
|
||||
transformQuery: query => {
|
||||
if (query.page && query.size) {
|
||||
const page = query.page || 1
|
||||
const page = query.page > 0 ? query.page : 1
|
||||
const offset = (page - 1) * query.size
|
||||
const limit = query.size
|
||||
query.offset = offset
|
||||
@ -68,6 +70,13 @@ export default {
|
||||
delete query['page']
|
||||
delete query['size']
|
||||
}
|
||||
if (query.sort) {
|
||||
let ordering = query.direction === 'descending' ? '-' : ''
|
||||
ordering += query.sort
|
||||
query.order = ordering
|
||||
delete query['sort']
|
||||
delete query['direction']
|
||||
}
|
||||
return query
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,9 @@ const cn = {
|
||||
'More actions': '更多操作',
|
||||
'Delete selected': '删除所选',
|
||||
'Update selected': '更新所选',
|
||||
'Search': '搜索'
|
||||
'Search': '搜索',
|
||||
'Source': '来源',
|
||||
'Status': '状态'
|
||||
},
|
||||
route: {
|
||||
'dashboard': '仪表盘',
|
||||
@ -77,7 +79,7 @@ const cn = {
|
||||
'FtpLog': 'FTP日志',
|
||||
'OperateLog': '操作日志',
|
||||
'PasswordChangeLog': '改密日志',
|
||||
'Settings': '系统设置'
|
||||
'Settings': '系统设置',
|
||||
},
|
||||
// 用户模块翻译
|
||||
users: {
|
||||
@ -86,6 +88,9 @@ const cn = {
|
||||
'userDetail': '用户详情',
|
||||
'name': '姓名',
|
||||
'username': '用户名',
|
||||
'Username': '用户名',
|
||||
'Role': '角色',
|
||||
'User Groups': '用户组',
|
||||
'email': '邮箱',
|
||||
'userGroup': '用户组',
|
||||
'role': '角色',
|
||||
|
@ -203,3 +203,23 @@ td .el-button.el-button--mini {
|
||||
.el-table .descending .sort-caret.descending {
|
||||
border-top-color: #676a6c;
|
||||
}
|
||||
|
||||
.text-danger {
|
||||
color: $--color-danger;
|
||||
}
|
||||
|
||||
.text-primary {
|
||||
color: $--color-primary;
|
||||
}
|
||||
|
||||
.text-info {
|
||||
color: $--color-info;
|
||||
}
|
||||
|
||||
.text-warning {
|
||||
color: $--color-warning;
|
||||
}
|
||||
|
||||
.text-success {
|
||||
color: $--color-success;
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ export default {
|
||||
{
|
||||
prop: 'name',
|
||||
label: this.$tc('Name'),
|
||||
key: 'name',
|
||||
formatter: DetailFormatter,
|
||||
sortable: true,
|
||||
route: 'UserDetail'
|
||||
@ -31,13 +30,11 @@ export default {
|
||||
{
|
||||
prop: 'comment',
|
||||
label: this.$tc('Comment'),
|
||||
key: 'comment',
|
||||
showOverflowTooltip: true
|
||||
}
|
||||
],
|
||||
// 写路由名字,table组件会自动传作为参数
|
||||
tableActions: {
|
||||
hasEdit: true,
|
||||
editRoute: '404'
|
||||
}
|
||||
},
|
||||
|
@ -1,91 +1,63 @@
|
||||
<template>
|
||||
<Page>
|
||||
<IBox>
|
||||
<DataTable :config="tableConfig" />
|
||||
</IBox>
|
||||
</Page>
|
||||
<GenericListPage :table-config="tableConfig" :header-actions="headerActions" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IBox, Page } from '@/layout/components'
|
||||
import DataTable from '@/components/DataTable'
|
||||
import { GenericListPage } from '@/layout/components'
|
||||
import { DetailFormatter, DisplayFormatter, ChoicesFormatter } from '@/components/DataTable/formatters/index'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
IBox,
|
||||
Page,
|
||||
DataTable
|
||||
GenericListPage,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
tableConfig: {
|
||||
url: '/api/v1/users/users/',
|
||||
defaultAlign: 'left',
|
||||
operationAttrs: {
|
||||
label: 'Operation',
|
||||
prop: 'operation',
|
||||
key: 'prop',
|
||||
align: 'center'
|
||||
},
|
||||
|
||||
extraButtons: [
|
||||
{
|
||||
type: 'primary',
|
||||
// disabled: row => row.date === '2016-05-04',
|
||||
text: this.$t('users.update'),
|
||||
// 必须使用箭头函数
|
||||
atClick: (row) => {
|
||||
this.$router.push({ name: '404' })
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'warning',
|
||||
// disabled: row => row.date === '2016-05-04',
|
||||
text: this.$t('users.delete'),
|
||||
atClick: (row) => {
|
||||
|
||||
}
|
||||
}
|
||||
],
|
||||
columns: [
|
||||
{
|
||||
type: 'selection',
|
||||
align: 'center'
|
||||
},
|
||||
// Bug
|
||||
// 应该让我插入Slot,使这个用户名可点击
|
||||
{
|
||||
prop: 'name',
|
||||
label: this.$t('users.name'),
|
||||
sortable: true // 可排序
|
||||
// url: 'UserDetail' // 第一个函数指定 路由Template
|
||||
label: this.$tc('Name'),
|
||||
formatter: DetailFormatter,
|
||||
sortable: 'custom',
|
||||
route: 'UserDetail'
|
||||
},
|
||||
{
|
||||
prop: 'username',
|
||||
label: this.$t('users.username'),
|
||||
sortable: true,
|
||||
label: this.$t('users.Username'),
|
||||
sortable: 'custom',
|
||||
},
|
||||
{
|
||||
prop: 'role',
|
||||
label: this.$t('users.role'),
|
||||
sortable: true
|
||||
label: this.$t('users.Role'),
|
||||
formatter: DisplayFormatter,
|
||||
sortable: 'custom',
|
||||
},
|
||||
// Bug API没有返回组织名称
|
||||
{
|
||||
prop: 'group',
|
||||
label: this.$t('users.usergroup'),
|
||||
sortable: true,
|
||||
align: 'left',
|
||||
formatter: row => {
|
||||
return <a href='http://qq.com' target='_blank'>hello</a>
|
||||
}
|
||||
prop: 'groups_display',
|
||||
label: this.$t('users.User Groups')
|
||||
},
|
||||
{
|
||||
prop: 'source',
|
||||
label: this.$t('users.source'),
|
||||
sortable: true
|
||||
label: this.$tc('Source'),
|
||||
sortable: 'custom',
|
||||
formatter: DisplayFormatter
|
||||
},
|
||||
{
|
||||
prop: 'is_valid',
|
||||
label: this.$tc('Status'),
|
||||
formatter: ChoicesFormatter,
|
||||
align: 'center',
|
||||
width: '80px'
|
||||
}
|
||||
]
|
||||
],
|
||||
// 写路由名字,table组件会自动传作为参数
|
||||
tableActions: {
|
||||
editRoute: '404'
|
||||
}
|
||||
},
|
||||
headerActions: {
|
||||
createRoute: 'UserGroupCreate'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user