table上下移动

demo1

<template>
  <div class="container">
    <div class="left">
      <draggable
        v-model="myArray"
        group="people"
        @start="drag = true"
        @end="drag = false"
        item-key="id"
      >
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
    <div class="right">
      <draggable
        v-model="myArray2"
        group="people"
        @start="drag = true"
        @end="drag = false"
        item-key="id"
      >
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
  </div>
</template>

<script>
import { defineComponent, reactive, toRefs } from "vue";
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    const data = reactive({
      drag: false,
      myArray: [
        { id: 1, name: "Jenny" },
        { id: 2, name: "kevin" },
        { id: 3, name: "lili" },
      ],
      myArray2: [
        { id: 1, name: "A" },
        { id: 2, name: "B" },
        { id: 3, name: "C" },
      ],
    });
    return { ...toRefs(data) };
  },
});
</script>

<style lang="less" scoped>
.container {
  display: flex;
  .left {
    background-color: #fff;
    width: 200px;
    height: 1000px;
    margin: 0 20px;
    padding: 20px;
    .left-drag {
      display: flex;
      flex-wrap: wrap;
      justify-content: space-between;
      min-height: 80px;
    }
  }
  .right {
    background-color: #fff;
    height: 1000px;
    width: 200px;
    padding: 20px;
    .right-drag {
      width: 410px;
      min-height: 80px;
      display: block;
    }
  }
  .item {
    height: 40px;
    border: 1px solid #e9e9e9;
    text-align: center;
    line-height: 40px;
   margin: 20px 0;
   background-color: rgb(242, 242, 242);
  }
}
</style>

demo2

<template>
  <div class="container">
    <div class="left">
      <draggable
        v-model="myArray"
        group="people"
        @end="onDragEnd"
        item-key="id"
      >
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
    <div class="right">
      <draggable
        v-model="myArray2"
        group="people"
        @end="onDragEnd"
        item-key="id"
      >
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
    <div class="right">
      <draggable
        v-model="myArray3"
        group="people"
        @end="onDragEnd"
        item-key="id"
      >
        <template #item="{ element }">
          <div class="item">{{ element.name }}</div>
        </template>
      </draggable>
    </div>
  </div>
</template>

<script>
import { defineComponent, reactive, toRefs } from "vue";
import draggable from "vuedraggable";

export default defineComponent({
  components: { draggable },
  setup() {
    const data = reactive({
      myArray: Array.from({ length: 10 }, (_, i) => ({ id: i + 1, name: `Jenny${i + 1}` })),
      myArray2: Array.from({ length: 10 }, (_, i) => ({ id: i + 11, name: `A${i + 1}` })),
      myArray3: Array.from({ length: 5 }, (_, i) => ({ id: i + 21, name: `C${i + 1}` })),
    });

    const totalItems = 25;
    const fixedArray3Size = 5;

    const onDragEnd = () => {
      balanceArrays(data.myArray, data.myArray2, data.myArray3);
    };

    const balanceArrays = (array1, array2, array3) => {
      // 确保 array3 的大小固定
      while (array3.length < fixedArray3Size) {
        // 从 array1 或 array2 中取出一个元素(优先从较大的数组中取)
        const sourceArray = array1.length >= array2.length ? array1 : array2;
        if (sourceArray.length > 0) {
          const [item] = sourceArray.splice(sourceArray.length - 1);
          array3.push(item);
        } else {
          // 理论上不应该发生,因为 totalItems 应该总是足够分配
          break;
        }
      }
      while (array3.length > fixedArray3Size) {
        // 将多余的元素放回 array1 或 array2(这里简单放回 array1,可以根据需要调整)
        const [item] = array3.splice(array3.length - 1);
        array1.push(item);
      }

      // 现在 array3 大小固定,重新分配 array1 和 array2
      const remainingItems = totalItems - fixedArray3Size;
      let combinedArray = [...array1, ...array2].sort((a, b) => a.id - b.id); // 按 id 排序

      // 重新分配元素,尽可能平均分配到 array1 和 array2
      const array1Length = Math.floor(remainingItems / 2); // 优先保证 array1 和 array2 长度接近
      const array2Length = remainingItems - array1Length;

      array1.length = 0;
      array1.push(...combinedArray.slice(0, array1Length));
      array2.length = 0;
      array2.push(...combinedArray.slice(array1Length));
    };

    return { ...toRefs(data), onDragEnd };
  },
});
</script>

<style lang="less" scoped>
.container {
  display: flex;
  .left, .right {
    background-color: #fff;
    width: 200px;
    height: 1000px;
    margin: 0 20px;
    padding: 20px;
    .item {
      height: 40px;
      border: 1px solid #e9e9e9;
      text-align: center;
      line-height: 40px;
      margin: 20px 0;
      background-color: rgb(242, 242, 242);
    }
  }
}
</style>

现实应用

<!-- 教务处  -->

