Vue 拖选表格: 模拟排班功能
演示
在线访问: https://wenkil.github.io/drag_table_demo (请使用PC端打开)
预览
源码
<template>
<div>
<div style="margin: 30px 0; text-align: right;">
<el-button @click="reset" class="reset-btn">重置</el-button>
<!-- <el-button type="primary" @click="changeGrid">确认修改</el-button>-->
</div>
<div class="box" @mousedown="handleMouseDown">
<div class="mask" v-show="is_show_mask"
:style="'width:'+mask_width+'left:'+mask_left+'height:'+mask_height+'top:'+mask_top">
</div>
<table border="1" cellspacing="0" class="table">
<th v-for="(item,index) in weekEnum" class="week-data-th" :key="index">
{{ item }}
</th>
<tr v-for="(item,index) in list">
<td
v-for="(temp,idx) in item.child"
@click="handleClickTimeData(temp,index)"
:key="idx"
class="week-data-td"
:style="`background:${temp.checked?'#3af':''}`"
>
<p>{{ temp.val }}</p>
</td>
</tr>
</table>
</div>
</div>
</template>
<script>
export default {
components: {},
props: {
tHead: {
type: Array,
default: () => []
},
tBody: {
type: Array,
default: () => []
}
},
data() {
return {
is_show_mask: false,
start_x: 0,
start_y: 0,
end_x: 0,
end_y: 0,
box_screen_left: 0,
box_screen_top: 0,
weekEnum: [
"星期一",
"星期二",
"星期三",
"星期四",
"星期五",
"星期六",
"星期日"
],
list: [],
tdLength: 30
};
},
computed: {
// 框选操作
mask_width() {
return `${Math.abs(this.end_x - this.start_x)}px;`;
},
mask_height() {
return `${Math.abs(this.end_y - this.start_y)}px;`;
},
mask_left() {
return `${
Math.min(this.start_x, this.end_x) - this.box_screen_left
}px;`;
},
mask_top() {
return `${
Math.min(this.start_y, this.end_y) - this.box_screen_top
}px;`;
}
},
mounted() {
window.addEventListener("scroll", this.windowScroll);//监听页面滚动
this.initTable();
this.initWidth();
},
beforeDestroy() {
window.removeEventListener("scroll", this.windowScroll);
},
methods: {
initWidth() {
const dom_box = document.querySelector(".box");
this.box_screen_left = dom_box.getBoundingClientRect().left;
this.box_screen_top = dom_box.getBoundingClientRect().top;
console.log("this.box_screen_left", this.box_screen_left);
console.log("this.box_screen_top", this.box_screen_top);
},
//页面滚动时初始化位置
windowScroll() {
this.resSetXY();
this.initWidth();
},
initTable() {
let tableList = [...new Array(this.tdLength).keys()];
console.log("tableList", tableList);
this.list = tableList.map((item, index) => {
let temp = Array.from(new Array(7).keys());
console.log("temp", temp);
let child = temp.map((v, key) => {
return {
key: key + index * 7,
val: ""
};
});
console.log("child", child);
return { child };
});
console.log("this.list", this.list);
},
reset() {
let tableList = JSON.parse(JSON.stringify(this.list));
tableList.map((item) => {
item.child.map((temp) => {
temp.checked = false;
});
});
this.list = tableList;
},
handleClickTimeData(obj, index) {
let tableList = JSON.parse(JSON.stringify(this.list));
console.log("tableList", tableList);
tableList[index].child.map((item) => {
if (item.key == obj.key) {
item.checked = !item.checked;
}
});
this.list = tableList;
},
changeGrid() {
this.handleDomSelect();//选中后的判断,找到框选内的格子
this.resSetXY();//调用此方法让框选消失
},
handleMouseDown(e) {
console.log("event", e);
this.is_show_mask = true;
this.start_x = e.clientX;
this.start_y = e.clientY;
this.end_x = e.clientX;
this.end_y = e.clientY;
window.addEventListener("mousemove", this.handleMouseMove);
window.addEventListener("mouseup", this.handleMouseUp);
},
handleMouseMove(event) {
this.end_x = event.clientX;
this.end_y = event.clientY;
},
handleMouseUp() {
window.removeEventListener("mousemove", this.handleMouseMove);
window.removeEventListener("mouseup", this.handleMouseUp);
this.changeGrid();
},
resSetXY() {
this.start_x = 0;
this.start_y = 0;
this.end_x = 0;
this.end_y = 0;
},
handleDomSelect() {
const dom_mask = window.document.querySelector(".mask");
const rect_select = dom_mask.getClientRects()[0];
console.log("rect_select", rect_select);
let selectKeys = [];
document.querySelectorAll(".week-data-td").forEach((node, index) => {
const rects = node.getClientRects()[0];
console.log("rects", rects);
if (this.collide(rects, rect_select) === true) {
selectKeys.push(index);
}
});
console.log("selectKeys", selectKeys);
if (selectKeys.length < 2) return;
let tableList = JSON.parse(JSON.stringify(this.list));
tableList = tableList.map((item, key) => {
let child = item.child.map((temp) => {
if (selectKeys.indexOf(temp.key) > -1) {
temp.checked = !temp.checked;
}
return temp;
});
return { child };
});
this.list = tableList;
console.log("this.list", this.list);
},
collide(rect1, rect2) {
const maxX = Math.max(rect1.x + rect1.width, rect2.x + rect2.width);
const maxY = Math.max(rect1.y + rect1.height, rect2.y + rect2.height);
const minX = Math.min(rect1.x, rect2.x);
const minY = Math.min(rect1.y, rect2.y);
if (maxX - minX <= rect1.width + rect2.width && maxY - minY <= rect1.height + rect2.height) {
return true;
}
else {
return false;
}
}
}
};
</script>
<style lang="scss" scoped>
td {
width: 300px;
text-align: center;
}
.box {
width: 100%;
height: auto;
margin: 20px auto;
position: relative;
user-select: none;
.table {
width: 100%;
}
.mask {
position: absolute;
background: #409eff;
opacity: 0.4;
}
}
.week-data-th {
min-width: 100px;
height: 30px;
}
.week-data-td {
height: 50px;
}
</style>
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!