Vue实现表格数据拖动排序,多选置顶置地


前言

ant design + HTML原生表格 + draggable + vue-scroll 实现给表格数据排序并计算开始时间和结束时间且表格可滚动,效果图如下
当议题时长或者议题顺序发生变化时重新计算时间


一、html

<!-- 数字输入框 -->
<a-input-number id="inputNumber" v-model="form.topicTime" style="width: 40%;" :min="1" :max="10" @change="getTopicTime()" />分钟
<!-- 表格 -->
<table>
	<td style="border: 0px;">
		<tr>
			<td class="titleClass" style="width:60px;background: #fafafa;">
				<a-checkbox v-model="checkState" :indeterminate="indeterminate" @click="onCheckAllChange()" />
			</td>
			<td v-for="(item, index) in titleList" :key="index" class="titleClass" style="background: #fafafa;" :style="getTableWidth(index)">{{ item }}</td>
		</tr>
		<vue-scroll :ops="ops" :style="getStyle1()">
			<draggable v-model="dataSource" animation="500" force-fallback="true" :move="checkMove" @start="onStart" @end="onEnd" @change="getTopicTime()">
				<tr v-for="(item, index) in dataSource" :key="item.id" :class="rowClassName(index)">
					<td class="titleClass" style="width:60px">
						<a-checkbox v-model="item.isTrusted" @change="onChange(item)" />
					</td>
					<td class="titleClass" style="width:60px">{{ index +1 }}</td>
                	<td class="titleClass" style="width:200px">{{ item.topicName }}</td>
                	<td class="titleClass" style="width:100px">{{ item.partNumber }}</td>
					<td class="titleClass" style="width:100px">{{ item.topicType }}</td>
                	<td class="titleClass" style="width:100px">{{ item.specialGroup }}</td>
                	<td class="titleClass" style="width:100px">{{ item.meetingPurpose }}</td>
                	<td class="titleClass" style="width:100px">{{ item.fsPrincipal }}</td>
                	<td class="titleClass" style="width:100px">{{ item.ppPrincipal }}</td>
                	<td class="titleClass" style="width:100px">{{ item.materialGroup }}</td>
                	<td class="titleClass" style="width:100px">{{ item.startTime }}</td>
					<td class="titleClass" style="width:100px">{{ item.endTime }</td>
				</tr>
			</draggable>
		</vue-scroll>
	</td>
</table>
<a-space style="float: right;margin: 15px;" size="large">
	<a-button class="save" @click="topIndex()">置顶</a-button>
	<a-button @click="bottomIndex()">置底</a-button>
</a-space>

二、data

data() {
    return {
      drag: false,
      titleList: ['序号', '议题名称', '零件编号', '议题类型', '专业组', '上会目的', 'FS负责人', 'PP负责人', '材料组', '起始时间', '结束时间'],
      checkedList: [], // 选中的数据
      checkState: false, // 全选check选中状态
      indeterminate: false, // 非全选check选中状态
      ops: {
        vuescroll: {},
        scrollPanel: {},
        rail: {
          keepShow: true
        },
        bar: {
          hoverStyle: true,
          onlyShowBarOnScroll: false, // 是否只有滚动的时候才显示滚动条
          background: '#00519B', // 滚动条颜色
          opacity: 1, // 滚动条透明度
          'overflow-x': 'hidden'
        }
      },
      dataSource: [{ topicId: 1, topicName: '议题1', isTrusted: false },
        { topicId: 2, topicName: '议题2', startTime: '', endTime: '', isTrusted: false },
        { topicId: 3, topicName: '议题3', startTime: '', endTime: '', isTrusted: false },
        { topicId: 4, topicName: '议题4', startTime: '', endTime: '', isTrusted: false },
        { topicId: 5, topicName: '议题5', startTime: '', endTime: '', isTrusted: false },
        { topicId: 6, topicName: '议题6', startTime: '', endTime: '', isTrusted: false }],
      form: {
        topicTime: 3
      },
    }
  },

三、methods

	// 根据选中数据数量来改变 全选check样式
	onChange(e) {
      console.log(e)
      let m = 0 // m 为选中的数据数量
      for (let n = 0; n < this.dataSource.length; n++) {
        if (this.dataSource[n].isTrusted === true) {
          m++
        }
      }
      // m = 0 时 显示空白
      // 0 < m < 全部数量 显示方块
      // m = 全部数量 显示对号
      if (m < this.dataSource.length && m > 0) {
        this.checkState = false
        this.indeterminate = true
      } else if (m === 0) {
        this.checkState = false
        this.indeterminate = false
      } else if (m === this.dataSource.length) {
        this.checkState = true
        this.indeterminate = false
      }
    },
    // 全选方法
    onCheckAllChange() {
      if (this.checkedList.length < this.dataSource.length) {
        for (let n = 0; n < this.dataSource.length; n++) {
          this.dataSource[n].isTrusted = true
          // 这里是深复制,如果直接等于,在下面清空时会清空原数据
          this.checkedList = JSON.parse(JSON.stringify(this.dataSource))
        }
      } else {
        for (let n = 0; n < this.dataSource.length; n++) {
          this.dataSource[n].isTrusted = false
          this.checkedList = []
        }
      }
    },
    // 不同列不同宽度
    getTableWidth(index) {
      if (index === 0) {
        return 'width: 60px;'
      } else if (index === 1) {
        return 'width: 200px;'
      } else {
        return 'width: 100px;'
      }
    },
    // 根据页面分辨率自适应表格高度
    getStyle1() {
      const fullWidth = document.documentElement.clientWidth
      if (fullWidth >= 1680) {
        return 'width:100%;height:300px;'
      } else if (window.screen.width < 1680) {
        return 'width:100%;height:200px;'
      }
    },
    // 表格斑马线
    rowClassName(index) {
      let className = 'light-row'
      if (index % 2 === 1) className = 'dark-row'
      return className
    },
    // 开始拖拽事件
    onStart() {
      this.drag = true
    },
    // 拖拽结束事件
    onEnd() {
      this.drag = false
      console.log('end..............')
    },
    // 设置拖动放置规则
    checkMove(evt) {
      console.log(evt)
      return true
    },
    // 置顶
    topIndex() {
      var that = this
      // 将所有 isTrusted 为 true 的数据存入 checkedList 中,并删除
      this.dataSource.forEach(function (item){
        if (item.isTrusted === true) {
          item.isTrusted = false
          that.checkedList.push(item)
        }
      })
      // 将checkedList中的数据从dataSource中删除
      let diff = [...this.dataSource]
      for (let i = 0, len = this.dataSource.length; i < len; i++ ) {
        let flag = false
        for (let j = 0, length = this.checkedList.length; j < length; j++) {
          if (this.dataSource[i].topicId === this.checkedList[j].topicId) {
            flag = true
          }
        }
        if (flag) {
          diff.splice(diff.findIndex(item => item.topicId === this.dataSource[i].topicId), 1)
        }
      }
      this.dataSource = diff
      // 将checkedList中的数据插入dataSource前面
      for (let i = this.checkedList.length -1; i >= 0; i--) {
        this.dataSource.unshift(this.checkedList[i])
      }
      this.checkedList = []
      this.getTopicTime()
    },
    // 置地
    bottomIndex(arr,index) {
      var that = this
      // 将所有 isTrusted 为 true 的数据存入 checkedList 中,并删除
      this.dataSource.forEach(function (item){
        if (item.isTrusted === true) {
          item.isTrusted = false
          that.checkedList.push(item)
        }
      })
      // 将checkedList中的数据从dataSource中删除
      let diff = [...this.dataSource]
      for (let i = 0, len = this.dataSource.length; i < len; i++ ) {
        let flag = false
        for (let j = 0, length = this.checkedList.length; j < length; j++) {
          if (this.dataSource[i].topicId === this.checkedList[j].topicId) {
            flag = true
          }
        }
        if (flag) {
          diff.splice(diff.findIndex(item => item.topicId === this.dataSource[i].topicId), 1)
        }
      }
      this.dataSource = diff
      // 将checkedList中的数据插入dataSource后面
      for (let i = 0; i < this.checkedList.length; i++) {
        this.dataSource.push(this.checkedList[i])
      }
      this.checkedList = []
      this.getTopicTime()
    },
    // 计算议题开始结束时间
    getTopicTime() {
      var that = this
      let date = new Date(2021, 6, 25, 8, 0, 0)  // 传入的会议开始日期,时间
      let startDate = '' // 议题开始的时间
      let endDate = '' // 议题结束的时间
      let hour = '' // 议题所在小时
      let startMinute = '' // 议题开始分钟
      let endMinute = '' // 议题结束分钟
      this.dataSource.forEach(function (item, index){
        startDate = new Date(date.setMinutes(date.getMinutes()))
        endDate = new Date(date.setMinutes(date.getMinutes() + that.form.topicTime))
        hour = date.getHours() < 10 ? '0' + date.getHours() : date.getHours()
        // console.log('hour:' + hour)
        startMinute = startDate.getMinutes() < 10 ? '0' + startDate.getMinutes() : startDate.getMinutes()
        endMinute = endDate.getMinutes() < 10 ? '0' + endDate.getMinutes() : endDate.getMinutes()
        // console.log('startMinute:' + startMinute)
        // console.log('endMinute:' + endMinute)
        item.startTime = hour + ':' + startMinute
        item.endTime = hour + ':' + endMinute
        // console.log(item.startTime)
        // console.log(item.endTime)
      })
    },

大功告成!剩下的样式什么的不用看也行,就是还原ant表格的样式

四、CSS

<style scoped>
  /*选中样式*/
  .chosen {
    border: solid 1px #3089dc !important;
  }
  /*定义要拖拽元素的样式*/
  .titleClass {
    padding: 16px 16px;
    border: 0px solid #fff;
    font-size: 12px;
    font-weight: 500;
  }
  .chackClass {
    position: relative;
    top: 0;
    left: 0;
    display: block;
    width: 16px;
    height: 16px;
    background-color: #fff;
    border: 1px solid #ddd;
    border-radius: 2px;
    border-collapse: separate;
  }
  .light-row {
    background-color: #fff;
  }
  .dark-row {
    background-color: #F8FBFE;
  }
  table.itxst {
    border-collapse: collapse;
    margin-bottom: -6px;
    padding-bottom: 0px;
    min-width: 6px;
    background: #fafafa;
  }
  table.itxst th {
  border: #ddd solid 1px;
  padding: 8px;
  background-color: #dedede;
  }
  table.itxst td {
  border: #ddd solid 1px;
  padding: 8px;
  background-color: #ffffff;
  }
  table.itxst tr {
   cursor: pointer;
  }
  table.itxst td.move:hover {
   cursor: move;
  }
</style>

总结

记得下载引入组件
npm install vuedraggable --save
npm install vue-scroll --save
main.js中:
import vuescroll from "vuescroll";//引入vuescroll
import "vuescroll/dist/vuescroll.css";//引入vuescroll样式
Vue.use(vuescroll);
。。。大概吧,记不住了
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值