123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- <template>
- <table class="table drag-table">
- <colgroup>
- <col v-if="dragEnable" width="20" />
- <col v-for="column in columns" :key="column.prop" :width="column.width" />
- </colgroup>
- <thead>
- <tr>
- <th v-if="dragEnable"></th>
- <th v-for="column in columns" :key="column.prop">
- {{ column.label }}
- </th>
- </tr>
- </thead>
- <tbody
- class="drag-table-tbody"
- @drop.prevent
- @dragover.prevent="dragOver($event)"
- @dragleave.prevent
- >
- <tr
- v-for="row in tableData"
- :key="row.$key"
- :id="row.$key"
- :class="[
- 'drag-table-row',
- {
- 'after-drop': row.$key === curDropRow.$key && isDragDown,
- 'before-drop': row.$key === curDropRow.$key && !isDragDown,
- },
- ]"
- draggable="false"
- @dragstart="($event) => dragStart($event, row)"
- @dragend.prevent="dragEnd"
- >
- <td
- v-if="dragEnable"
- class="drag-handle"
- @mousedown.stop="dragHandleMousedown"
- @mouseup.stop="dragHandleMouseup"
- >
- <i class="el-icon-more"></i>
- </td>
- <td
- v-for="column in columns"
- :key="column.prop"
- :class="column.className"
- >
- <slot :name="column.prop" v-bind:row="row">
- {{ row[column.prop] }}
- </slot>
- </td>
- </tr>
- </tbody>
- </table>
- </template>
- <script>
- import { randomCode } from "@/plugins/utils";
- export default {
- name: "drag-table",
- props: {
- data: {
- type: Array,
- default() {
- return [];
- },
- },
- columns: {
- type: Array,
- default() {
- // {label,prop,width?}[]
- return [];
- },
- },
- sortField: {
- type: String,
- default: "sortNum",
- },
- dragEnable: {
- type: Boolean,
- default: true,
- },
- },
- data() {
- return {
- tableData: [],
- curDragRow: {},
- curDropRow: {},
- dragStartPageY: null,
- isDragDown: false,
- };
- },
- methods: {
- buildData(val) {
- if (!val) {
- this.tableData = [];
- return;
- }
- this.tableData = val.map((item, index) => {
- return {
- ...item,
- $index: index + 1,
- $key: randomCode(),
- };
- });
- },
- getRelateElement(dom) {
- let element = null;
- let parentNode = dom;
- while (!element && !parentNode.className.includes("drag-table-tbody")) {
- if (!element && parentNode["id"]) {
- element = parentNode;
- } else {
- parentNode = parentNode.parentNode;
- }
- }
- return element;
- },
- getSiblingRow(targetKey, offset) {
- const pos = this.tableData.findIndex((row) => row.$key === targetKey);
- return this.tableData[pos + offset] || null;
- },
- dragStart(e, row) {
- if (!this.dragEnable) return;
- this.dragStartPageY = e.pageY;
- this.curDragRow = row;
- },
- dragOver(e) {
- if (!this.dragEnable) return;
- // console.log(e.target);
- this.isDragDown = e.pageY > this.dragStartPageY;
- if (e.target.className.includes("drag-table-tbody")) {
- this.curDropRow = this.isDragDown
- ? this.tableData.slice(-1)[0]
- : this.tableData[0];
- return;
- }
- const elementDom = this.getRelateElement(e.target);
- if (!elementDom) return;
- const targetKey = elementDom.id;
- this.curDropRow = this.getSiblingRow(targetKey, 0);
- },
- dragEnd(e) {
- if (!this.dragEnable) return;
- if (this.curDragRow.id === this.curDropRow.id || !this.curDropRow) return;
- // 往下:target上一个位置
- // 往上:target下一个位置
- this.moveElementToElement({
- curRow: this.curDragRow,
- toRow: this.curDropRow,
- isDragDown: this.isDragDown,
- });
- e.target.setAttribute("draggable", false);
- this.curDragRow = {};
- this.curDropRow = {};
- this.dragStartPageY = null;
- this.isDragDown = false;
- },
- moveElementToElement({ curRow, toRow, isDragDown }) {
- const curPos = this.tableData.findIndex(
- (row) => row.$key === curRow.$key
- );
- this.tableData.splice(curPos, 1);
- const toPos = this.tableData.findIndex((row) => row.$key === toRow.$key);
- const offset = isDragDown ? 1 : 0;
- this.tableData.splice(toPos + offset, 0, curRow);
- this.tableData.forEach((row, index) => {
- row[this.sortField] = index + 1;
- row.$index = index + 1;
- });
- this.$emit("sort-change", this.tableData);
- },
- dragHandleMousedown(e) {
- const elementDom = this.getRelateElement(e.target);
- elementDom.setAttribute("draggable", true);
- },
- dragHandleMouseup(e) {
- const elementDom = this.getRelateElement(e.target);
- elementDom.setAttribute("draggable", false);
- },
- },
- watch: {
- data: {
- handler(val) {
- this.buildData(val);
- },
- immediate: true,
- },
- },
- };
- </script>
|