自由定义表单table组件(antdesign版)

对表单自由排序,决定哪些列显示隐藏,能保存设置过的操作
效果图
在这里插入图片描述
使用前先安装拖拽的插件,插件官网https://sortablejs.com/

npm install sortablejs --save

保留自定义表单缓存,清除其他缓存

/**
 * 清除所有localStorage
 */
export function removeAll() {
  //保留表单自定义的缓存项
  const specialCacheKey = 'customTableCatch';
  // 获取缓存的所有键
  const keys = Object.keys(localStorage);
  // 清除除了特定键以外的所有缓存
  keys.forEach(key => {
    if (key !== specialCacheKey) {
      localStorage.removeItem(key);
    }
  });

console.log('所有的缓存',keys)
  // return window.localStorage.clear();
}

使用页,操作列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:{
         //组件id
         customId:{
            type:String,
            default:'customCustomTable'
         },
         //指定的key字段
         forKey:{
            type:String,
            default:'dataIndex'
         },
         //表头数据
         tableHeadList:{
            type:Array,
            default:[]
         },
         //表头数据缓存ID,必传且每个页面传的不能相同,否则会冲突
         customCacheId:{
            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(){
            let all = JSON.parse(window.localStorage.getItem('customTableCatch'));
            console.log('重置表单',all)
            //有该缓存
            if(all&&all[this.customCacheId]){
               all[this.customCacheId] = '';//清空原有的
               window.localStorage.setItem('customTableCatch',JSON.stringify(all));//重新替换
            }
            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;
            })
            let all = JSON.parse(window.localStorage.getItem('customTableCatch'));
            if(!all){
               all = {};
            }
            all[this.customCacheId] = this.headList;//在对应位置加上数据
            window.localStorage.setItem('customTableCatch',JSON.stringify(all));//缓存
            console.log('保存',this.headList)
            this.$message.success('保存成功')
            this.customVisible = false;
         },
         //处理初始化数据
         dealList(e){
           const that = this;
           let all = JSON.parse(window.localStorage.getItem('customTableCatch'));
           let oldlist = '';
           if(all&&all[this.customCacheId]){
               oldlist = all[this.customCacheId];//拿取缓存数据
           }
           if(oldlist){
               //有旧数据,新旧合并,保留旧数据的操作
               let newlist = [];
               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>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值