实现效果图 目前只适应6栏js操作
实现功能:实现各个阶段任务随意拖动到任意栏目,栏目宽度按传入数组自适应分布
html
<div class="task-wrap">
<div
class="list-item"
v-for="item in taskList"
:key="item.id"
:style="index == 0 ? 'background:#fff' : ''"
>
<div class="header">
{{ item.name }}
</div>
<div class="list">
<div
class="listBx"
:class="move ? 'move' : ''"
v-for="child in item.child"
:key="child.id"
draggable="true"
@dragover.prevent
@dragstart="dragstart($event, child, item.id)"
@drag="dragmove"
@dragend="dragend($event, child)"
@mouseover="enter"
@mouseleave="leave"
>
<div class="top">
{{ child.title }}
</div>
<div class="bottom">
{{ child.name }}
<span> {{ child.time }}</span>
</div>
</div>
</div>
</div>
<div class="nav-header" v-show="flag">
<div class="header-item" v-for="item in taskList" :key="item.id">
{{ item.name }}
</div>
</div>
<el-dialog
title="任务修改"
:visible.sync="dialogVisible"
width="650px"
center
>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="任务名称">
<el-input v-model="form.name"></el-input>
</el-form-item>
<el-form-item label="任务时间">
<el-input v-model="form.time"></el-input>
</el-form-item>
<el-form-item label="任务类型">
<el-select v-model="form.region" placeholder="任务类型">
<el-option label="未开始" value="1"></el-option>
<el-option label="进行中" value="2"></el-option>
</el-select>
</el-form-item>
<el-form-item label="任务内容">
<el-input
type="textarea"
:rows="2"
placeholder="请输入内容"
v-model="form.title"
>
</el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="dialogVisible = false"
>确 定</el-button
>
</span>
</el-dialog>
</div>
js
export default {
name: "task",
data() {
return {
dialogVisible: false,
flag: false,
move: false,
screenWidth: document.documentElement.clientWidth,
itemWidth: 0,
index: 0,
form: {},
taskList: [
{
id: 1,
name: "未开始",
child: [
{
id: 11,
title: "成品的价格方面,重新设计",
name: "王小虎",
time: "1h"
}
]
},
{
id: 2,
name: "进行中",
child: [
// {
// id: 21,
// title: "成品的价格方面,重新设计",
// name: "王小虎",
// time: "1h"
// }
]
},
{
id: 3,
name: "已暂停",
child: [
// {
// id: 31,
// title: "成品的价格方面,重新设计",
// name: "王小虎",
// time: "1h"
// }
]
},
{
id: 4,
name: "已完成",
child: [
{
id: 41,
title: "成品的价格方面,重新设计",
name: "王小虎",
time: "1h"
}
]
},
{
id: 5,
name: "已取消",
child: [
{
id: 51,
title: "成品的价格方面,重新设计",
name: "王小虎",
time: "1h"
}
]
},
{
id: 6,
name: "已关闭",
child: [
{
id: 61,
title: "基础数据客户管理批量导入",
name: "已关闭",
time: "0h"
},
{
id: 71,
title: "基础数据.客户管理,导入模板",
name: "已关闭",
time: "0h"
},
{
id: 81,
title: "基础数据成品管理详情的样式",
name: "已关闭",
time: "0h"
}
]
}
],
};
},
mounted() {
// 判断传递的子项定义宽度
let taskList = document.querySelectorAll(".list-item");
let headerList = document.querySelectorAll(".header-item");
let width;
if (taskList.length == 2) {
width = "50%";
} else if (taskList.length == 3) {
width = "33.33%";
} else if (taskList.length == 4) {
width = "25%";
} else if (taskList.length == 5) {
width = "20%";
} else if (taskList.length == 6) {
width = "16.66%";
}
for (var i = 0; i < taskList.length; i++) {
taskList[i].style.width = width;
headerList[i].style.width = width;
}
window.onresize = () => {
return (() => {
// 获取到实时的屏幕宽度
this.screenWidth = document.documentElement.clientWidth;
let headerList = document.querySelectorAll(".header-item");
// 实时获取每一栏的宽度
this.itemWidth = this.screenWidth / headerList.length;
})();
};
window.addEventListener("scroll", this.handleScroll);
},
destroyed() {
document.removeEventListener("scroll", this.handleScroll);
},
methods: {
handleScroll() {
//获取滚动时的高度
let scrollTop =
window.pageYOffset ||
document.documentElement.scrollTop ||
document.body.scrollTop;
if (scrollTop > 50) {
this.flag = true;
}
if (scrollTop < 50) {
this.flag = false;
}
},
dragstart(event, child, index) {
this.move = true;
// 判断移动的是哪一栏 通过传递的参数获得
let str = child.id + "";
// 获取当前移动的坐标
this.index = index;
// 获取当前宽度
this.itemWidth = parseInt(this.screenWidth / this.taskList.length);
// 当前选择的位置
this.form = child;
},
dragmove() {
let taskList = document.querySelectorAll(".list-item");
let index = this.index;
let indexEnd = parseInt(event.clientX / this.itemWidth);
for (let i = 0; i < taskList.length; i++) {
taskList[i].style.background = "#fff";
}
taskList[indexEnd].style.background = "rgba(0,0,0,.2)";
},
dragend(event, child) {
this.move = false;
// 获取移动的初始以及之后的坐标
let index = this.index - 1;
let indexEnd = parseInt(event.clientX / this.itemWidth);
// 获取当前子元素坐标
let i = this.taskList[index].child.indexOf(child);
this.taskList[index].child.splice(i, 1);
this.taskList[indexEnd].child.push(child);
this.dialogVisible = true;
let taskList = document.querySelectorAll(".list-item");
taskList[0].style.background = "#fff";
},
enter(index) {
this.move = true;
},
leave() {
this.move = false;
}
}
};
css
body {
height: 100%;
}
.task-wrap {
min- 1200px;
overflow-x: hidden;
}
.task-wrap .list-item {
float: left;
16.66%;
height: 100%;
}
.task-wrap .list-item .header {
100%;
height: 44px;
line-height: 44px;
text-align: center;
}
.task-wrap .list-item .list {
min-height: 100vh;
padding: 10px;
border-right: 2px solid #ccc;
}
.task-wrap .list-item .list .listBx {
box-sizing: border-box;
100%;
min-height: 64px;
padding: 10px;
border: 1px solid #ccc;
margin-bottom: 10px;
}
.move {
cursor: move;
}
.task-wrap .list-item .list .listBx > div {
height: 50%;
}
.task-wrap .list-item .list .listBx .top {
line-height: 28px;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.task-wrap .list-item .list .listBx .bottom {
position: relative;
padding-left: 32px;
}
.task-wrap .list-item .list .listBx .bottom::before {
position: absolute;
top: -5px;
left: 0;
content: "";
display: inline-block;
28px;
height: 40px;
background: url("../assets/zx.png") no-repeat;
}
.task-wrap .list-item .list .listBx .bottom span {
position: absolute;
top: 5px;
right: 10px;
color: #999;
}
.task-wrap .list-item:nth-child(1) .header,
.nav-header div:nth-child(1) {
font-weight: 600;
border-bottom: 5px solid #92ceff;
}
.task-wrap .list-item:nth-child(2) .header,
.nav-header div:nth-child(2) {
font-weight: 600;
border-bottom: 5px solid #0991ff;
}
.task-wrap .list-item:nth-child(3) .header,
.nav-header div:nth-child(3) {
font-weight: 600;
border-bottom: 5px solid #fdcb56;
}
.task-wrap .list-item:nth-child(4) .header,
.nav-header div:nth-child(4) {
font-weight: 600;
border-bottom: 5px solid #40df98;
}
.task-wrap .list-item:nth-child(5) .header,
.nav-header div:nth-child(5) {
font-weight: 600;
border-bottom: 5px solid #cccccc;
}
.task-wrap .list-item:nth-child(6) .header,
.nav-header div:nth-child(6) {
font-weight: 600;
border-bottom: 5px solid #7f869a;
}
.nav-header {
position: fixed;
top: 0;
100%;
height: 44px;
line-height: 44px;
background: #fff;
transition: 0.2s;
}
.nav-header div {
float: left;
text-align: center;
16.66%;
}
.mask {
100px;
height: 100px;
background: pink;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}