mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-22 16:47:03 +00:00
[Update] 解决排序问题
This commit is contained in:
parent
f6702c701d
commit
3873e7ceaf
@ -14,6 +14,7 @@
|
|||||||
@selection-change="selectStrategy.onSelectionChange"
|
@selection-change="selectStrategy.onSelectionChange"
|
||||||
@select="selectStrategy.onSelect"
|
@select="selectStrategy.onSelect"
|
||||||
@select-all="selectStrategy.onSelectAll($event, selectable)"
|
@select-all="selectStrategy.onSelectAll($event, selectable)"
|
||||||
|
@sort-change="onSortChange"
|
||||||
>
|
>
|
||||||
<!--TODO 不用jsx写, 感觉template逻辑有点不清晰了-->
|
<!--TODO 不用jsx写, 感觉template逻辑有点不清晰了-->
|
||||||
<template v-if="isTree">
|
<template v-if="isTree">
|
||||||
@ -103,6 +104,7 @@
|
|||||||
:is="col.formatter"
|
:is="col.formatter"
|
||||||
:row="row"
|
:row="row"
|
||||||
:col="col"
|
:col="col"
|
||||||
|
:cell-value="row[col.prop]"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
@ -717,7 +719,7 @@ export default {
|
|||||||
extraQuery: {
|
extraQuery: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default() {
|
default() {
|
||||||
return undefined
|
return {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@ -1230,6 +1232,19 @@ export default {
|
|||||||
iconShow(index, record) {
|
iconShow(index, record) {
|
||||||
// return index ===0 && record.children && record.children.length > 0;
|
// return index ===0 && record.children && record.children.length > 0;
|
||||||
return record[this.treeChildKey] && record[this.treeChildKey].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>
|
<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>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -30,5 +30,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.detail {
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
</style>
|
</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: {
|
axiosConfig: {
|
||||||
raw: 1,
|
raw: 1,
|
||||||
params: {
|
params: {
|
||||||
display: 1
|
display: 1,
|
||||||
|
draw: 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
defaultAlign: 'left',
|
defaultAlign: 'left',
|
||||||
@ -58,9 +59,10 @@ export default {
|
|||||||
},
|
},
|
||||||
pageCount: 5,
|
pageCount: 5,
|
||||||
paginationLayout: 'total, sizes, prev, pager, next',
|
paginationLayout: 'total, sizes, prev, pager, next',
|
||||||
|
paginationSize: 15,
|
||||||
transformQuery: query => {
|
transformQuery: query => {
|
||||||
if (query.page && query.size) {
|
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 offset = (page - 1) * query.size
|
||||||
const limit = query.size
|
const limit = query.size
|
||||||
query.offset = offset
|
query.offset = offset
|
||||||
@ -68,6 +70,13 @@ export default {
|
|||||||
delete query['page']
|
delete query['page']
|
||||||
delete query['size']
|
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
|
return query
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,9 @@ const cn = {
|
|||||||
'More actions': '更多操作',
|
'More actions': '更多操作',
|
||||||
'Delete selected': '删除所选',
|
'Delete selected': '删除所选',
|
||||||
'Update selected': '更新所选',
|
'Update selected': '更新所选',
|
||||||
'Search': '搜索'
|
'Search': '搜索',
|
||||||
|
'Source': '来源',
|
||||||
|
'Status': '状态'
|
||||||
},
|
},
|
||||||
route: {
|
route: {
|
||||||
'dashboard': '仪表盘',
|
'dashboard': '仪表盘',
|
||||||
@ -77,7 +79,7 @@ const cn = {
|
|||||||
'FtpLog': 'FTP日志',
|
'FtpLog': 'FTP日志',
|
||||||
'OperateLog': '操作日志',
|
'OperateLog': '操作日志',
|
||||||
'PasswordChangeLog': '改密日志',
|
'PasswordChangeLog': '改密日志',
|
||||||
'Settings': '系统设置'
|
'Settings': '系统设置',
|
||||||
},
|
},
|
||||||
// 用户模块翻译
|
// 用户模块翻译
|
||||||
users: {
|
users: {
|
||||||
@ -86,6 +88,9 @@ const cn = {
|
|||||||
'userDetail': '用户详情',
|
'userDetail': '用户详情',
|
||||||
'name': '姓名',
|
'name': '姓名',
|
||||||
'username': '用户名',
|
'username': '用户名',
|
||||||
|
'Username': '用户名',
|
||||||
|
'Role': '角色',
|
||||||
|
'User Groups': '用户组',
|
||||||
'email': '邮箱',
|
'email': '邮箱',
|
||||||
'userGroup': '用户组',
|
'userGroup': '用户组',
|
||||||
'role': '角色',
|
'role': '角色',
|
||||||
|
@ -203,3 +203,23 @@ td .el-button.el-button--mini {
|
|||||||
.el-table .descending .sort-caret.descending {
|
.el-table .descending .sort-caret.descending {
|
||||||
border-top-color: #676a6c;
|
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',
|
prop: 'name',
|
||||||
label: this.$tc('Name'),
|
label: this.$tc('Name'),
|
||||||
key: 'name',
|
|
||||||
formatter: DetailFormatter,
|
formatter: DetailFormatter,
|
||||||
sortable: true,
|
sortable: true,
|
||||||
route: 'UserDetail'
|
route: 'UserDetail'
|
||||||
@ -31,13 +30,11 @@ export default {
|
|||||||
{
|
{
|
||||||
prop: 'comment',
|
prop: 'comment',
|
||||||
label: this.$tc('Comment'),
|
label: this.$tc('Comment'),
|
||||||
key: 'comment',
|
|
||||||
showOverflowTooltip: true
|
showOverflowTooltip: true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
// 写路由名字,table组件会自动传作为参数
|
// 写路由名字,table组件会自动传作为参数
|
||||||
tableActions: {
|
tableActions: {
|
||||||
hasEdit: true,
|
|
||||||
editRoute: '404'
|
editRoute: '404'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1,91 +1,63 @@
|
|||||||
<template>
|
<template>
|
||||||
<Page>
|
<GenericListPage :table-config="tableConfig" :header-actions="headerActions" />
|
||||||
<IBox>
|
|
||||||
<DataTable :config="tableConfig" />
|
|
||||||
</IBox>
|
|
||||||
</Page>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { IBox, Page } from '@/layout/components'
|
import { GenericListPage } from '@/layout/components'
|
||||||
import DataTable from '@/components/DataTable'
|
import { DetailFormatter, DisplayFormatter, ChoicesFormatter } from '@/components/DataTable/formatters/index'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
IBox,
|
GenericListPage,
|
||||||
Page,
|
|
||||||
DataTable
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tableConfig: {
|
tableConfig: {
|
||||||
url: '/api/v1/users/users/',
|
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: [
|
columns: [
|
||||||
{
|
|
||||||
type: 'selection',
|
|
||||||
align: 'center'
|
|
||||||
},
|
|
||||||
// Bug
|
|
||||||
// 应该让我插入Slot,使这个用户名可点击
|
|
||||||
{
|
{
|
||||||
prop: 'name',
|
prop: 'name',
|
||||||
label: this.$t('users.name'),
|
label: this.$tc('Name'),
|
||||||
sortable: true // 可排序
|
formatter: DetailFormatter,
|
||||||
// url: 'UserDetail' // 第一个函数指定 路由Template
|
sortable: 'custom',
|
||||||
|
route: 'UserDetail'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'username',
|
prop: 'username',
|
||||||
label: this.$t('users.username'),
|
label: this.$t('users.Username'),
|
||||||
sortable: true,
|
sortable: 'custom',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'role',
|
prop: 'role',
|
||||||
label: this.$t('users.role'),
|
label: this.$t('users.Role'),
|
||||||
sortable: true
|
formatter: DisplayFormatter,
|
||||||
|
sortable: 'custom',
|
||||||
},
|
},
|
||||||
// Bug API没有返回组织名称
|
|
||||||
{
|
{
|
||||||
prop: 'group',
|
prop: 'groups_display',
|
||||||
label: this.$t('users.usergroup'),
|
label: this.$t('users.User Groups')
|
||||||
sortable: true,
|
|
||||||
align: 'left',
|
|
||||||
formatter: row => {
|
|
||||||
return <a href='http://qq.com' target='_blank'>hello</a>
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'source',
|
prop: 'source',
|
||||||
label: this.$t('users.source'),
|
label: this.$tc('Source'),
|
||||||
sortable: true
|
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