vue elementUI table 多页选中 回显的处理逻辑

2023-01-12  本文已影响0人  八妹sss
效果
image.png

代码

<template>
  <div class="lesson-main">
    <section class="lesson-body">
      <section class="lesson-body-left">
        <div class="filter-box">
          <span class="search-input-box">
            <el-input
              v-model="keyword"
              placeholder="请输入关键词搜索"
              prefix-icon="el-icon-search">
            </el-input>
          </span>
        </div>
        <div class="table-wrapper">
          <el-table class="table-border"
            ref="lessonTableRef"
            :data="lessonList"
            :row-key="(row)=>{ return row.classId}"
            @select="handleSelectionChange"
            @select-all="handleAllChange">
            <el-table-column
              width="80"
              type="selection"
              :reserve-selection="true">
            </el-table-column>
            <el-table-column prop="lessonTitle" label="名称" min-width="200">
              <template slot-scope="scope">
                <div class="lesson-info">
                  <p class="icon_course"></p>
                  <p class="title">{{ scope.row.classTitle }}</p>
                </div>
              </template>
            </el-table-column>
            <el-table-column prop="duration" label="时长" min-width="120">
              <template slot-scope="scope">{{ scope.row.duration | handleDuration }}</template>
            </el-table-column>
            <el-table-column prop="" label="过期时间" min-width="120">
              <template slot-scope="scope">{{scope.row.expireTime ? scope.row.expireTime.slice(0, 10) : '-'}}</template>
            </el-table-column>
          </el-table>
          <div class="table-page">
            <p class="all-btn"
              :class="{
                disabled: !this.count
              }"
              @click="handleSelectAll()">全部筛选结果</p>
            <el-pagination
              style="text-align: right"
              background
              :total="count"
              :current-page="page"
              :page-size="pageSize"
              :page-sizes="pageSizesG"
              @size-change="handleSizeChange"
              @current-change="handleCurrentChange"
              layout="sizes, prev, pager, next">
            </el-pagination>
          </div>
        </div>
      </section>
      <section class="lesson-body-right">
        <div class="choose-header">
          <p class="text">已选择:{{chooseLessonList.length}}/{{count}}</p>
          <p class="close-btn"
            @click="handleClearAll()">清除所有</p>
        </div>
        <div class="choose-wrapper">
          <ul class="lesson-list draggable-list">
            <li class="lesson-item lesson-drag-btn"
              v-for="(info, i) in chooseLessonList"
              :key="`lesson${info.classId}`">
              <p class="icon_course"></p>
              <p class="title">{{info.classTitle}}</p>
              <p class="icon_close"
                @click.stop="handleClear(i)"></p>
            </li>
          </ul>
        </div>
      </section>
    </section>
    <section class="lesson-footer">
      <newElButton
        width='80px'
        btnType='cancel'
        @handleClick='handleLessonCancel()'
        >取消</newElButton>
      <newElButton
        class='ml20'
        width='80px'
        @handleClick='handleLessonSave()'
        >确定</newElButton>
    </section>
  </div>
</template>
<script>
import { getLessonList } from '@/api'

