需求: 我们在选择人员的时候,左侧是个树,用于展示人员的部门、岗位,当点击部门后者岗位的时候,穿梭框左侧用于展示该部门岗位下的人员,右侧框展示我们选择后的人员。并且当我们选择完人员之后,左侧的人员要有一个被选择的状态。
我们需要先写一个组件:
<template>
<div class="th_transfer" v-loading="transferLoading">
<div class="transfer_list all_transfer_list">
<div class="transfer_header">
<span @click="allSelect" class="hand">
<input class="hand" type="checkbox" v-model="all_select" />
</span>
<span class="hand" @click="allSelect">待选人员</span>
</div>
<ul v-if="transferList != null">
<li
class="transfer_li"
v-for="(item, index) in transferList"
:key="index"
>
<span>
<input :disabled="inputDisabled(item)" class="hand" type="checkbox" v-model="item.is_select" />
</span>
<span
class="hand transfer_label_span"
@click="selectItem(item)"
>
{{ item.USERALIAS }}
</span>
</li>
</ul>
<ul v-else>
<li class="transfer_li"></li>
</ul>
</div>
<div class="th_transfer_btn">
<button class="el-icon-arrow-right" @click="changeBtn('right')"></button>
<button class="el-icon-arrow-left" @click="changeBtn('left')"></button>
</div>
<div class="transfer_list select_transfer_list">
<div class="transfer_header">
<span @click="delAllSelect" class="hand">
<input class="hand" type="checkbox" v-model="y_select" />
</span>
<span class="hand" @click="delAllSelect">已选人员</span>
</div>
<ul>
<li
class="transfer_li"
v-for="(item, index) in selectList"
:key="index"
>
<span>
<input class="hand" type="checkbox" v-model="item.is_select" />
</span>
<span
class="hand transfer_label_span"
@click="selectItem(item, true)"
>
{{ item.USERALIAS }}
</span>
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
name: "th_transfer",
props: {
// 待选人员
userList: {
type: Array,
default: [],
},
// 已选人员
defaultSelectList: {
type: Array,
default: [],
},
// 状态
transferLoading: false
},
data() {
return {
all_select: false,
y_select: false,
selectList: this.defaultSelectList,
};
},
watch: {
defaultSelectList: {
handler: function (val) {
this.selectList = val;
},
immediate: true,
},
},
methods: {
/*
* 已经被选中的人员不能在进行操作
* 待选人员禁止操作
* */
inputDisabled(item) {
var status = false
const people = this.selectList.filter(e => {
return e.USERID === item.USERID
})
if (people.length > 0) {
status = true
}
return status
},
/*
* 单选
* item 当前选中人员
* status 状态,区分待选和已选人员
* */
// 待选 单选
selectItem(item, status) {
// 点击已选人员不进入此判断
if (!status) {
// 待选人员并是已被选中人员则不发生改变
const people = this.selectList.filter(e => {
return e.USERID === item.USERID
})
if (people.length > 0) return
}
item.is_select = !item.is_select;
this.$forceUpdate();
},
// 待选 全选
allSelect() {
this.all_select = !this.all_select;
if (this.all_select) {
this.transferList.forEach((e) => {
e.is_select = true;
});
} else {
this.transferList.forEach((e) => {
// 待选人员是已被选中人员则不发生改变
const people = this.selectList.filter(item => {
return e.USERID === item.USERID
})
if (people.length === 0) {
e.is_select = false;
}
});
}
},
// 已选 全选
delAllSelect() {
this.y_select = !this.y_select;
if (this.y_select) {
this.selectList.forEach((e) => {
e.is_select = true;
});
} else {
this.selectList.forEach((e) => {
e.is_select = false;
});
}
},
// 按钮
changeBtn(val) {
if (val === "right") {
this.addRightList();
} else if (val === "left") {
this.delRightList();
}
this.$emit("finalUser", this.selectList);
},
addRightList() {
// this.all_select = false
const addList = JSON.parse(
JSON.stringify(
this.transferList.filter((e) => {
return e.is_select;
})
)
);
if (this.selectList.length > 0) {
var arr = [];
this.selectList.forEach((e) => {
const selectuser = e.USERID + e.USERALIAS;
arr.push(selectuser);
});
addList.forEach((e) => {
const user = e.USERID + e.USERALIAS;
if (!arr.includes(user)) {
e.is_select = false;
this.selectList.push(e);
}
});
} else {
addList.forEach((e) => {
e.is_select = false;
});
this.selectList = addList;
}
},
delRightList() {
this.y_select = false;
const arr = this.selectList.filter((e) => {
return e.is_select;
});
this.transferList.forEach((e) => {
// 回显 选定
const user = e.USERID + e.USERALIAS
arr.forEach(j => {
const juser = j.USERID + j.USERALIAS
if (user === juser) {
e.is_select = true
}
})
})
this.selectList = this.selectList.filter((e) => {
return !e.is_select;
});
},
},
computed: {
transferList() {
this.all_select = false;
var list = JSON.parse(JSON.stringify(this.userList));
if (list != null) {
list.forEach((e) => {
e["is_select"] = false;
e.is_select= false;
// 回显 选定
const user = e.USERID + e.USERALIAS
this.selectList.forEach(j => {
const juser = j.USERID + j.USERALIAS
if (user === juser) {
e.is_select = true
}
})
});
return list;
}
},
},
};
</script>
<style scoped lang="scss">
ul {
margin: 0;
padding: 0;
}
ul > li {
list-style: none;
}
button {
color: #fff;
background-color: #409eff;
border-color: #409eff;
display: inline-block;
line-height: 1;
white-space: nowrap;
cursor: pointer;
text-align: center;
box-sizing: border-box;
outline: none;
margin: 6px;
transition: 0.1s;
font-weight: 500;
padding: 6px 14px;
font-size: 14px;
border-radius: 4px;
}
.hand {
cursor: pointer;
}
.transfer_li {
height: 30px;
display: flex;
align-items: center;
height: 30px;
line-height: 30px;
padding-left: 15px;
color: #606266;
font-weight: 500;
font-size: 14px;
position: relative;
cursor: pointer;
}
.th_transfer {
width: 100%;
height: 100%;
display: flex;
}
.transfer_list {
width: 300px;
height: 100%;
min-height: 300px;
max-height: 300px;
overflow: auto;
border: 1px solid #ebeef5;
border-radius: 4px;
}
.transfer_header {
height: 40px;
line-height: 40px;
background: #f5f7fa;
margin: 0;
padding-left: 15px;
border-bottom: 1px solid #ebeef5;
box-sizing: border-box;
color: #000;
}
.transfer_label_span {
display: inline-block;
width: 90%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.all_transfer_list {
}
.th_transfer_btn {
display: flex;
flex-flow: column;
justify-content: center;
}
.select_transfer_list {
//width: 300px;
}
</style>
父组件的调用:
<transfer
v-model="transfer"
:transferLoading="transferLoading"
:userList="userList"
:defaultSelectList="transfer"
@finalUser="finalUser"
></transfer>