前段时间业务需求里面有通过拖拽来实现类似排班的效果,但实际业务逻辑比较复杂,数据间的关联度强,不太方便展示,这里就单独把拖拽写了一个小demo进行展示。
需求:拖动左边表格里的数据进行患者手术排台
实现思路:
1、在需要拖动的dom节点上添加以下属性和事件
:draggable="true" // 开启拖拽
@dragover.prevent.stop // 防止事件冒泡
@dragstart="onDragleave($event, item)" // 拖拽事件开始(item:被拖拽的所有数据)
2、在目标拖拽dom节点上添加以下事件
@dragover.prevent
@dragenter.prevent
@drop="handleDrop($event, item)" // item:拖拽前绑定的的原始数据
完整代码:
<template>
<div class="container">
<div class="surgicalInformation">
<!-- 表格 -->
<table>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>科室</td>
</tr>
<tr v-for="(item, index) in tableData" :data-id="item.id" :key="item.id" :draggable="true" @dragover.prevent.stop
@dragstart="onDragleave($event, item)">
<td>{
{ index + 1 }}</td>
<td>{
{ item.name }}</td>
<td>{
{ item.age }} 岁</td>
<td>{
{ item.department }}</td>
</tr>
</table>
</div>
<div class="shiftInformation">
<div class="box" ref="targetBox" :data-items="item.name" v-for="item in info" :key="item.name" @dragover.prevent
@dragenter.prevent @drop="handleDrop($event, item)">
<div class="boxName">{
{ item.name }}</div>
<div class="boxContain">
<div style="font-weight: 700;">患者手术信息</div>
<div class="doctor">姓名 : {
{ item.data.doctor }}</div>
<div class="nurse1">年龄 : {
{ item.data.age }}</div>
<div class="nurse2">科室 : {
{ item.data.department }}</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang='ts' name="fundataDragging">
import { ref } from 'vue'
const targetBox = ref()
// 模拟数据
let tableData = ref<any[]>([])
tableData.value = [
{
id: 1,
age: 20,
name: '王患者',
department: '手术室',
},
{
id: 2,
age: 21,
name: '李患者',
department: '妇产科',
},
{
id: 3,
age: 22,
name: '陈患者',
department: 'ICU',
},
{
id: 4,
age: 23,
name: '郑患者',
department: '骨科',
},
]
// reactive 数据更新页面不更新 数组数据实时更新需要用ref
let info = ref<any[]>([])
info.value = [
{
name: 'A-01',
data: {
doctor: '',
nurse1: '',
nurse2: ''
}
},
{
name: 'A-02',
data: {
doctor: '',
nurse1: '',
nurse2: ''
}
},
{
name: 'A-03',
data: {
doctor: '',
nurse1: '',
nurse2: ''
}
},
]
const onDragleave = (event: any, item: any) => {
event.dataTransfer.setData("nurseInfo", JSON.stringify(item));
console.log('---拖拽的数据---: ', item);
}
const handleDrop = (event: any, item: any) => {
event.preventDefault();
// 获取拖放的数据
const data = JSON.parse(event.dataTransfer.getData('nurseInfo'));
console.log(data, '获取被拖放的数据');
console.log(item, '拖拽之前的原数据');
item.data.doctor = data.name
item.data.age = data.age
item.data.department = data.department
// 删除拖拽走的数据
tableData.value.map((i: any, index: number) => {
if (data.id == i.id) {
tableData.value.splice(index, 1)
}
})
}
</script>
<style lang="scss" scoped>
.container {
height: 100%;
display: flex;
.surgicalInformation {
width: 40%;
height: 100%;
padding: 10px;
table {
border: 1px solid #000;
width: 100%;
height: 100%;
tr {
height: 50px;
text-align: center;
background-color: #ebf5ff;
}
tr:nth-child(1) {
background-color: #33affb;
}
}
}
.shiftInformation {
flex: 1;
height: 100%;
display: flex;
justify-content: space-evenly;
padding: 80px;
.box {
width: 250px;
height: 150px;
border: 1px solid paleturquoise;
margin-right: 10px;
border-radius: 20px;
display: flex;
.boxName {
width: 20%;
height: 100%;
background-color: #33affb;
text-align: center;
border-radius: 20px;
line-height: 150px;
font-size: 20px;
font-weight: 700;
}
.boxContain {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: space-evenly;
margin-left: 20px;
font-size: 16px;
}
}
}
}
</style>