提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
Article directory
Preface
vant2的级联选择器
, component link portal
functional requirements, select all and deselect all, only a simple version.
There are two buttons, one and 全选
one, 取消全选
and only select || Cancel the currently displayed children array.
提示:以下是本篇文章正文内容,下面案例可供参考
1. Page code
Due to privacy, only static images can be posted here.
I encapsulated this code into a components component and only need to throw it intopopup弹出框
1. Parent page code
<!-- 选择人员弹出框 -->
<van-popup v-model="showChose" closeable close-icon="close" position="right"
:style="{ height: '100%', width: '100%' }">
<!-- 弹出框内容 -->
<ChoseUser v-if="showChose" name="参会" @onCancel="showChose = false" @onConfirm="onConfirmChose">
</ChoseUser>
</van-popup>
2.js method
import ChoseUser from "@/components/ChoseUser/general.vue"
export default {
name: "vinit",
components: {
ChoseUser,
},
data() {
return {
showChose:false,
Get return value
methods:{
// 确定选中人员
onConfirmChose(activeUser) {
console.log(activeUser, '选中人员')
this.showChose = false
// 回显参会人员
this.userOut = activeUser.map(item => item.text).join()
},
}
2. Subcomponent code
1.Page
The code is as follows (example):
<template>
<div class="showUser">
<h4 @click="getDeptList">请选择{
{ name }}人员</h4>
<van-search v-model="searchName" :placeholder="`请输入搜索的${name}人姓名`" />
<van-loading size="24px" v-if="list.length == 0">加载中...</van-loading>
<div class="submit">
<van-button type="danger" plain size="small" @click="onSelectAll">全选</van-button>
<van-button type="warning" plain size="small" @click="onClearAll">取消全选</van-button>
</div>
<van-tree-select :items="list | newUserList(searchName)" :active-id.sync="activeId"
:main-active-index.sync="activeIndex" />
<div class="submit">
<van-button type="default" @click="onCancel">取消</van-button>
<van-button type="info" @click="onConfirm">确定</van-button>
</div>
</div>
</template>
2. Style code
The code is as follows (example):
.showUser {
height: 100vh;
box-sizing: border-box;
padding: 30px 0;
h4 {
margin-bottom: 30px;
padding-left: 30px;
font-size: 30px;
}
// 选择器
.van-tree-select {
margin-top: 20px;
height: 70% !important;
.van-sidebar-item--select::before {
background-color: #418AF1;
}
.van-tree-select__item--active {
color: #418AF1;
}
}
.submit {
width: 100%;
display: flex;
justify-content: space-around;
margin: 20px 0;
.van-button {
width: 150px;
}
}
}
3. js code
Let’s first look at the data formats supported by the vant component
What it needs is an object array, its object data is the list on the left, and the children data is the child data list rendered on the right.
For example, the following format
testList: [
{
id: 1,
text: '湖南',
children:[{
id:101,
text:'长沙'
},{
id:102,
text:'张家界'
}]
}, {
id: 2,
text: '广东',
children:[{
id:201,
text:'深圳'
},{
id:202,
text:'佛山'
}]
},
]
The way I write it here is to get the department list, then click on the department (on the left), and then request the personnel list on the right .
After obtaining the personnel list, according to the current index subscript, write it to the children of the corresponding department on the left. The code has been compressed.
The method is roughly as follows: obtain personnel data and modify it as needed
getDeptList() {
// 如果有传入id,则zmlk处理, 没有则通用流程处理
let id = this.id || this.mainDept.deptId
deptList(id).then(res => {
let data = res.data
data.forEach(item => {
item.text = item.label
item.children = []
})
// 添加主部门信息,可以查询全部人员
// if (res.data.length > 1) {
// data.unshift({
// id: this.mainDept.deptId,
// text: this.mainDept.deptName,
// children: [],
// })
// }
this.list = data
}).then(() => {
// 获取当前用户信息所在部门,使左侧对应
const userInfo = Cookies.get("userInfo") && JSON.parse(Cookies.get("userInfo"));
const userDeptId = userInfo ? userInfo.deptId : null
// 左侧选中的部门id赋值,有个人信息,赋值,没有则取第一项
this.deptId = userDeptId || this.list[0].id
// 设置选中部门下标为自己的部门
let index = this.list.findIndex(item => item.id === this.deptId)
this.activeIndex = index == -1 ? 0 : index
this.getDeptUserList() // 调用获取部门下人员信息
})
},
// 获取自己部门下人员列表
getDeptUserList() {
// 如果选中部门,有人员列表,则不请求数据
if (this.list[this.activeIndex].children.length > 0) {
return
}
deptUserList(this.deptId).then(res => {
let array = []
res.data.filter(item => {
array.push({
text: item.realName,
id: item.userName,
deptId: item.deptId,
userId: item.userId,
})
})
// 赋值当前选中部门下children的值
this.list[this.activeIndex].children = [...array]
// 赋值全部人员,用于返回给父页面(对象数组)
this.userListAll = [...this.userListAll, ...array]
})
},
Because there are no user personnel at the beginning, I need a listener. To switch the list on the left, I need to request the personnel list on the right.
watch: {
// 要监听的数据,可以是数组、对象、或者普通的变量
activeIndex: {
// immediate: true, // 立即执行,创建页面时就执行一次
// deep: true, // 深度监听,会监听到对象里面的属性改变
handler(newIndex) {
this.deptId = this.list[newIndex].id
this.getDeptUserList()
},
},
},
上面代码是,获取左侧列表和右侧人员列表的方法
, because they are obtained separately.
If yours is an array obtained at once, it does not need to be so cumbersome. Although the request return value becomes larger, it may be slow and slow.
key code
1. Subcomponent variables
props: {
name: {
type: String,
default: "处理", // 处理||传阅, 领导||部门
},
// 是否多选,默认多选,
isArray: {
type: Boolean,
default: true
},
},
data() {
return {
activeIndex: 0, // 左侧《下标
activeId: [], //右侧》列表选中项 ids数组
searchName: "", // 搜索过滤
deptId: "", // 部门id,用于查询部门人员
list: [], // ----------------待选列表, 部门+人员子级 children嵌套
flowList: [], // 正在处理人员,用于禁选
userListAll: [], // 所有子级人员
mainDept: null,// 当前用户部门信息
}
},
created() {
this.init()
},
mounted() {
},
methods: {
init(){
this.isArray ? this.activeId = [] : this.activeId = ""
this.getDeptList() // 获取部门列表
}
},
2. Search filters
filters: {
// 过滤选择人员
newUserList(list, searchName) {
let arr = []
if (searchName != "") {
list.forEach((item1, index1) => {
arr.push({
text: item1.text,
children: []
})
item1.children.forEach(item2 => {
if (item2.text.toLowerCase().includes(searchName.toLowerCase())) {
arr[index1].children.push({
id: item2.id,
disabled: item2.disabled,
text: item2.text,
})
}
})
})
return arr
} else {
return list
}
}
},
3. Return the object array to the parent page
computed: {
activeList() {
let selectedData = []
if (Array.isArray(this.activeId)) {
console.log("计算")
selectedData = this.activeId.map(id => {
// 通过 id 查找对应的数据
return this.userListAll.find(data => data.id == id);
});
}
return selectedData
},
},
4.Confirmation and cancellation methods
Subpage code
// 取消
onCancel() {
this.$emit("onCancel")
},
// 确定
onConfirm() {
this.$emit("onConfirm", this.activeList)
},
The cancellation method is to close through the parent page
5. Select all and reverse the selection
Select all and reverse selection as long as the variables are consistent, you can directly take them away and use them.
// 全选
onSelectAll() {
console.log('全选')
const currentChildren = this.list[this.activeIndex]?.children || [];
console.log(currentChildren)
const selectedIdsSet = new Set(this.activeId);
currentChildren.forEach(item => {
selectedIdsSet.add(item.id);
});
this.activeId = Array.from(selectedIdsSet);
console.log(this.activeId)
},
// 清空当前页全选
onClearAll() {
const currentChildren = this.list[this.activeIndex]?.children || [];
const selectedIdsSet = new Set(this.activeId);
currentChildren.forEach(item => {
selectedIdsSet.delete(item.id);
});
this.activeId = Array.from(selectedIdsSet);
},
Summarize
Let’s look at the case diagram
1. Click on the partial personnel list
全选
, and then on the all personnel list page you can see that the selected person is selected.
2. On the all personnel list全选
, then on the partial personnel list取消全选
. Switching back to all personnel, you can see that some personnel have also been deselected.
3. Filter function
Fix bug
My selection all is to get all the children data of the currently selected item, but
when I use search search filtering, it will be accidentally damaged. I searched for 3 people in the list of all people, clicked to select all, and 10 people were selected.
Modify now
在methods下添加过滤方法
filterNewUserList(list, searchName) {
let arr = [];
if (searchName !== "") {
list.forEach((item1, index1) => {
arr.push({
text: item1.text,
children: [],
});
item1.children.forEach((item2) => {
if (
item2.text.toLowerCase().includes(searchName.toLowerCase())
) {
arr[index1].children.push({
id: item2.id,
disabled: item2.disabled,
text: item2.text,
});
}
});
});
return arr;
} else {
return list;
}
},
在computed中添加计算属性变量
filterUserList() {
return this.filterNewUserList(this.list, this.searchName);
},
Modify the above selection method
Just change the list to filterUserList
The clearing method does not change, because we really want to clear everything. Currently, we can also clear the searched people, and change it to filterUserList.
The complete code is as follows (the part needs to be deleted for free)
<template>
<div class="showUser">
<h4 @click="getDeptList">请选择{
{ name }}人员</h4>
<van-search v-model="searchName" :placeholder="`请输入搜索的${name}人姓名`" />
<van-loading size="24px" v-if="list.length == 0">加载中...</van-loading>
<div class="submit">
<van-button type="danger" plain size="small" @click="onSelectAll">全选</van-button>
<van-button type="warning" plain size="small" @click="onClearAll">取消全选</van-button>
</div>
<van-tree-select :items="list | newUserList(searchName)" :active-id.sync="activeId"
:main-active-index.sync="activeIndex" />
<div class="submit">
<van-button type="default" @click="onCancel">取消</van-button>
<van-button type="info" @click="onConfirm">确定</van-button>
</div>
</div>
</template>
<script>
import {
deptList, // 查询部门列表
deptUserList, // 查询部门下的用户列表 id
} from "@/api/flow/common.js"
import {
shouwenFormNot, // 收文未办
} from "@/api/flow/shouwen/task.js"
import {
jobFormNot, // 任务
} from "@/api/flow/job/task.js"
import {
sealFormNot, // 公章
} from "@/api/flow/seal/task.js"
import {
carFormNot, // 公车
} from "@/api/flow/car/task.js"
import {
leaveFormNot, // 请假
} from "@/api/flow/leave/task.js"
import {
getToken
} from "@/utils/auth";
import Cookies from "js-cookie"
export default {
name: "vinit",
components: {
},
props: {
name: {
type: String,
default: "处理", // 处理||传阅, 领导||部门
},
// 是否多选,默认多选,
isArray: {
type: Boolean,
default: true
},
// 公文id, 有id查出正在办并禁用,没id查全部人员
formId: {
type: Number
},
// 传入部门id,6185||326, zmlk专用,没传根据自己id查当前能查询到的
id: {
type: String
},
// 选择人员类型,shouwen收文,job任务,seal公章,car公车,leave请假
type: {
type: String,
default: "shouwen",
}
},
data() {
return {
timer: null,//定时器
activeIndex: 0, // 左侧《下标
activeId: [], //右侧》列表选中项 ids数组
searchName: "", // 搜索过滤
deptId: "", // 部门id,用于查询部门人员
list: [], // ----------------待选列表, 部门+人员子级 children嵌套
flowList: [], // 正在处理人员,用于禁选
userListAll: [], // 所有子级人员
mainDept: null,// 当前用户部门信息
}
},
computed: {
activeList() {
let selectedData = []
if (Array.isArray(this.activeId)) {
console.log("计算")
selectedData = this.activeId.map(id => {
// 通过 id 查找对应的数据
return this.userListAll.find(data => data.id == id);
});
}
return selectedData
},
filterUserList() {
return this.filterNewUserList(this.list, this.searchName);
},
},
filters: {
// 过滤选择人员
newUserList(list, searchName) {
let arr = []
if (searchName != "") {
list.forEach((item1, index1) => {
arr.push({
text: item1.text,
children: []
})
item1.children.forEach(item2 => {
if (item2.text.toLowerCase().includes(searchName.toLowerCase())) {
arr[index1].children.push({
id: item2.id,
disabled: item2.disabled,
text: item2.text,
})
}
})
})
return arr
} else {
return list
}
}
},
watch: {
// 要监听的数据,可以是数组、对象、或者普通的变量
activeIndex: {
// immediate: true, // 立即执行,创建页面时就执行一次
// deep: true, // 深度监听,会监听到对象里面的属性改变
handler(newIndex) {
this.deptId = this.list[newIndex].id
this.getDeptUserList()
},
},
},
created() {
this.mainDept = JSON.parse(Cookies.get("mainDept"))
// 发起定时器轮询异步请求
this.timer = setInterval(() => {
// 执行异步请求,获取 token 的新值
// 如果获取到了新值,则更新组件的状态
if (typeof getToken() !== 'undefined') {
this.init()
// 清除定时器
clearInterval(this.timer);
}
}, 30);
},
mounted() {
},
methods: {
init() {
this.isArray ? this.activeId = [] : this.activeId = ""
// 公文id, 有id查出正在办并禁用,没id查全部人员
if (this.formId) {
switch (this.type) {
case "shouwen":
this.getShouwenList()
break;
case "job":
this.getJobList()
break;
case "seal":
this.getSealList()
break;
case "car":
this.getCarList()
break;
case "leave":
this.getLeaveList()
break;
}
} else {
this.getDeptList() // 获取部门列表
}
},
// 全选
onSelectAll() {
const currentChildren = this.filterUserList[this.activeIndex]?.children || [];
console.log(currentChildren)
const selectedIdsSet = new Set(this.activeId);
currentChildren.forEach(item => {
selectedIdsSet.add(item.id);
});
this.activeId = Array.from(selectedIdsSet);
console.log(this.activeId)
},
// 清空当前页全选
onClearAll() {
const currentChildren = this.list[this.activeIndex]?.children || [];
const selectedIdsSet = new Set(this.activeId);
currentChildren.forEach(item => {
selectedIdsSet.delete(item.id);
});
this.activeId = Array.from(selectedIdsSet);
},
// 取消
onCancel() {
this.$emit("onCancel")
},
// 确定
onConfirm() {
this.$emit("onConfirm", this.activeList)
},
// 获取部门列表
getDeptList() {
// 如果有传入id,则zmlk处理, 没有则通用流程处理
let id = this.id || this.mainDept.deptId
deptList(id).then(res => {
let data = res.data
// 如果传参为部门,过滤领导id
if (this.name == "部门") {
data = res.data.filter(item => {
return item.id != 6185
})
}
data.forEach(item => {
item.text = item.label
item.children = []
})
// 添加主部门信息,可以查询全部人员
if (res.data.length > 1) {
data.unshift({
id: this.mainDept.deptId,
text: this.mainDept.deptName,
children: [],
})
}
this.list = data
}).then(() => {
const userInfo = Cookies.get("userInfo") && JSON.parse(Cookies.get("userInfo"));
const userDeptId = userInfo ? userInfo.deptId : null
this.deptId = userDeptId || this.list[0].id
console.log('当前部门id', this.deptId)
// zmlk\通用的请求部门人员判断
if (this.id) {
this.deptId = this.list[0].id // 文秘查询专用
} else {
this.deptId = this.deptId // 自己的部门id
}
// 设置选中部门下标为自己的部门
let index = this.list.findIndex(item => item.id === this.deptId)
this.activeIndex = index == -1 ? 0 : index
this.getDeptUserList()
})
},
// 获取自己部门下人员列表
getDeptUserList() {
// 如果选中部门,有人员列表,则不请求数据
if (this.list[this.activeIndex].children.length > 0) {
return
}
deptUserList(this.deptId).then(res => {
let array = []
res.data.filter(item => {
let bool = false
for (const element of this.flowList) {
(element.userName == item.userName) && (bool = true)
}
array.push({
text: item.realName,
id: item.userName,
disabled: bool,
userName: item.userName,
realName: item.realName,
deptId: item.deptId,
userId: item.userId,
})
})
// 赋值当前选中部门下children的值
this.list[this.activeIndex].children = [...array]
// 赋值全部人员
this.userListAll = [...this.userListAll, ...array]
})
},
filterNewUserList(list, searchName) {
let arr = [];
if (searchName !== "") {
list.forEach((item1, index1) => {
arr.push({
text: item1.text,
children: [],
});
item1.children.forEach((item2) => {
if (
item2.text.toLowerCase().includes(searchName.toLowerCase())
) {
arr[index1].children.push({
id: item2.id,
disabled: item2.disabled,
text: item2.text,
});
}
});
});
return arr;
} else {
return list;
}
},
// 收文待办
getShouwenList() {
shouwenFormNot(this.formId).then(res => {
this.flowList = [...res.data]
this.getDeptList()
})
},
// 任务
getJobList() {
jobFormNot(this.formId).then(res => {
this.flowList = [...res.data]
this.getDeptList()
})
},
// 公章
getSealList() {
sealFormNot(this.formId).then(res => {
this.flowList = [...res.data]
this.getDeptList()
})
},
// 公车
getCarList() {
carFormNot(this.formId).then(res => {
this.flowList = [...res.data]
this.getDeptList()
})
},
// 请假
getLeaveList() {
leaveFormNot(this.formId).then(res => {
this.flowList = [...res.data]
this.getDeptList()
})
},
},
}
</script>
<style scoped lang="less">
.showUser {
height: 100vh;
box-sizing: border-box;
padding: 30px 0;
h4 {
margin-bottom: 30px;
padding-left: 30px;
font-size: 30px;
}
// 选择器
.van-tree-select {
margin-top: 20px;
height: 70% !important;
.van-sidebar-item--select::before {
background-color: #418AF1;
}
.van-tree-select__item--active {
color: #418AF1;
}
}
.submit {
width: 100%;
display: flex;
justify-content: space-around;
margin: 20px 0;
.van-button {
width: 150px;
}
}
}
</style>