vue3中el-table表头筛选

效果如下,可以勾选表头进行隐藏,也可以对表头进行拖动排序
在这里插入图片描述
index主界面

<script>
let tempHead = [];
const showFilter = ref<boolean>(false);
let tableHeadList = ref<TableHeadItem[]>([
  { prop: "displayId", label: "编号", visible: true, sortable: true, isVis: true },
  { prop: "status", label: "1", visible: true, sortable: false, isVis: true },
  // { prop: 'approveOpnion', label: '审批意见', visible: false },
  { prop: "playType", label: "2", visible: true, sortable: false, isVis: true },
  { prop: "ownerRoleId", label: "3", visible: true, sortable: true, isVis: true },
  { prop: "approvalName", label: "4", visible: true, sortable: true, isVis: true },
  { prop: "startTime", label: "5", visible: true, sortable: true, isPx: 350, isVis: true },
  { prop: "airCraftName", label: "6", visible: true, sortable: false, isPx: 300, isVis: true },
  { prop: "airspaceInfos", label: "7", visible: true, sortable: false, isVis: true },
  { prop: "createTime", label: "8", visible: true, sortable: true, isPx: 200, isVis: true },
]);

const openFilter = () => {
  let tbLists = JSON.parse(localStorage.getItem("taskTableHead") || "[]");
  if (tbLists.length !== 0) {
    tableHeadList.value = tbLists;
    tempHead = tbLists;
  } else {
    tempHead = tableHeadList.value;
  }
  showFilter.value = !showFilter.value;
};
const updateColumns = (val) => {
  localStorage.setItem("taskTableHead", JSON.stringify(val));
  nextTick(() => {
    tableHeadList.value = val;
    showFilter.value = false;
  });
};

watchEffect(() => {
  let tbLists = JSON.parse(localStorage.getItem("taskTableHead") || "[]");
  tempHead = tableHeadList.value;
  if (tbLists.length !== 0) {
    tableHeadList.value = tbLists;
    tempHead = tbLists;
  } else {
    tempHead = tableHeadList.value;
  }
});
// 关闭表头筛选组件
const cancelFilter = () => {
  showFilter.value = false;
};
const changeVisable = (val, item) => {
  tempList.value = tempList.value.map(i => {
    if (i.label === item.label) {
      return { ...i, visible: val }
    }
    return i
  })
}
</script>


<template>
 <div class="searchRight">
          <el-form-item class="newbtn">
            <div class="iconBtn" @click="handleExport">
              <img src="@/assets/imgs/planMonitor/download.png" alt="" />
            </div>
            <div class="iconBtn filterBtn" @click="openFilter">
              <img src="@/assets/imgs/planMonitor/set_up.png" alt="" />
            </div>
            <!-- 表头筛选组件 -->
          </el-form-item>
          <div class="filter" v-if="showFilter">
            <filterTable :tableHeadList="tempHead" @update-columns="updateColumns" @cancel-filter="cancelFilter" />
          </div>
        </div>
</template>

filterTable

<script setup lang="ts">
import draggable from 'vuedraggable'
defineOptions({ name: 'FilterTable' })
interface TableHeadItem {
  id?: number | string
  visible: boolean
  label: string
  prop: string
  sortable?: boolean
  width?: number | string
  isPx?: number
}
const props = defineProps({
  tableHeadList: {
    type: Array as () => TableHeadItem[],
    default: () => []
  }
})
const nameList = ref<TableHeadItem[]>([])
const tempList = ref<TableHeadItem[]>([])
watch(() => props.tableHeadList, (val) => {
  if(val.length !== 0) {
    nameList.value = val.map(item => ({ ...item }))
    tempList.value = val.map(item => ({ ...item }))
  }
}, { immediate: true })

const emit = defineEmits(['updateColumns', 'cancelFilter'])
const changeVisable = (val, item) => {
  tempList.value = tempList.value.map(i => {
    if (i.label === item.label) {
      return { ...i, visible: val }
    }
    return i
  })
}

const confirmFn = () => {
  nameList.value = tempList.value.map(item => ({ ...item }))
  emit('updateColumns', nameList.value)
}

const cacelFn = () => {
  emit('cancelFilter')
}

</script>
<template>
  <div class="filterContainer">
    <div class="filterWrap">
      <draggable v-model="tempList" handle=".icon" animation="200" item-key="id">
        <template #item="{ element }">
          <div class="opreatItem" v-if="element.isVis">
            <div class="icon"></div>
            <el-checkbox :label="element.label" :value="element.visible" :checked="element.visible" @change="changeVisable($event, element)" />
          </div>
        </template>
      </draggable>
    </div>
    <div class="btnBox">
      <el-button class="cancel" link @click="cacelFn">取 消</el-button>
      <el-button class="confirm" link @click="confirmFn">确 定</el-button>
    </div>
  </div>
