feat: 增加表格快捷操作
This commit is contained in:
parent
94cb153aa8
commit
4314fc52f2
@ -30,6 +30,7 @@
|
|||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"print-js": "^1.0.63",
|
"print-js": "^1.0.63",
|
||||||
"raphael": "^2.3.0",
|
"raphael": "^2.3.0",
|
||||||
|
"screenfull": "^5.1.0",
|
||||||
"viser-vue": "^2.4.6",
|
"viser-vue": "^2.4.6",
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
"vue-clipboard2": "^0.2.1",
|
"vue-clipboard2": "^0.2.1",
|
||||||
|
81
_web/src/components/Table/columnSetting.vue
Normal file
81
_web/src/components/Table/columnSetting.vue
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
<template>
|
||||||
|
<div slot="overlay" class="ant-dropdown-menu s-tool-column ant-dropdown-content">
|
||||||
|
<div class="s-tool-column-header s-tool-column-item">
|
||||||
|
<a-checkbox :indeterminate="indeterminate" :checked="checkAll" @change="onCheckAllChange">
|
||||||
|
列展示
|
||||||
|
</a-checkbox>
|
||||||
|
<a @click="reset">重置</a>
|
||||||
|
</div>
|
||||||
|
<a-divider />
|
||||||
|
<div class="ant-checkbox-group">
|
||||||
|
<div>
|
||||||
|
<draggable v-model="columnsSetting" animation="300" @end="dragEnd">
|
||||||
|
<div class="s-tool-column-item" v-for="item in columnsSetting" :key="item.title">
|
||||||
|
<div class="s-tool-column-handle" >
|
||||||
|
<a-icon type="more"/>
|
||||||
|
<a-icon type="more"/>
|
||||||
|
</div>
|
||||||
|
<a-checkbox v-model="item.checked" @change="onChange">{{ item.title }}</a-checkbox>
|
||||||
|
</div>
|
||||||
|
</draggable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <a-checkbox-group v-model="checkedList" :options="optionsWithDisabled" @change="onChange" >-->
|
||||||
|
<!-- </a-checkbox-group>-->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
columns: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ([])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
draggable
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
indeterminate: false,
|
||||||
|
checkAll: true,
|
||||||
|
columnsSetting: [],
|
||||||
|
originColumns: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
reset() {
|
||||||
|
this.columnsSetting = this.originColumns
|
||||||
|
this.indeterminate = false
|
||||||
|
this.checkAll = true
|
||||||
|
},
|
||||||
|
onChange() {
|
||||||
|
const checkedList = this.columnsSetting.filter(value => value.checked)
|
||||||
|
this.indeterminate = !!checkedList.length && checkedList.length < this.columnsSetting.length
|
||||||
|
this.checkAll = checkedList.length === this.columnsSetting.length
|
||||||
|
this.$emit('columnChange', this.columnsSetting)
|
||||||
|
},
|
||||||
|
onCheckAllChange(e) {
|
||||||
|
const val = e.target.checked
|
||||||
|
Object.assign(this, {
|
||||||
|
indeterminate: false,
|
||||||
|
checkAll: val,
|
||||||
|
columnsSetting: this.columns.map(value => ({ ...value, checked: val }))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
dragEnd() {
|
||||||
|
this.$emit('columnChange', this.columnsSetting)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.columnsSetting = this.columns.map(value => ({ ...value, checked: true }))
|
||||||
|
this.originColumns = [...this.columnsSetting]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
|
||||||
|
</style>
|
@ -1,7 +1,14 @@
|
|||||||
import T from 'ant-design-vue/es/table/Table'
|
import T from 'ant-design-vue/es/table/Table'
|
||||||
import get from 'lodash.get'
|
import get from 'lodash.get'
|
||||||
|
import screenfull from 'screenfull'
|
||||||
|
import draggable from 'vuedraggable'
|
||||||
|
import columnSetting from './columnSetting'
|
||||||
|
import './index.less'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
draggable, columnSetting
|
||||||
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
needTotalList: [],
|
needTotalList: [],
|
||||||
@ -11,7 +18,15 @@ export default {
|
|||||||
|
|
||||||
localLoading: false,
|
localLoading: false,
|
||||||
localDataSource: [],
|
localDataSource: [],
|
||||||
localPagination: Object.assign({}, this.pagination)
|
localPagination: Object.assign({}, this.pagination),
|
||||||
|
isFullscreen: false,
|
||||||
|
customSize: this.size,
|
||||||
|
|
||||||
|
// 列配置
|
||||||
|
indeterminate: true,
|
||||||
|
checkAll: false,
|
||||||
|
checkedList: [],
|
||||||
|
columnsSetting: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
props: Object.assign({}, T.props, {
|
props: Object.assign({}, T.props, {
|
||||||
@ -74,6 +89,10 @@ export default {
|
|||||||
pageURI: {
|
pageURI: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
extraTool: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ([])
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
watch: {
|
watch: {
|
||||||
@ -116,6 +135,7 @@ export default {
|
|||||||
// console.log('this.localPagination', this.localPagination)
|
// console.log('this.localPagination', this.localPagination)
|
||||||
this.needTotalList = this.initTotalList(this.columns)
|
this.needTotalList = this.initTotalList(this.columns)
|
||||||
this.loadData()
|
this.loadData()
|
||||||
|
this.columnsSetting = this.columns
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/**
|
/**
|
||||||
@ -276,11 +296,109 @@ export default {
|
|||||||
</template>
|
</template>
|
||||||
</a-alert>
|
</a-alert>
|
||||||
) */
|
) */
|
||||||
|
},
|
||||||
|
columnChange(val) {
|
||||||
|
this.columnsSetting = val
|
||||||
|
},
|
||||||
|
renderHeader () {
|
||||||
|
let tools = [
|
||||||
|
{
|
||||||
|
icon: 'reload',
|
||||||
|
title: '刷新',
|
||||||
|
onClick: () => {
|
||||||
|
this.refresh()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'column-height',
|
||||||
|
title: '密度',
|
||||||
|
isDropdown: true,
|
||||||
|
menu: () => {
|
||||||
|
const onClick = ({ key }) => {
|
||||||
|
this.customSize = key
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a-menu slot="overlay" onClick={onClick} selectable defaultSelectedKeys={[this.customSize]}>
|
||||||
|
<a-menu-item key="default">默认</a-menu-item>
|
||||||
|
<a-menu-item key="middle">中等</a-menu-item>
|
||||||
|
<a-menu-item key="small">紧凑</a-menu-item>
|
||||||
|
</a-menu>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'setting',
|
||||||
|
title: '列设置',
|
||||||
|
isDropdown: true,
|
||||||
|
menu: () => {
|
||||||
|
return <columnSetting slot="overlay" columns={this.columns} onColumnChange={this.columnChange} />
|
||||||
|
},
|
||||||
|
onClick: () => {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: this.isFullscreen ? 'fullscreen-exit' : 'fullscreen',
|
||||||
|
title: '全屏',
|
||||||
|
onClick: () => {
|
||||||
|
if (screenfull.isEnabled) {
|
||||||
|
const table = document.querySelector('.table-wrapper')
|
||||||
|
const antdCard = table.parentNode.parentNode
|
||||||
|
if (antdCard.classList.contains('ant-card')) {
|
||||||
|
screenfull.toggle(antdCard)
|
||||||
|
this.isFullscreen = !this.isFullscreen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
if (this.extraTool.length) {
|
||||||
|
tools = tools.concat(this.extraTool)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="s-table-tool">
|
||||||
|
<div class="s-table-tool-left">
|
||||||
|
{this.$scopedSlots.operator()}
|
||||||
|
</div>
|
||||||
|
<div class="s-table-tool-right">
|
||||||
|
{
|
||||||
|
tools.map(tool => {
|
||||||
|
if (tool.isDropdown) {
|
||||||
|
return (
|
||||||
|
<a-dropdown trigger={['click']}>
|
||||||
|
<a-tooltip title={tool.title} class="s-tool-item" onClick={tool.onClick}>
|
||||||
|
<a-icon type={tool.icon}/>
|
||||||
|
</a-tooltip>
|
||||||
|
{ tool.menu() }
|
||||||
|
</a-dropdown>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<a-tooltip title={tool.title} class="s-tool-item" onClick={tool.onClick}>
|
||||||
|
<a-icon type={tool.icon} />
|
||||||
|
</a-tooltip>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
/* return (
|
||||||
|
<a-alert showIcon={true} style="margin-bottom: 16px">
|
||||||
|
<template slot="message">
|
||||||
|
<span style="margin-right: 12px">已选择: <a style="font-weight: 600">{this.selectedRows.length}</a></span>
|
||||||
|
{needTotalItems}
|
||||||
|
{clearItem}
|
||||||
|
</template>
|
||||||
|
</a-alert>
|
||||||
|
) */
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const props = {}
|
let props = {}
|
||||||
const localKeys = Object.keys(this.$data)
|
const localKeys = Object.keys(this.$data)
|
||||||
const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert
|
const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert
|
||||||
|
|
||||||
@ -311,6 +429,12 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this[k] && (props[k] = this[k])
|
this[k] && (props[k] = this[k])
|
||||||
|
// 此处配置表格大小与要显示的列
|
||||||
|
props = {
|
||||||
|
...props,
|
||||||
|
size: this.customSize,
|
||||||
|
columns: this.columnsSetting.filter(value => value.checked === undefined || value.checked)
|
||||||
|
}
|
||||||
return props[k]
|
return props[k]
|
||||||
})
|
})
|
||||||
const table = (
|
const table = (
|
||||||
@ -321,6 +445,7 @@ export default {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="table-wrapper">
|
<div class="table-wrapper">
|
||||||
|
{ this.renderHeader() }
|
||||||
{ showAlert ? this.renderAlert() : null }
|
{ showAlert ? this.renderAlert() : null }
|
||||||
{ table }
|
{ table }
|
||||||
</div>
|
</div>
|
||||||
|
54
_web/src/components/Table/index.less
Normal file
54
_web/src/components/Table/index.less
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
.table-wrapper{
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.s-table-tool{
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
.s-table-tool-left{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.s-table-tool-right{
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
.s-tool-item{
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-tool-column-item{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 16px 4px 4px;
|
||||||
|
.ant-checkbox-wrapper{
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
.s-tool-column-handle{
|
||||||
|
opacity: .8;
|
||||||
|
cursor: move;
|
||||||
|
.anticon-more{
|
||||||
|
font-size: 12px;
|
||||||
|
margin-top: 2px;
|
||||||
|
& + .anticon-more{
|
||||||
|
margin: 2px 4px 0 -8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.s-tool-column-header{
|
||||||
|
padding: 5px 16px 10px 24px;
|
||||||
|
min-width: 180px;
|
||||||
|
}
|
||||||
|
.s-tool-column{
|
||||||
|
.ant-divider{
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.ant-checkbox-group{
|
||||||
|
padding: 4px 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,10 +43,6 @@
|
|||||||
</a-form>
|
</a-form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-operator" v-if="hasPerm('sysUser:add')" >
|
|
||||||
<a-button type="primary" v-if="hasPerm('sysUser:add')" icon="plus" @click="$refs.addForm.add()">新增用户</a-button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<s-table
|
<s-table
|
||||||
ref="table"
|
ref="table"
|
||||||
size="default"
|
size="default"
|
||||||
@ -56,6 +52,9 @@
|
|||||||
:rowKey="(record) => record.id"
|
:rowKey="(record) => record.id"
|
||||||
:rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
|
:rowSelection="{ selectedRowKeys: selectedRowKeys, onChange: onSelectChange }"
|
||||||
>
|
>
|
||||||
|
<template slot="operator" v-if="hasPerm('sysUser:add')">
|
||||||
|
<a-button type="primary" v-if="hasPerm('sysUser:add')" icon="plus" @click="$refs.addForm.add()">新增用户</a-button>
|
||||||
|
</template>
|
||||||
<span slot="sex" slot-scope="text">
|
<span slot="sex" slot-scope="text">
|
||||||
{{ sexFilter(text) }}
|
{{ sexFilter(text) }}
|
||||||
</span>
|
</span>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user