import Sortable from "sortablejs";
import newElButton from '@/components/elUI/newElButton'
export default {
  components: {
    newElButton
  },
  props: {
    selectList: {
      type: Array
    }
  },
  data () {
    return {
      keyword: '',
      count: 0,
      page: 1,
      pageSize: 10,
      lessonList: [], // 
      echoList: [], // 收集回显用的数据
      chooseLessonList: [], // 实际保存的数据
    }
  },
  methods: {
    // 单项选择:打勾或取消
    handleSelectionChange (selected, row) {
      if (!this.echoList.find(info => info.classId === row.classId)) {
        // 回显数据里没有本条,把这条加进来(选中)
        this.echoList.push(row)
      } else {
        // 回显数据里有本条,把这条删除(取消选中)
        this.echoList.forEach((info, index) => {
          if (info.classId === row.classId) {
            this.echoList.splice(index, 1)
          }
        })
      }
      // 这里用于收集实际需要的数据数组
      this.chooseLessonList = this.echoList;
    },
    // 全选、取消全选(原理同上面的单选)
    handleAllChange (selected) {
      if (selected.length > 0) {
        // 多页同时选中时,先清除当前页数据
        this.lessonList.forEach((item) => {
          this.echoList.forEach((info, index) => {
            if (info.classId == item.classId) {
              this.echoList.splice(index, 1);
            }
          });
        });
        // 再记录选中的数据
        selected.forEach((item) => {
          if (!this.echoList.find(info => info.classId == item.classId)) {
            this.echoList.push(item);
          }
        });
      } else {
        // 数据为空代表取消全选,清除当前页所有数据
        this.lessonList.forEach((item) => {
          this.echoList.forEach((info, index) => {
            if (info.classId == item.classId) {
              this.echoList.splice(index, 1);
            }
          });
        });
      }
      // 这里用于收集实际需要的数据数组
      this.chooseLessonList = this.echoList;
    },
    // 全选、取消全选
    handleSelectAll () {
      if (!this.count) {
        return
      }
      this.$refs.lessonTableRef.toggleAllSelection()
    },
    // 清除所有
    handleClearAll () {
      this.echoList = []
      // 这里用于收集实际需要的数据数组
      this.chooseLessonList = this.echoList
      this.$refs.lessonTableRef.clearSelection();
    },
    // 清除单个
    handleClear (i) {
      let delRow = this.chooseLessonList.splice(i, 1)
      // 回显数据也要移除被删数据
      this.echoList.forEach((info, index) => {
        if (info.classId == delRow[0]?.classId) {
          this.echoList.splice(index, 1)
        }
      })
      this.handleSelectTable()
    },
    handleLessonSave () {
      this.$emit('save', this.chooseLessonList)
    },
    handleLessonCancel () {
      this.$emit('cancel')
    },
    handleSizeChange(val) {
      this.page = 1
      this.pageSize = val
      this.fetchLessonList()
    },
    handleCurrentChange (val) {
      this.page = val
      this.fetchLessonList()
    },
    fetchLessonList() {
      let params = {
        keyword: this.keyword,
        currentPage: this.page,
        pageSize: this.pageSize
      }
      params = this.filterSearchInfo(params)
      getLessonList(params).then(res => {
        if (res.data.code === 200) {
          let data = res.data.data
          if (data) {
            this.count = +data.total
            if (data.list && data.list.length) {
              this.lessonList = data.list
            } else {
              this.lessonList = []
            }
            this.$nextTick(() => {
              this.handleSelectTable()
            })
          }
        }
      }).catch(err => {
        this.handleError(err)
      })
    },
    handleSelectTable () {
      // 所有取消选中
      this.$refs.lessonTableRef.clearSelection()
      // 表格回显选中
      if (this.echoList && this.echoList.length) {
        this.echoList.forEach(info => {
          this.lessonList.forEach(row => {
            if (row.classId == info.classId) {
              this.$refs.lessonTableRef.toggleRowSelection(row, true)
            }
          })
        })
      }
    },
    // 开启拖拽(未生效需要找原因)
    initRowDrop () {
      const tbody = document.querySelector(".draggable-list");
      const _this = this;
      Sortable.create(tbody, {
        handle: ".lesson-drag-btn",
        onEnd({ newIndex, oldIndex }) {
          if (newIndex === oldIndex) return false;
          const currRow = _this.chooseLessonList.splice(oldIndex, 1)[0];
          _this.chooseLessonList.splice(newIndex, 0, currRow);
        },
      });
    }
  },
  filters: {
    handleDuration (val) {
      if (!val) {
        return '--'
      }
      val = Number(val)
      var hour = Math.floor(val / 3600)
      var min = Math.ceil((val % 3600) / 60)
      if (hour > 0 && min > 0) {
        return `${hour}小时${min}分`
      } else if (hour > 0 && min === 0) {
        return `${hour}小时`
      } else {
        return `${min}分`
      }
    }
  },
  watch: {
    chooseLessonList () {
      this.$nextTick(() => {
        this.initRowDrop()
      })
    }
  },
  created () {
    this.echoList = JSON.parse(JSON.stringify(this.selectList))
    this.chooseLessonList = JSON.parse(JSON.stringify(this.selectList))
    this.fetchLessonList()
  },
}
</script>
<style lang="stylus" scoped>
.lesson-main
  width 100%
  height calc(100vh - 55px)
  display flex
  flex-direction column
  position relative
  .lesson-body
    height calc(100% - 57px)
    display: flex
    .lesson-body-left
      width calc(100% - 258px)
      height 100%
      border-right 1px solid #E9EAED
      padded_box(border-box, 16px 20px)
      .filter-box
        width 100%
        display: flex
        align-items: center
      .table-wrapper
        width 100%
        height calc(100% - 48px)
        // display flex
        // flex-direction: column
        // justify-content: space-between
        margin-top 16px
        // .table-border.el-table
        //   flex none
        .lesson-info
          width 100%
          display: flex
          align-items: center
          .icon_course
            width 20px
            height 20px
            background: url('~assets/img/knowledge/icon_course@2x.png') no-repeat center/100%
          .title
            max-width calc(100% - 48px)
            height: 20px;
            line-height: 20px
            font-family:'PingFangSC-Regular';
            font-size: 14px;
            color: #5E5F66;
            margin:0 8px 0 4px
        .table-page
          display: flex
          justify-content: space-between
          align-items center
          .all-btn
            line-height 20px
            font-family: 'PingFangSC-Regular';
            font-size: 14px;
            color: #3377FE;
            padded_box(border-box, 4px 12px)
            cursor pointer
            margin-top 18px
            &.disabled
              cursor: not-allowed
    .lesson-body-right
      width 258px
      height 100%
      padded_box(border-box, 16px 20px)
      .choose-header
        width 100%
        display: flex
        justify-content: space-between
        align-items: center
        .text
          height: 20px;
          line-height 20px
          font-family: PingFangSC-Regular;
          font-size: 12px;
          color: #5E5F66;
        .close-btn
          height: 20px;
          line-height 20px
          font-family: PingFangSC-Regular;
          font-size: 12px;
          color: #9B9EA8;
          cursor pointer
      .choose-wrapper
        width 100%
        scroll()
        scroll-bar()
        height calc(100% - 36px)
        margin-top 16px
        .lesson-list
          display: flex
          flex-wrap: wrap
          .lesson-item
            display: flex
            align-items center
            height 32px
            line-height: 20px
            background: #F1F6FE
            padded_box(border-box, 6px 12px)
            border-radius: 4px
            margin 0 10px 10px 0
            cursor pointer
            .icon_course
              width 20px
              height 20px
              background: url('~assets/img/knowledge/icon_course@2x.png') no-repeat center/100%
            .title
              height: 20px;
              line-height: 20px
              font-family: 'PingFangSC-Regular';
              font-size: 12px;
              color: #303544;
              margin 0 12px 0 4px
            .icon_close
              width 16px
              height 16px
              background: url('~assets/img/icon_close@2x.png') no-repeat center/12px
              cursor: pointer
  .lesson-footer
    flex none
    text-align right
    padded_box(border-box, 12px 20px)
    border-top 1px solid #E9EAED
</style>
参考

原文地址:https://blog.csdn.net/Skty_ywh/article/details/126000082

上一篇 下一篇

猜你喜欢

热点阅读