前言
最近叼毛产品 让写个需求,动态展示表格字段,要求动态根据用户习惯保存,下次进页面展示以前的,还能再次选择。
思考
- 让用户选择展示那些字段
- 保存db
- 进页面先查询db 然后根据table 字段属性过滤
平时vue页面写的表格类型字段
columnsData: [
{
title: '状态',
width: 120,
align: 'center',
key: 'a',
render: (h, params) => {
const row = params.row
return 'xxxxxx'
},
filters: [
{
label: 'xxx',
value: 1
},
{
label: 'xxxx',
value: 2
},
{
label: 'xxxx',
value: 3
}
],
filterMultiple: true,
filterRemote(value) {
this.queryForm.a = value.join(',')
this.search()
}
},
{
title: 'xxxx',
width: 100,
align: 'center',
key: 'b',
filters: [
{
label: 'xxx',
value: 1
},
{
label: 'xxx',
value: 2
}
],
filterMultiple: false,
filterRemote(value) {
this.queryForm.b = value[0]
this.search()
},
render: (h, params) => {
const row = params.row
if (row.payType === 1) {
return 'xxx'
}
return 'xxx'
}
},
{title: '时间', width: 120, key: 'c', sortable: 'custom'},
在页面加载时候会吧次数据加载到内存,我们用次定义的字段,展示列表,让用户选择,需要展示的那些字段。
核心数据已打码
选择的数据保存到db即可 这里需要注意的是 根据自己需求保存,是保存字段还是保存数组下标。
- 保存字段,可能会有重复字段(定义重复字段)
- 保存下标,表格属性head可能会被修改(中间肯能添加,导致保存数据和元数据不一致)
这里建议保存字段
实现
表设计
这里我们根据用户手机号保存,当然其他条件自己可以扩展。
考虑到别的表格字段可能也需要,便于扩展,将次写成组件,易于其他页面扩展。
第一步 查询后台配置
有配置则展示配置字段,否则展示原有字段
http查询后台字段 (这里需要注意的是查询时候必须先查询此配置,再查询后台表格数据,必须同步查 )
代码就不展示了
一个查询即可
这里content 我用, 号拼接保存的字段
如 a,b,c,d,e 然后用此和原有的字段进行对比
查询
data(){
initColumnList: [],
backupInitColumnList: [],
tableFiledForm: {
show: false,
tableType: 5,
originTableFiledList: [],
columnList: []
}
},
created() {
this.deepInit().then(() => {
this.getTableFiled(5).then(() => {
this.search()
})
})
}
查询配置
这里后台代码就省略了,也没啥写的、
getXXXXXXXXX(type) {
return new Promise((resolve, reject) => {
this.tableFiledForm.columnList = this.initColumnList
let params = {
method: 'get',
url: this.$context + '/table/getTable?=' + type
}
this.$http(params)
.then(res => {
if (res.data.code === '200' && res.data.data !== null && res.data.data !== '') {
let columnsDataArray = this.initColumnList
let originTableFiledList = res.data.data.content.split(',')
let originTableFiledListElement = originTableFiledList.filter(x => x !== '')
if (originTableFiledListElement.length === 0) {
this.columnsData = this.backupInitColumnList
return
}
this.columnsData = this.tablefiledJS.sortAndFilter(columnsDataArray, originTableFiledListElement)
}
})
resolve()
})
},
查询完之后进行原有的展示字段备份
这里需要注意的是,原有的字段,我们可能会定义函数,拷贝的时候需要将函数也一同拷贝了。
//深拷贝
deepInit() {
return new Promise((resolve, reject) => { //同步
// copy original columnsData to tableFiledForm
for (let i = 0; i < this.columnsData.length; i++) {
let columnsDatum = this.columnsData[i]
let deepCopyList1 = this.tablefiledJS.deepCopy(columnsDatum)
let deepCopyList2 = this.tablefiledJS.deepCopy(columnsDatum)
this.initColumnList.push(deepCopyList1) //备份字段 在没查询到的时候 使用原字段
this.backupInitColumnList.push(deepCopyList2) //备份字段
}
resolve()
})
},
选中后(或者进页面根据选中的字段,进行过滤字段)
var deepCopy = function deepCopy(obj) {
let result = obj
if (typeof obj === 'object' && obj !== null) {
result = Object.prototype.toString.call(obj) === '[object Array]' ? [] : {}
for (let prop in obj) {
result[prop] = this.deepCopy(obj[prop])
}
}
return result
}
const operation = '操作'
const selection = 'selection'
var sortAndFilter = function sortAndFilter(columnsDataArray, originTableFiledList) {
let array = []
let sortArray = []
for (let i = 0; i < columnsDataArray.length; i++) {
let columnsDataObj = columnsDataArray[i]
if (columnsDataObj.type === selection) {
array.push(columnsDataObj)
}
if (!columnsDataObj.key || columnsDataObj === '') {
continue
}
for (let ii = 0; ii < originTableFiledList.length; ii++) {
if (columnsDataObj.key === originTableFiledList[ii]) {
array.push(columnsDataObj)
continue
}
}
if (columnsDataObj.title === operation) {
array.push(columnsDataObj)
}
}
if (array.len !== 0) {
console.log('sort befor : ')
console.log(array)
var jsonAarry = array.filter(x => x.title === operation)
if (array.length <= originTableFiledList.length / 2) {
for (let i = array.length - 1; i >= 0; i--) {
if (array[i].type === selection) {
continue
}
delete array[i].width
}
if (jsonAarry.length > 0) {
delete jsonAarry[0].fixed
}
}
let selectionJson = array.filter(x => x.type === selection)
if (selectionJson.length > 0) {
sortArray.push(selectionJson[0])
}
for (let k = 0; k < originTableFiledList.length; k++) {
for (let p = 0; p < array.length; p++) {
if (array[p].key === originTableFiledList[k]) {
if (!sortArray.find(x => x.key === originTableFiledList[k])) {
sortArray.push(array[p])
continue
}
}
}
}
let json = array.filter(x => x.title === operation)
if (json.length > 0) {
sortArray.push(json[0])
}
this.columnsData = sortArray
console.log('after sort : ')
console.log(sortArray)
}
return sortArray
}
export default {
sortAndFilter,
deepCopy
}
表格页面 引入组件
<tableFiled
:show="tableFiledForm.show" // 是否展示
:columnList="tableFiledForm.columnList" //原字段 组件页面点击选择
:tableType="tableFiledForm.tableType" //类型 那个表格的类型
@closeConfirmOrder="confirmTableFildeForm" // 关闭
@getSearch="getTableFiled(5)" //保存回调查询
></tableFiled>
组件关闭和展示
//组件弹框 显示和关闭
confirmTableFildeForm() {
this.tableFiledForm.show = false
},
disabledTableFiled() {
this.tableFiledForm.show = true
}
table页面点击展示选择字段的按钮
<span @click="disabledTableFiled"> 点击打开页面选择,字段</span>
组件代码
<template>
<Modal
v-model="show"
:mask-closable="false"
:closable="false"
:columnList="columnList"
:tableType="tableType"
:originTableFiledList="originTableFiledList"
width="800"
:title="modeMapper[mode]">
<Form ref="addTableFieldFormLimit" :model="addVehicleOwnerForm">
<Row>
<div style="height: 300px;">
<template>
<div style="width: 74%;display: inline-block;height: 280px;overflow-y:scroll;">
<Checkbox-group v-model="addVehicleOwnerForm.disabledGroup" @on-change="watchCheck()">
<div v-for=" (it,index) in addVehicleOwnerForm.tableFieldList" style="display: inline-block;margin-left: 5px;margin-top: 2px;width: 120px;">
<Checkbox :label="index"> <span style="margin-left: 5px"> </span>{{it.title}}</Checkbox></div>
<br v-if="(index + 1) % 4 ===0">
</Checkbox-group>
</div>
<div style="width: 25%;display: inline-block;height: 300px;overflow-y:scroll;">
<h5 style="margin-left: 5px;margin-top: 2px;">当前已选字段</h5>
<div style="margin-top: 20px;">
<div id="example1" class="list-group col" >
<div class="list-group col" v-for=" (it,index) in addVehicleOwnerForm.disabledGroupNameList" style="margin-top:10px;">
<span style="margin-top: 20px;margin-left:10px"><img src="../../../images/tdimg.png" width="13xp" height="13px" > </span><span style="margin-left: 15px;"> {{it.title}}</span> <span style="margin-left: 10px;" @click="deleteVoid(index)"><img src="../../../images/gb.png" width="13xp" height="13px" ></span>
</div>
</div>
</div>
</div>
</template>
</div>
</Row>
</Form>
<!-- 自定义footer -->
<div slot="footer">
<Button @click="cancelHandle">取消</Button>
<Button type="primary" @click="addVehicleOwnerHandle">确定</Button>
</div>
</Modal>
</template>
<script>
//拖拽排序的 插件
import Sortable from 'sortablejs'
export default {
data() {
return {
addVehicleOwnerForm: {
disabledGroup: [], //选中的组件
tableFieldList: [] // 所有字段(表格原有的字段,展示列表 让用户点击选择)
},
disabledGroupNameList: [],
sortable: null,
modeMapper: {
add: '设置列表显示字段',
edit: '设置列表显示字段'
},
loading: false
}
},
props: {
//组件传进来的值
show: {type: Boolean, require: true},
mode: {type: String, default: 'add'},
originTableFiledList: {type: Array, default: []},
tableType: {type: Number},
columnList: {type: Array, default: []}
},
methods: {
filterTableFieldMethod() {
console.log('this.columnList : ')
console.log(this.columnList)
let columnsDataArray = this.columnList
let array = []
for (let i = 0; i < columnsDataArray.length; i++) {
let columnsDataObj = columnsDataArray[i]
//过滤操作,默认表格展示的操作 和 选择框 这里我进行了过滤
if (columnsDataObj.type === 'selection' || columnsDataObj.title === '操作') {
continue
}
array.push(columnsDataObj)
}
this.addVehicleOwnerForm.tableFieldList = array
// this.addVehicleOwnerForm.disabledGroup = [0, 1]
// 查询后台是否被选中
let checked = this.savedFieldId()
this.getDisabledGroupNameList()
this.addVehicleOwnerForm.disabledGroup = checked
console.log(' save index ')
console.log(this.addVehicleOwnerForm.disabledGroup)
this.addVehicleOwnerForm.tableType = this.tableType
this.initSortable()
},
savedFieldId() {
let checked = []
let params = {
method: 'get',
url: this.$context + '/table/getTable?tableType=' + this.tableType
}
this.$http(params)
.then(res => {
if (res.data.code === '200' && res.data.data !== null && res.data.data !== '') {
let originTableFiledList = res.data.data.content.split(',')
// saved field
for (let j = 0; j < originTableFiledList.length; j++) {
for (let i = 0; i < this.addVehicleOwnerForm.tableFieldList.length; i++) {
if (originTableFiledList[j] === this.addVehicleOwnerForm.tableFieldList[i].key) {
checked.push(i)
}
}
}
}
})
return checked
},
/**
* @description 取消
*/
cancelHandle() {
this.$emit('closeConfirmOrder', []) // 关闭模态窗
},
deleteVoid(val) {
if (this.addVehicleOwnerForm.disabledGroup.length === 1) {
this.addVehicleOwnerForm.disabledGroup = []
this.addVehicleOwnerForm.disabledGroupNameList = []
return
}
this.addVehicleOwnerForm.disabledGroup.splice(val, 1)
},
watchCheck() {
if (this.addVehicleOwnerForm.disabledGroup.length === 0) {
this.addVehicleOwnerForm.disabledGroupNameList = []
}
},
// 初始化拖拽 拖拽排序
initSortable() {
const el = document.querySelector('#example1')
this.sortable = new Sortable(el, {
animation: 150,
ghostClass: 'blue-background-class',
direction: 'horizontal',
forceFallback: true,
onEnd: ({newIndex, oldIndex}) => {
var oldArrayIndex = 0
var newArrayIndex = 0
for (let i = 0; i < this.addVehicleOwnerForm.disabledGroup.length; i++) {
if (newIndex === i) {
newArrayIndex = i
}
if (oldIndex === i) {
oldArrayIndex = i
}
}
var oldobj = this.addVehicleOwnerForm.disabledGroup[oldArrayIndex]
var newobj = this.addVehicleOwnerForm.disabledGroup[newArrayIndex]
this.addVehicleOwnerForm.disabledGroup[oldIndex] = newobj
this.addVehicleOwnerForm.disabledGroup[newIndex] = oldobj
}
})
},
/**
* @description 确定
*/
addVehicleOwnerHandle() {
if (this.addVehicleOwnerForm.disabledGroup.length === 0) {
this.$Message.info('未选择使用默认字段')
this.sendHttp('')
return
}
if (this.addVehicleOwnerForm.disabledGroup.length < 4) {
this.$Message.info('至少选择4个!')
return
}
if (this.addVehicleOwnerForm.disabledGroup.length === this.addVehicleOwnerForm.tableFieldList.length) {
this.$Message.info('不能全选')
return
}
let tableFieldStr = ''
for (let disabledGroupElement of this.addVehicleOwnerForm.disabledGroup) {
for (let j = 0; j < this.addVehicleOwnerForm.tableFieldList.length; j++) {
if (disabledGroupElement !== j) {
continue
}
tableFieldStr += ',' + this.addVehicleOwnerForm.tableFieldList[j].key
}
}
console.log(this.addVehicleOwnerForm.disabledGroup)
console.log(tableFieldStr)
this.sendHttp(tableFieldStr)
},
sendHttp(tableFieldStr) {
// 配置请求参数
let params = {
method: 'post',
url: '127.0.0.1:9090table/add',
data: {
'tableType': this.tableType,
'content': tableFieldStr
}
}
// 发送请求
this.$http(params)
.then(res => {
this.$Message.success(res.data.msg) // 提示成功
this.$emit('closeConfirmOrder', []) // 关闭模态窗
this.$emit('getSearch') // 关闭模态窗
})
},
getDisabledGroupNameList() {
let array = []
for (let disabledGroupElement of this.addVehicleOwnerForm.disabledGroup) {
for (let j = 0; j < this.addVehicleOwnerForm.tableFieldList.length; j++) {
if (disabledGroupElement !== j) {
continue
}
array.push(this.addVehicleOwnerForm.tableFieldList[j])
}
}
this.addVehicleOwnerForm.disabledGroupNameList = array
}
},
watch: {
columnList(val) {
if (val.length) {
this.filterTableFieldMethod()
}
},
'addVehicleOwnerForm.disabledGroup': function (val) {
if (val.length !== 0) {
this.getDisabledGroupNameList()
}
}
},
created() {
this.filterTableFieldMethod()
}
}
</script>
演示
选择字段
保存后table展示字段
最后
- 注意深拷贝,原先字段定义的函数也需要拷贝过来
- 拖拽排序组件
- 可参考
http://www.sortablejs.com/index.html https://www.cnblogs.com/moqiutao/p/6423754.html https://blog.csdn.net/wsln_123456/article/details/108595514
|