</template>
<style lang="scss" scoped>
.filterContainer {
  width: px(280);
  height: px(394);
  border-radius: px(5);
  border: px(1) solid #404d59;

  .filterWrap {
    height: px(338);
    overflow: auto;
    padding: px(18) 0;
  }

  .opreatItem {
    display: flex;
    align-items: center;
    padding: 0 px(18);
  }
  .opreatItem:hover {
    background: rgba(247, 247, 247, 0.1);
  }
  .icon {
    width: px(10);
    height: px(16);
    background-image: url('@/assets/imgs/planMonitor/checked.png');
    background-size: 100% 100%;
    cursor: crosshair;
    margin-right: px(15);
  }
  :deep(.el-checkbox__label) {
    width: px(84);
    height: px(20);
    font-family:
      PingFangSC,
      PingFang SC;
    font-weight: 400;
    font-size: px(14);
    color: #ffffff;
    line-height: px(20);
    text-align: left;
    font-style: normal;
  }
  .btnBox {
    height: px(55);
    display: flex;
    justify-content: flex-end;
    padding: 0 px(24);
    border-top: px(1) solid rgba(117, 183, 251, 0.5);

    .confirm {
      width: px(38);
      font-family:
        PingFangSC,
        PingFang SC;
      font-weight: 400;
      font-size: px(14);
      color: #75b7fb;
      line-height: px(20);
      text-align: left;
      font-style: normal;
    }

    .cancel {
      width: px(38);
      font-family:
        PingFangSC,
        PingFang SC;
      font-weight: 400;
      font-size: px(14);
      color: #999999;
      line-height: px(20);
      text-align: right;
      font-style: normal;
    }
  }
}
</style>

draggable

<template>
  <el-text type="info" size="small"> 拖动左上角的小圆点可对其排序 </el-text>
  <VueDraggable
    :list="formData"
    :force-fallback="true"
    :animation="200"
    handle=".drag-icon"
    class="m-t-8px"
    item-key="index"
  >
    <template #item="{ element, index }">
      <div
        class="mb-4px flex flex-col gap-4px border border-gray-2 border-rounded rounded border-solid p-8px"
      >
        <!-- 操作按钮区 -->
        <div
          class="m--8px m-b-4px flex flex-row items-center justify-between p-8px"
          style="background-color: var(--app-content-bg-color)"
        >
          <el-tooltip content="拖动排序">
            <Icon
              icon="ic:round-drag-indicator"
              class="drag-icon cursor-move"
              style="color: #8a909c"
            />
          </el-tooltip>
          <el-tooltip content="删除">
            <Icon
              icon="ep:delete"
              class="cursor-pointer text-red-5"
              v-if="formData.length > 1"
              @click="handleDelete(index)"
            />
          </el-tooltip>
        </div>
        <!-- 内容区 -->
        <slot :element="element" :index="index"></slot>
      </div>
    </template>
  </VueDraggable>
  <el-tooltip :disabled="limit < 1" :content="`最多添加${limit}个`">
    <el-button
      type="primary"
      plain
      class="m-t-4px w-full"
      :disabled="limit > 0 && formData.length >= limit"
      @click="handleAdd"
    >
      <Icon icon="ep:plus" /><span>添加</span>
    </el-button>
  </el-tooltip>
</template>

<script setup lang="ts">
// 拖拽组件
import VueDraggable from 'vuedraggable'
import { usePropertyForm } from '@/components/DiyEditor/util'
import { any, array } from 'vue-types'
import { propTypes } from '@/utils/propTypes'
import { cloneDeep } from 'lodash-es'

// 拖拽组件封装
defineOptions({ name: 'Draggable' })

// 定义属性
const props = defineProps({
  // 绑定值
  modelValue: array<any>().isRequired,
  // 空的元素:点击添加按钮时,创建元素并添加到列表;默认为空对象
  emptyItem: any<unknown>().def({}),
  // 数量限制:默认为0,表示不限制
  limit: propTypes.number.def(0)
})
// 定义事件
const emit = defineEmits(['update:modelValue'])
const { formData } = usePropertyForm(props.modelValue, emit)

// 处理添加
const handleAdd = () => formData.value.push(cloneDeep(props.emptyItem || {}))
// 处理删除
const handleDelete = (index: number) => formData.value.splice(index, 1)
</script>

<style scoped lang="scss"></style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值