对表单自由排序,决定哪些列显示隐藏,能保存设置过的操作
效果图
使用页,操作列dataIndex要设置为action,forKey必需是唯一的
用的vue2版的antdesign vue写的样式,想用其它的ui框架可以自行修改样式
<customTable :tableHeadList="tableHead" @customTableUpde="customTableUpde" forKey="dataIndex"></customTable>import customTable from "./components/customTable.vue" //引入
const tableHead = [{title: '序号',dataIndex: 'index',scopedSlots: { customRender: 'index' },width: 60,align: 'center'},{title: '产品图片',dataIndex: 'pic',scopedSlots: { customRender: 'pic' },ellipsis: true,align: 'center'},{title: '产品名称',dataIndex: 'goodsName',ellipsis: true,align: 'center'},{title: '原价',dataIndex: 'oriPrice',ellipsis: true,width: 80,align: 'center'},{title: '现价',dataIndex: 'price',ellipsis: true,width: 80,align: 'center'},{title: '产品分类',dataIndex: 'goodsCategoryName',ellipsis: true,align: 'center'},{title: '状态',dataIndex: 'publishStatusName',scopedSlots: { customRender: 'publishStatusName' },ellipsis: true,align: 'center'},{title: '操作',dataIndex:'action',// fixed: 'right',scopedSlots: { customRender: 'action' },width: 140,align: 'center'}
];
export default {components: { customTable },data() {return {tableHeadList:[],//表单使用的头部数据}},methods:{//更新表格头部customTableUpde(e){this.tableHeadList = e;},}
customTable组件
<template><div><a-popover title="" v-model="customVisible" trigger="click" placement="topRight"><a-icon type="setting" style="font-size:20px;" @click="waiClick" /><template slot="content"><div class="customBigBox"><div :id="customId" :ref="customId" v-if="headList&&headList.length>0" class="customBox"><div v-for="(item,index) in headList" :key="item[forKey]" ><div class="customEach" v-if="item.dataIndex != operation"><a-checkbox@change="customCheckChange($event,index)" style="width: 20px;height: 20px;margin-right:4px;":checked="item.ischecked"v-model="item.ischecked" ></a-checkbox><div class="customText">{{item.title}}</div><a-tooltip placement="top" title="固定到左侧"><a-icon type="vertical-right" class="customFixed" @click="addFixed('left',index)" :style="{'margin-left':'4px','color': (item[fixedName]&&item[fixedName]=='left')?'#1890ff':'#777'}" /></a-tooltip><a-tooltip placement="top" title="固定到右侧"><a-icon type="vertical-left" class="customFixed" @click="addFixed('right',index)" :style="{'margin-left':'10px','color': (item[fixedName]&&item[fixedName]=='right')?'#1890ff':'#777'}" /></a-tooltip></div></div></div><div class="customNodata" v-else>暂无数据</div></div><div class="customAction"><a-button @click="reset" style="margin-right: 16px;">重置</a-button><a-button type="primary" @click="save">保存</a-button></div></template></a-popover></div>
</template><script>//拖拽插件,官网https://sortablejs.com/import Sortable from 'sortablejs'export default{data(){return {customVisible:false,headList:[],//数据el:null,//列表元素}},props:{//组件idcustomId:{type:String,default:'customCustomTable'},//指定的key字段forKey:{type:String,default:'dataIndex'},//表头数据tableHeadList:{type:Array,default:[]},//表头数据缓存IDcustomCacheId:{type:String,default:'customCustomTable'},//左右固定属性名fixedName:{type:String,default:'fixed'},//操作列对应的名字operation:{type:String,default:'action'}},mounted(){ let data = JSON.parse(JSON.stringify(this.tableHeadList));this.dealList(data);this.$nextTick(() =>{this.initDrag()this.watchList()})},methods:{//重置reset(){window.localStorage.removeItem(this.customCacheId)let data = JSON.parse(JSON.stringify(this.tableHeadList))this.dealList(data)this.$message.success('重置成功')this.customVisible = false;},//保存save(){//加个排序this.headList.map((res,index) =>{res.issort = index+1;})window.localStorage.setItem(this.customCacheId,JSON.stringify(this.headList))console.log('保存',this.headList)this.$message.success('保存成功')this.customVisible = false;},//处理初始化数据dealList(e){const that = this;let old = window.localStorage.getItem(this.customCacheId);if(old){//有旧数据,新旧合并,保留旧数据的操作let newlist = [];let oldlist = JSON.parse(old);console.log('拿取',oldlist)e.map(res =>{let resul = oldlist.filter(ve => ve[that.forKey] == res[that.forKey]);if(resul&&resul.length>0){let currentobj = res;currentobj.issort = resul[0].issort;currentobj.ischecked = resul[0].ischecked;currentobj[that.fixedName] = resul[0][that.fixedName];newlist.push(currentobj)}else{res.issort = 9999;res.ischecked = true;if(!res[that.fixedName]){res[that.fixedName] = '';}newlist.push(res)}})//排序let sortlist = newlist.sort((a,b) =>{let value1 = a['issort'];let value2 = b['issort'];return value1 - value2;})this.headList = sortlist;}else{e.map(res =>{res.issort = 9999;res.ischecked = true;if(!res[that.fixedName]){res[that.fixedName] = '';}})this.headList = e;}this.outputData()},//重新初始化拖拽waiClick(){if(!this.el){setTimeout(() =>{this.$nextTick(() =>{this.initDrag()})},100)}},//初始化拖拽initDrag(){const that = this;const el = document.getElementById(this.customId);if(el){this.el = el;// 创建拖拽实例new Sortable(el, {group:this.customId+'group',animation: 150,sort: true,onEnd: (e) => {//拖拽回调that.dealDragList(e.newIndex,e.oldIndex)}});}},//监听数据变化watchList(){this.unwatch = this.$watch('tableHeadList',function(newlist,oldlist){let data = JSON.parse(JSON.stringify(newlist));this.dealList(data)},{deep:true //深度监听})},//处理拖拽后的数据dealDragList(newIndex,oldIndex){if(newIndex == oldIndex)return;let data = JSON.parse(JSON.stringify(this.headList));const currentRow = data[oldIndex];data.splice(oldIndex, 1);//删除原位置数据data.splice(newIndex, 0, currentRow); this.headList = data;this.outputData()},//选择customCheckChange(e,index){this.headList[index].ischecked = e.target.checked;this.outputData()},//固定项addFixed(e,index){if(e == 'left'){if(!this.headList[index][this.fixedName] || this.headList[index][this.fixedName] == 'right'){this.headList[index][this.fixedName] = 'left';}else{this.headList[index][this.fixedName] = '';}}else{if(!this.headList[index][this.fixedName] || this.headList[index][this.fixedName] == 'left'){this.headList[index][this.fixedName] = 'right';}else{this.headList[index][this.fixedName] = '';}}this.outputData()},//输出数据outputData(e){let data = JSON.parse(JSON.stringify(this.headList));//将符合要求的返回let newdata = data.filter(res => res.ischecked);this.$emit('customTableUpde',newdata)console.log('新返回的数组',data)},},beforeDestroy(){//移除监听if(this.unwatch){this.unwatch()}}}
</script><style scoped>
.customBigBox{width:270px;
}
.customBox{width:100%;height: 280px;overflow-y: scroll;background-color: #fff;border-radius: 6px;padding-right: 5px;box-sizing: border-box;
}
.customEach{width: 100%;height: 34px;user-select: none;list-style-type: none;color: #333;padding-left: 10px;font-size: 14px;display: flex;justify-content: space-between;align-items: center;background-color: #fff;
}
.customText{flex: 1;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;
}
.customText:hover{color: #1890ff;
}
.customFixed{font-size: 16px;
}
.customFixed:hover{color: #1890ff;
}
.customAction{width: 100%;height: 60px;display: flex;justify-content: flex-end;align-items: center;padding: 5px 14px;box-sizing: border-box;
}
.customNodata{width: 100%;height: 100%;display: flex;align-items: center;justify-content: center;font-size: 14px;color: #999;
}
</style>