【fix 66426】完成JTable的隐藏冻结列控制
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
<template>
|
||||
<a-table
|
||||
ref='table'
|
||||
:table-key="tableKey"
|
||||
:columns="resultColumns"
|
||||
v-bind="$attrs"
|
||||
v-on="$listeners">
|
||||
|
||||
<template v-for="(slotItem) of slots" :slot="slotItem" slot-scope="text, record, index">
|
||||
<slot :name="slotItem" v-bind="{text,record,index}"></slot>
|
||||
</template>
|
||||
|
||||
<div slot="settingDropdown">
|
||||
<a-card>
|
||||
<!-- scroll.x 要大于表格所有固定列宽的合,每个列都要有width,否则定位后宽度会出现变形,否则会出现问题 -->
|
||||
<a-table
|
||||
rowKey="key"
|
||||
:style="settingStyle"
|
||||
tableLayout="fixed"
|
||||
size="small"
|
||||
bordered
|
||||
:pagination="false"
|
||||
:scroll="settingScroll"
|
||||
:data-source="settingDataSource"
|
||||
:columns="settingColumns">
|
||||
|
||||
<a-checkbox slot="hide" slot-scope="text, record"
|
||||
:checked="text"
|
||||
:disabled="record.disabledHide"
|
||||
@change="changeSetting(text, 'hide', record)"></a-checkbox>
|
||||
<a-checkbox slot="freeze" slot-scope="text, record"
|
||||
:checked="text"
|
||||
:disabled="record.disabledFreeze"
|
||||
@change="changeSetting(text, 'freeze', record)"></a-checkbox>
|
||||
</a-table>
|
||||
</a-card>
|
||||
</div>
|
||||
<a-icon ref='settingBtn' slot="settingIcon" type='setting' :style="{ fontSize:'16px', color: '#108ee9' }" />
|
||||
|
||||
</a-table>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
// 操作列的key或dataIndex
|
||||
const actionKey = 'action'
|
||||
// 保存localStorage中的后缀
|
||||
const saveSuffix = ':JTable'
|
||||
// 拿到column的key
|
||||
const getKey = col => col.key || col.dataIndex
|
||||
// 所有JTable的缓存key
|
||||
const J_TABLE_KEYS = 'J_TABLE_KEYS'
|
||||
|
||||
/**
|
||||
* 以下 表格为实际要展示的表、配置表为设置冻结和隐藏的表
|
||||
* 执行流程梳理
|
||||
* 1.mounted挂载时去拿配置
|
||||
* 1.1.从localStorage取历史配置:取到直接进入2 没取到就进1.2
|
||||
* 1.2.从父组件获取columns初始化配置 并存储到localStorage
|
||||
*
|
||||
* 2.拿到配置后
|
||||
* 2.1.watch进行监听配置,然后生成 配置表格的数据,再调用setResultColumns来更新表格
|
||||
* 2.2.将columns根据配置转换成resultColumns进行渲染表格
|
||||
*
|
||||
* 3.修改配置触发changeSetting来对配置进行更新,更新后watch会监听到跳转2如此循环
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'JTable',
|
||||
props: {
|
||||
tableKey: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
// 配置表的样式
|
||||
settingStyle: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({ width: '300px' })
|
||||
},
|
||||
// 配置表的scroll
|
||||
settingScroll: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({ y: 300 })
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// 设置表格
|
||||
settingColumns: [
|
||||
{ title: '列名', dataIndex: 'title', align: 'center', ellipsis: true, width: 150 },
|
||||
{ title: '隐藏', dataIndex: 'hide', align: 'center', ellipsis: true, width: 60, scopedSlots: { customRender: 'hide' } },
|
||||
{ title: '冻结', dataIndex: 'freeze', align: 'center', ellipsis: true, width: 60, scopedSlots: { customRender: 'freeze' } }
|
||||
],
|
||||
settingDataSource: [],
|
||||
settingColumnsObj: { hide: [], freeze: [] }, // 本地存储的配置对象
|
||||
resultColumns: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
slots () {
|
||||
const slots = []
|
||||
for (const column of this.columns) {
|
||||
if (column.scopedSlots && column.scopedSlots.customRender) {
|
||||
slots.push(column.scopedSlots.customRender)
|
||||
}
|
||||
}
|
||||
return slots
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 配置列改变,将配置转换成配置表格数据
|
||||
settingColumnsObj: {
|
||||
deep: true, // 深度监听
|
||||
immediate: true, // 挂载先执行一次
|
||||
handler () {
|
||||
const dataSource = []
|
||||
this.columns.forEach(col => {
|
||||
const tempKey = getKey(col)
|
||||
// 操作栏不可配置
|
||||
if (tempKey === actionKey) {
|
||||
return
|
||||
}
|
||||
// hideSettingColumn: true 可以让不显示字段控制
|
||||
if (col.hideSettingColumn) {
|
||||
return
|
||||
}
|
||||
dataSource.push({
|
||||
title: col.title, // 用于显示的字段
|
||||
key: tempKey, // 用于存储的字段
|
||||
hide: this.settingColumnsObj.hide.includes(tempKey), // 是否隐藏
|
||||
freeze: this.settingColumnsObj.freeze.includes(tempKey), // 是否冻结
|
||||
disabledHide: col.disabledHide, // 禁用隐藏
|
||||
disabledFreeze: col.disabledFreeze // 禁用冻结
|
||||
})
|
||||
})
|
||||
this.settingDataSource = dataSource
|
||||
this.setResultColumns()
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 将父组件的columns进行处理:增加设置列按钮
|
||||
* 冻结列要有width,否则会有问题,建议使用minWidth,scroll.x要大于所有列width的和
|
||||
*/
|
||||
setResultColumns () {
|
||||
// 深度克隆,防止直接修改父组件数据
|
||||
const columns = cloneDeep(this.columns)
|
||||
// 设置按钮插槽配置
|
||||
const settingOption = {
|
||||
scopedSlots: {
|
||||
filterDropdown: 'settingDropdown',
|
||||
filterIcon: 'settingIcon',
|
||||
customRender: 'action'
|
||||
}
|
||||
}
|
||||
const findActionIndex = columns.findIndex(col => col && (getKey(col) === actionKey))
|
||||
// 如果找到操作栏,就把设置加到操作栏上
|
||||
if (findActionIndex !== -1) {
|
||||
// 添加设置插槽配置,并固定右侧
|
||||
Object.assign(columns[findActionIndex], settingOption, { fixed: 'right' })
|
||||
} else {
|
||||
// 如果没有找到操作栏,就把最后列加上设置插槽配置
|
||||
Object.assign(columns[columns.length - 1], settingOption)
|
||||
}
|
||||
// 最后过滤掉需要隐藏的字段,按定位进行排序
|
||||
const startArr = [] // 冻结左侧的列
|
||||
const midArr = [] // 没有冻结的列
|
||||
const endArr = [] // 冻结右侧的列(只能是action,暂时不能自定义固定右侧)
|
||||
columns.forEach(col => {
|
||||
const key = getKey(col)
|
||||
const fixed = this.settingColumnsObj.freeze.includes(key)
|
||||
col.hide = this.settingColumnsObj.hide.includes(key)
|
||||
col.fixed = key === actionKey ? 'right' : fixed
|
||||
if (!col.hide) {
|
||||
// 如果没有宽度就取minWidth(不添加原数据的width属性,这里只对需要固定的minWidth生效)
|
||||
const minWidth = col.width || col.minWidth
|
||||
switch (col.fixed) {
|
||||
case true:
|
||||
case 'left':
|
||||
startArr.push({ ...col, width: minWidth })
|
||||
break
|
||||
case 'right':
|
||||
endArr.push({ ...col, width: minWidth })
|
||||
break
|
||||
default:
|
||||
midArr.push(col)
|
||||
}
|
||||
}
|
||||
})
|
||||
// 更新父组件的数据,将排序后的进行渲染
|
||||
this.$emit('update:columns', columns)
|
||||
this.resultColumns = [...startArr, ...midArr, ...endArr]
|
||||
},
|
||||
/**
|
||||
* 配置表中复选框改变状态的事件
|
||||
* @param text 修改前的状态
|
||||
* @param type 隐藏还是冻结
|
||||
* @param record 当前行数据
|
||||
*/
|
||||
changeSetting (text, type, record) {
|
||||
const checked = !text // text是点击前的状态,取反就是要修改的状态
|
||||
console.log('修改了配置', checked, type, record)
|
||||
// 修改当前行配置
|
||||
record[type] = !checked
|
||||
// 勾选就添加,取消就删除
|
||||
if (checked) {
|
||||
this.settingColumnsObj[type].push(record.key)
|
||||
} else {
|
||||
this.settingColumnsObj[type].splice(this.settingColumnsObj[type].findIndex(item => item === record.key), 1)
|
||||
}
|
||||
this.saveSetting()
|
||||
/**
|
||||
* 弹框消失问题 冻结列会导致dom结构改变而从局部更新丢失弹框
|
||||
* 情况1:原本显示没有冻结列,新增第一个冻结列
|
||||
* 情况2:原本有且只剩一个冻结列,取消最后一个冻结列
|
||||
* 解决方案,刷新前获取dom,刷新后再次获取,如果获取不一致就触发点击事件点开弹框
|
||||
*/
|
||||
const beforeIsFixed = !!this.$refs.table.$el.querySelector('.ant-table-fixed-left')
|
||||
this.$nextTick(() => {
|
||||
const afterIsFixed = !!this.$refs.table.$el.querySelector('.ant-table-fixed-left')
|
||||
// console.log(beforeIsFixed, afterIsFixed)
|
||||
if (beforeIsFixed !== afterIsFixed) {
|
||||
this.$refs.settingBtn.$el.click()
|
||||
}
|
||||
})
|
||||
},
|
||||
// 初始化配置,从columns里获取
|
||||
initSetting () {
|
||||
const hide = []
|
||||
const freeze = []
|
||||
this.columns.forEach(col => {
|
||||
const key = getKey(col)
|
||||
// hide属性控制隐藏
|
||||
if (col.hide) {
|
||||
hide.push(key)
|
||||
}
|
||||
// fixed冻结到左侧
|
||||
if (col.fixed === true || col.fixed === 'left') {
|
||||
freeze.push(key)
|
||||
}
|
||||
})
|
||||
this.settingColumnsObj = { hide, freeze }
|
||||
this.saveSetting()
|
||||
},
|
||||
// 配置保存到本地
|
||||
saveSetting () {
|
||||
// 获取所有的jtable缓存的key数组(用于清除缓存,没有就初始化数组)
|
||||
const jTableKeys = Vue.ls.get(J_TABLE_KEYS) || []
|
||||
const saveKey = this.tableKey + saveSuffix
|
||||
// 如果不在数组里面就追加进去
|
||||
if (!jTableKeys.includes(saveKey)) {
|
||||
jTableKeys.push(saveKey)
|
||||
}
|
||||
Vue.ls.set(J_TABLE_KEYS, jTableKeys, 7 * 24 * 60 * 60 * 10)
|
||||
Vue.ls.set(saveKey, this.settingColumnsObj, 7 * 24 * 60 * 60 * 10)
|
||||
},
|
||||
// 清除本地的配置(当前的JTable)
|
||||
clearSetting () {
|
||||
this.settingColumnsObj = { hide: [], freeze: [] }
|
||||
Vue.ls.remove(this.tableKey + saveSuffix)
|
||||
this.$message.success('成功清除当前JTable的缓存!')
|
||||
},
|
||||
// 清除所有缓存
|
||||
clearAllCacheSetting () {
|
||||
// 获取到之后遍历删除,最后把keys数组删除
|
||||
const jTableKeys = Vue.ls.get(J_TABLE_KEYS)
|
||||
jTableKeys && jTableKeys.forEach(key => {
|
||||
Vue.ls.remove(key)
|
||||
})
|
||||
Vue.ls.remove(J_TABLE_KEYS)
|
||||
this.$message.success('成功清除全局JTable的缓存!')
|
||||
},
|
||||
},
|
||||
mounted () {
|
||||
const settingColumnsObj = Vue.ls.get(this.tableKey + saveSuffix)
|
||||
// 第一次进页面或清空缓存进行初始化
|
||||
if (settingColumnsObj) {
|
||||
this.settingColumnsObj = settingColumnsObj
|
||||
} else {
|
||||
this.initSetting()
|
||||
}
|
||||
},
|
||||
created () {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang='less' scoped>
|
||||
</style>
|
||||
Reference in New Issue
Block a user