vue.draggable 拖拽
文档:
vue.draggable中文文档 - itxst.com
参考:
Vue.jsvuedraggable插件安装与使用教程-CSDN博客
vue使用vuedraggable实现嵌套多层拖拽排序功能_vue.js_脚本之家
https://zhuanlan.zhihu.com/p/611811323
安装vuedraggable插件
npm i vuedraggable
<template>
<div class="left-allocate">
<!-- 拖拽部分开始 -->
<div class="drag-distribute-cls">
<div class="waitloadcar-list">
<draggable
v-show="waitLoadList.length > 0"
v-model="waitLoadList"
forceFallback="true"
group="vehicle-station"
animation="0"
:sort="false"
touchStartThreshold="0px"
dragClass="dragClass"
ghostClass="ghostClass"
chosenClass="chosenClass"
@start="onStart"
@end="onEnd">
<transition-group>
<div v-for="(vehicle, index) in waitLoadList" :key="index" :class="['vehicle-cls', vehicle.type === 'pallet' ? 'pallet-cls' : 'shelves-cls']">
<van-image
v-if="vehicle.type === 'shelves'"
width="48"
height="48"
:src="require('../src/assets/logo.png')"
/>
<van-image
v-if="vehicle.type === 'pallet'"
width="68"
height="48"
:src="require('../src/assets/logo.png')"
/>
<van-image
v-if="vehicle.type === 'cage'"
width="64"
height="64"
:src="require('../src/assets/logo.png')"
/>
<span class="vehicle-name">{
{ vehicle.name }}</span>
</div>
</transition-group>
</draggable>
<div v-show="waitLoadList.length === 0" class="vehicle-cls shelves-cls">无未分配载具</div>
</div>
<h4 class="header">放置位置列表</h4>
<div class="workposition-list">
<draggable
v-show="workpositionList.length"
v-model="workpositionList"
group="vehicle-station"
:disabled="false"
:sort="false"
handle=".mover-butuodong">
<transition-group>
<div v-for="(workpos, index) in workpositionList"
:key="index"
class="workpos-cls"
@mousemove="workposMove"
:data-actindex="index"
:style="{ marginRight: index % 2 ? '16px': '0px'}">
<h5 :style="{ marginTop: index % 2 !== 0 ? '48px' : '16px' }">{
{ index % 2 === 0 ? '放置位置' + workpos.station : ''}}</h5>
<!-- 托盘 -->
<div class="pallet-icon" v-if="workpos.type === 'pallet'">
<van-image
width="68"
height="48"
:src="require('../src/assets/logo.png')"
/>
<span class="sel-text">{
{ workpos.name }}</span>
</div>
<!-- 移动货架 -->
<div class="shelves-icon" v-if="workpos.type === 'shelves'">
<div class="left-shelves">
<van-image
width="48"
height="48"
:src="require('../src/assets/logo.png')"
/>
<span class="sel-text">{
{ workpos.name }}</span>
</div>
</div>
<!-- 笼车 -->
<div class="shelves-icon" v-if="workpos.type === 'cage'">
<div class="left-shelves">
<van-image
width="48"
height="48"
:src="require('../src/assets/logo.png')"
/>
<span class="sel-text">{
{ workpos.name }}</span>
</div>
</div>
<!-- 放置位置空 -->
<div class="shelves-icon" v-if="workpos.type === 'kong'">
<div class="left-kong">空</div>
</div>
</div>
</transition-group>
</draggable>
<div v-show="workpositionList.length === 0" class="workpos-kong">
无可分配放置位置
</div>
</div>
</div>
</div>
</template>
<script>
import draggable from 'vuedraggable'
export default {
name: 'DraggerName',
components: {
draggable
},
data () {
return {
waitLoadList: [
// { type: 'shelves', name: '测试11', station: '', vehicleId: '1', amount: 4000.00 },
{ type: 'pallet', name: '测试两个15', station: '', vehicleId: '5', amount: 4000.00 },
{ type: 'shelves', name: '测试16', station: '', vehicleId: '6', amount: 4000.00 },
{ type: 'shelves', name: '测试17', station: '', vehicleId: '7', amount: 4000.00 },
{ type: 'pallet', name: '测试两个18', station: '', vehicleId: '8', amount: 4000.00 }
],
// 数据的一些约定:托盘(type: 'pallet')放在放置位置的第一个;type: 'fu' 不显示
workpositionList: [
{ type: 'kong', name: '', station: '1', storageId: '1' },
{ type: 'kong', name: '', station: '1', storageId: '2' },
{ type: 'kong', name: '', station: '2', storageId: '3' },
{ type: 'kong', name: '', station: '2', storageId: '4' },
{ type: 'kong', name: '', station: '3', storageId: '5' },
{ type: 'kong', name: '', station: '3', storageId: '6' }
],
waitDragStart: [],
waitVehicleing: {}, // 正在拖动的
workDragStart: []
}
},
mounted () {
// 重置hover
document.body.style.setProperty('--bg-color', 'transparent')
document.body.style.setProperty('--border-value', '1px dotted #CACDD6')
},
methods: {
// 动态获取放置编号
workposMove (e) {
this.workposNo = e.currentTarget.dataset.actindex
},
// 开始拖拽事件
onStart (e) {
const { oldIndex } = e
this.waitVehicleing = this.waitLoadList[oldIndex]
// this.waitDragStart = deepClone(this.waitLoadList)
// this.workDragStart = deepClone(this.workpositionList)
// 添加hover
document.body.style.setProperty('--bg-color', 'rgba(241, 151, 44, 0.10)')
document.body.style.setProperty('--border-value', '1px solid #F1972C')
},
// 拖拽结束事件
onEnd (e) {
// 重置hover
document.body.style.setProperty('--bg-color', 'transparent')
document.body.style.setProperty('--border-value', '1px dotted #CACDD6')
// hover样式的序号
const hoverIndex = Number(this.workposNo)
// 开始分配
const { newIndex, oldIndex } = e
// 列表没有变化
if ((newIndex === oldIndex) && (this.waitDragStart.length === this.waitLoadList.length)) {
return false
}
this.workpositionList.splice(newIndex, 1)
const { type: waitType } = this.waitVehicleing
const { type: workType, name: workName, station: workStation, storageId: workStorageId } = this.workpositionList[hoverIndex]
if (workName) {
this.waitLoadList.push({ type: workType, name: workName, station: '' })
}
if (['shelves', 'cage'].includes(waitType)) {
this.workpositionList[hoverIndex] = {
...this.waitVehicleing,
station: workStation,
storageId: workStorageId
}
} else if (waitType === 'pallet') {
this.workpositionList[hoverIndex] = {
...this.waitVehicleing,
station: workStation,
storageId: workStorageId
}
// 托盘占两个格子
if (hoverIndex % 2) {
// 第奇数个
const { type: sworkType, name: sworkName, station: sworkStation, storageId: sworkStorageId } = this.workpositionList[hoverIndex - 1]
if (sworkName) {
this.waitLoadList.push({ type: sworkType, name: sworkName, station: '' })
}
this.workpositionList.splice(hoverIndex + 1, 0, { type: 'fu', name: '', station: sworkStation, storageId: sworkStorageId })
this.workpositionList.splice(hoverIndex - 1, 1)
} else {
// 第偶数个
const { type: sworkType, name: sworkName, station: sworkStation, storageId: sworkStorageId } = this.workpositionList[hoverIndex + 1]
if (sworkName) {
this.waitLoadList.push({ type: sworkType, name: sworkName, station: '' })
}
this.workpositionList[hoverIndex + 1] = { type: 'fu', name: '', station: sworkStation, storageId: sworkStorageId }
}
}
}
}
}
</script>
<style lang="scss" scoped>
.left-allocate {
.drag-distribute-cls {
.waitloadcar-list {
width: 100%;
min-height: 134px;
div span {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.vehicle-cls {
height: 102px;
background: #FFFFFF;
box-shadow: 0 1px 6px 0 rgba(0,0,0,0.08);
border-radius: 8px;
margin: 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
.shelves-cls {
width: 126px;
}
.pallet-cls {
width: 262px;
}
.vehicle-name {
font-family: PingFangSC-Regular;
font-size: 14px;
color: rgba(0,0,0,0.70);
letter-spacing: 0;
text-align: center;
font-weight: 400;
}
}
.workposition-list {
.workpos-kong {
width: 126px;
height: 102px;
background: #ffffff;
box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.08);
border-radius: 8px;
margin: 16px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
}
div span {
display: flex;
flex-wrap: wrap;
margin-left: 16px;
}
.workpos-cls {
.sel-text {
display: inline;
margin-left: 0px;
}
h5 {
font-family: PingFangSC-Regular;
font-size: 16px;
color: rgba(0,0,0,0.70);
letter-spacing: 0;
font-weight: 400;
margin: 16px 0 12px;
}
.pallet-icon {
width: 262px;
height: 102px;
background: #DBF3F0;
box-shadow: 0 1px 6px 0 rgba(0,0,0,0.08);
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
.shelves-icon {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.left-kong {
width: 126px;
height: 102px;
line-height: 102px;
background: #F5F6F9;
border: 1px dotted #CACDD6;
border-radius: 8px;
text-align: center;
font-family: PingFangSC-Medium;
font-size: 18px;
color: rgba(0,0,0,0.40);
letter-spacing: 0;
font-weight: 500;
margin: 0 4px;
&:hover {
background-color: var(--bg-color);
border: var(--border-value);
}
}
.left-shelves {
width: 126px;
height: 102px;
background: #DBF3F0;
box-shadow: 0 1px 6px 0 rgba(0,0,0,0.08);
border-radius: 8px;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
margin: 0 4px;
}
}
}
}
.dragClass {
border: 1px solid #01AE97;
border-radius: 8px;
}
.ghostClass {
display: none;
}
}
}
</style>