<template>
    <div class="but">
        <el-button @click="mergeAndPrintArrays()" type="primary">保存数据</el-button>
        <el-button @click="restoration()" type="primary">数据还原</el-button>
    </div>
    <div class="container">
        <div class="left">
            <el-table :data="myArray" row-key="id" ref="table1" id="table1">
                <el-table-column prop="name" label="姓名"></el-table-column>
                <el-table-column prop="state" label="前台是否展示" width="90">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.states" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
                <el-table-column prop="state" label="是否作为搜索条件" width="120">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.state" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
            </el-table>

        </div>

        <div class="left">
            <el-table :data="myArray2" row-key="id" ref="table2" id="table2">
                <el-table-column prop="name" label="姓名"></el-table-column>
                <el-table-column prop="state" label="前台是否展示" width="90">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.states" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
                <el-table-column prop="state" label="是否作为搜索条件" width="120">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.state" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
            </el-table>

        </div>

        <div class="left">
            <el-table :data="myArray3" row-key="id" ref="table3" id="table3">
                <el-table-column prop="name" label="姓名"></el-table-column>
                <el-table-column prop="state" label="前台是否展示" width="90">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.states" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
                <el-table-column prop="state" label="是否作为搜索条件" width="120">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.state" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
            </el-table>

        </div>


        <div class="left">
            <el-table :data="myArray4" row-key="id" ref="table4" id="table4">
                <el-table-column prop="name" label="姓名"></el-table-column>
                <el-table-column prop="state" label="前台是否展示" width="90">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.states" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
                <el-table-column prop="state" label="是否作为搜索条件" width="120">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.state" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
            </el-table>

        </div>


        <div class="left">
            <el-table :data="myArray5" row-key="id" ref="table5" id="table5">
                <el-table-column prop="name" label="姓名"></el-table-column>
                <el-table-column prop="state" label="前台是否展示" width="90">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.states" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
                <el-table-column prop="state" label="是否作为搜索条件" width="120">
                    <template v-slot="scope">
                        <el-switch v-model="scope.row.state" @change="stateChanged(scope.row)" />
                    </template>
                </el-table-column>
            </el-table>

        </div>

    </div>

</template>

<script>
import Sortable from "sortablejs";
import webfield from "@/api/sys/webfield";
import notifyService from "@/api/notify/notifyService";
export default {
    data() {

        return {
            dataList: [],
            earchVisible: true,
            loading: false,
            myArray: [],
            myArray2: [],
            myArray3: [],
            myArray4: [],
            myArray5: [],
            userName: "",
            userNameF: "",
            companyDTO: '',
            ids: '',
            newtype: ''
        };
    },
    props: ["value1"],
    mounted() {
        this.refreshList();

    },
    async created() {
        var userInfo = this.$TOOL.data.get("USER_INFO");
        this.userName = userInfo.id;
        this.companyDTO = userInfo.companyDTO.id;
    },

    methods: {
        // 获取数据 初始化
        refreshList() {
            // this.newtype = JSON.parse(this.value1)
            // console.log(this.newtype, 'new11')
            this.loading = true;
            const params = {
                officeId: this.companyDTO,
                type: 1,
            };
            webfield.webfieldinit(params).then((data) => {
                this.dataList = JSON.parse(data.data.content)
                this.ids = data.data.id
                console.log(data, "disa")
                this.assignDataToArrays();
                this.loading = false;
            }).catch((error) => {
                console.error('Error fetching data:', error);
                this.loading = false;
            });
        },

        // 获取数据 平均分配
        assignDataToArrays() {
            this.myArray = [];
            this.myArray2 = [];
            this.myArray3 = [];
            this.myArray4 = [];
            this.myArray5 = [];

            // 计算每个数组应该分配的数据量
            const chunkSize = Math.ceil(this.dataList.length / 5);
            // 将 dataList 的数据平均分配到五个数组中
            for (let i = 0; i < this.dataList.length; i++) {
                if (i < chunkSize) {
                    this.myArray.push(this.dataList[i]);
                } else if (i < chunkSize * 2) {
                    this.myArray2.push(this.dataList[i]);
                } else if (i < chunkSize * 3) {
                    this.myArray3.push(this.dataList[i]);
                } else if (i < chunkSize * 4) {
                    this.myArray4.push(this.dataList[i]);
                } else {
                    this.myArray5.push(this.dataList[i]);
                }
            }

            this.initSortable();
        },

        initSortable() {
            const initSortableForTable = (tableRef, dataArray, num) => {
                const tbody = this.$refs[tableRef].$el.querySelector(".el-table__body-wrapper tbody");
                Sortable.create(tbody, {

                    onEnd: ({ newIndex, oldIndex, to, from, clone, pullMode, item }) => {
                        const totableid = to.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.id
                        const fromtableid = from.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.parentElement.id
                        //id映射
                        const tablemap = {
                            table1: this.myArray,
                            table2: this.myArray2,
                            table3: this.myArray3,
                            table4: this.myArray4,
                            table5: this.myArray5,
                        }
                        if (totableid == fromtableid) {
                            const currRow = dataArray.splice(oldIndex, 1)[0];
                            dataArray.splice(newIndex, 0, currRow);
                        } else {
                            //不一致 跨列拖动
                            const currRow = tablemap[fromtableid].splice(oldIndex, 1)[0];
                            // //向to添加一个元素
                            tablemap[totableid].splice(newIndex, 0, currRow);
                            //from table会少一列
                            if (tablemap[totableid][newIndex + 1]) {
                                //如果 to table 的下一行有数据 补充回fromtable的oldindx
                                tablemap[fromtableid].splice(oldIndex, 0, tablemap[totableid][newIndex + 1])
                                //得删除to table的数据
                                tablemap[totableid].splice(newIndex + 1, 1)
                            } else if (tablemap[totableid][newIndex - 1]) {
                                tablemap[fromtableid].splice(oldIndex, 0, tablemap[totableid][newIndex - 1])
                                //得删除to table的数据
                                tablemap[totableid].splice(newIndex - 1, 1)
                            } else {
                                console.error("前后都没有数据 无法补充")
                            }
                            // console.log(this.myArray, this.myArray2)

                        }

                    },
                    group: 'zhaoxin'
                });
            };

            initSortableForTable('table1', this.myArray);
            initSortableForTable('table2', this.myArray2);
            initSortableForTable('table3', this.myArray3);
            initSortableForTable('table4', this.myArray4);
            initSortableForTable('table5', this.myArray5);
        },
        //合并数组  保存数据
        mergeAndPrintArrays() {

            // console.log(JSON.parse(this.value1), 'oooooooooooo')
            // this.newtype = JSON.parse(JSON.stringify(this.options))[0].value

            this.newtype = JSON.parse(this.value1)
            // 合并三个数组
            const mergedArray = [...this.myArray, ...this.myArray2, ...this.myArray3, ...this.myArray4, ...this.myArray5];
            const news = JSON.stringify(mergedArray);
            this.loading = true;

            // 构建请求参数对象
            const params = {
                officeId: this.companyDTO,
                type: this.newtype,
                content: news,
                operatorId: this.userName,

            };

            const newparams = {
                officeId: this.companyDTO,
                type: this.newtype,
                content: news,
                operatorId: this.userName,
                id: this.ids
            };

            if (this.ids === '') {
                console.log('空啦')
                webfield.webfieldadd(params).then((response) => {
                    location.reload(true);
                    this.loading = false;
                }).catch((error) => {
                    console.error('Error fetching data:', error);
                    this.loading = false;
                });
            } else {
                console.log("不空")
                console.log(this.myArray, 'cuirow')
                webfield.webfieldadd(newparams).then((response) => {
                    location.reload(true);
                    this.loading = false;

                }).catch((error) => {
                    console.error('Error fetching data:', error);
                    this.loading = false;
                });
            }


        },
        // 控制显隐
        stateChanged(row) {
            const index = this.myArray.findIndex(item => item.id === row.id);
            console.log('Row index:', index);
            console.log('Row data:', row);
        },

        // 还原数据
        restoration() {
            this.loading = true;
            console.log(this.loading, 'loading'); // 修正了拼写错误,从 'loda' 改为 'loading'

            if (this.ids === '' || this.ids === undefined || this.ids === null) {
                console.log('kong ')
                alert('已经还原成最初的原始数据了!');
                this.loading = false; // 如果不需要刷新页面,可以在这里直接设置 loading 为 false
            } else {
                console.log(this.ids, 'konglllll ')
                webfield.webfielddel(this.ids).then((data) => {
                    console.log(data)
                    this.assignDataToArrays();
                    location.reload(true); // 仅在数据删除成功后刷新页面
                }).catch((error) => {
                    console.error('Error fetching data:', error);
                    this.loading = false; // 请求失败时设置 loading 为 false
                });
            }
        }
    },
};
</script>

<style lang="less" scoped>
.but {
    margin-bottom: 3rem;
}

.container {
    display: flex;
    margin-bottom: 50rem;

    .left,
    .right {
        background-color: #fff;
        width: 282px;
        height: 1000px;
        margin: 0 4px;
        padding: 0 -8px;


        .item {
            height: 40px;
            border: 1px solid #e9e9e9;
            text-align: center;
            line-height: 40px;
            margin: 20px 0;
            background-color: rgb(242, 242, 242);
        }
    }
}
</style>
相关推荐
银之夏雪14 分钟前
ESLint 深度解析:原理、规则与插件开发实践
java·前端·javascript
白嫖叫上我1 小时前
js删除嵌套数组对象中的某项,并重置其后的索引
前端·javascript
yinxiangzhongqing2 小时前
从vue源码解析Vue.set()和this.$set()
前端·javascript·vue.js
廖若星辰LTY2 小时前
uniapp 解决 H5 跨域问题
前端·javascript·uni-app·html5
青红光硫化黑2 小时前
前端基础之内置指令与自定义指令
前端·javascript
青红光硫化黑3 小时前
前端基础之收集表单数据
前端·javascript
GISer_Jing3 小时前
前端埋点项目从设计到实现详解
前端·javascript·react.js
幸运小圣3 小时前
模板字符串【ES6】
开发语言·javascript·es6
幸运小圣3 小时前
对象扩展【ES6】
前端·javascript·es6
陆沙5 小时前
D3.js-简单入门2-动态图表&交互操作
开发语言·javascript·交互