前言:
没啥说的,一切尽在代码中
我的效果图
单页面代码:(这里在catch中定义了api返回的测试数据,可直接运行看效果!)
功能说明:(展示tree树菜单、关键字筛选)这里的tree数据格式:
<template>
<el-container style="
min-height: 0px;
max-height: 100%;
border-right: 1px solid #eeeeee;
border-left: 1px solid #eeeeee;
border-bottom: 1px solid #eeeeee;
">
<!--条件筛选的输入框 @input:输入框值改变时触发"-->
<div style="margin-left: 6px;">
<el-input style="margin-top: 8px;" placeholder="请输入关键字..." v-model="filterText" clearable></el-input>
<!--el-aside侧边栏-->
<el-aside width="300px"
style="background-color: #eeeeee;height: 400px;padding: 5px; border-right: 1px solid #eeeeee;margin-top: 6px;">
<!--el-tree树形菜单 data:数据源 | props:映射 | @node-click:选中后触发 | :filter-node-method:过滤的方法 | ref:定义变量,在方法中获取tree值-->
<el-tree :data="departmentArray" :props="defaultProps" @node-click="handleNodeClick"
:filter-node-method="filterNode" ref="tree"></el-tree>
</el-aside>
</div>
</el-container>
</template>
<script>
import Vue from '@/main'
export default {
name: "update-department.component",
title:'岗位/任岗',
data() {
return {
//input 关键字
filterText: '',
//el-tree 数据展示的映射字段
defaultProps: {
children: 'children',
label: 'nameCn',//filterNode 方法筛选方法时,字段使用nameCn
},
//el-tree的数据集合(部门 一级岗位?二级岗位?)
departmentArray: [],
};
},
mounted() {
this.queryDepartmentJob();
},
watch: {
//输入框值发生变化~触发 | 配合tree的过滤数据filterNode方法使用
filterText(val) {
this.$refs.tree.filter(val);
},
},
methods: {
//查询树形菜单| 部门信息即岗位列表
queryDepartmentJob() {
Vue.$Request({
method: 'post',
url: '/post/list',
data: {},
params: {}
}).then((res) => {
if (res.data.code === 200) {
console.log("tree数据:", JSON.stringify(res.data.data.dataList));
//tree下展示岗位的层级关系,并将岗位放到所属的部门下;
//departmentName departmentId 部门 主管岗位?
//nameCn 岗位 | pid为空则为一级岗位 ,否则为二级岗位
this.departmentArray = this.format(res.data.data.dataList);
}
}).catch(error => {
let res=[{"id":10047,"opCode":null,"useStatus":1,"departmentId":30758,"nameCn":"测试数据1124","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":0,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":"HBLX01_SYS","pId":null,"createTime":"2021-11-24 14:39:47","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"数字化管理中心"},{"id":10011,"opCode":null,"useStatus":1,"departmentId":30754,"nameCn":"电商部长","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":0,"postType":null,"effectiveDate":"2001-01-01 00:00:00","expiryDate":"2001-01-01 00:00:00","memo":"无","reportType":null,"pId":null,"createTime":"2021-11-24 14:37:05","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"人力资源中心"},{"id":10010,"opCode":null,"useStatus":1,"departmentId":30754,"nameCn":"信息主管","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":0,"postType":null,"effectiveDate":"2001-01-01 00:00:00","expiryDate":"2001-01-01 00:00:00","memo":null,"reportType":null,"pId":null,"createTime":"2021-11-24 14:37:03","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"人力资源中心"},{"id":10006,"opCode":null,"useStatus":1,"departmentId":30754,"nameCn":"行政管理","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":null,"createTime":"2021-11-24 14:37:01","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"人力资源中心"},{"id":10005,"opCode":null,"useStatus":1,"departmentId":30754,"nameCn":"电商客服专员","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":null,"createTime":"2021-11-24 14:37:00","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"人力资源中心"},{"id":10004,"opCode":null,"useStatus":1,"departmentId":30758,"nameCn":"信息专员","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":10000,"createTime":"2021-11-16 11:13:46","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"数字化管理中心"},{"id":10003,"opCode":null,"useStatus":1,"departmentId":30758,"nameCn":"软件测试","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":10000,"createTime":"2021-11-16 11:13:44","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"数字化管理中心"},{"id":10002,"opCode":null,"useStatus":1,"departmentId":30758,"nameCn":"软件开发","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":10000,"createTime":"2021-11-16 11:13:43","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"数字化管理中心"},{"id":10001,"opCode":null,"useStatus":1,"departmentId":30758,"nameCn":"软件架构","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":10000,"createTime":"2021-11-16 11:13:41","createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"数字化管理中心"},{"id":10000,"opCode":null,"useStatus":1,"departmentId":30758,"nameCn":"信息总监","nameEn":null,"pinyinSimple":null,"pinyin":null,"director":1,"postType":null,"effectiveDate":null,"expiryDate":null,"memo":null,"reportType":null,"pId":null,"createTime":null,"createUserId":null,"updateTime":null,"updateUserId":null,"other":null,"field1":null,"field2":null,"field3":null,"departmentName":"数字化管理中心"}];
// console.log("tree数据:", JSON.stringify(this.departmentArray));
this.departmentArray = this.format(res);
this.$message.warning('服务器抛出异常信息:' + error);
})
},
//第一步:遍历原始数组~提炼部门信息(名称、ID)到新数组(部门数组)
format(array) {
//定义部门数组
let arr = [];
array.forEach(obj => {
//这里之所以将部门名称字段,重新取名nameCn,是因为tree数据渲染,必须是根据某一个字段(因为岗位名称字段:nameCn,保持一致)进行嵌套展示!
arr.push({departmentId: obj.departmentId, nameCn: obj.departmentName});
})
console.log("提炼出的部门数组:", JSON.stringify(arr));//有重复的部门数组
//部门数组去重(去除重复部门) | 利用对象访问属性的方法,判断对象中是否存在重复的departmentId
let deparement_array = [];
let obj = {};
for (let i = 0; i < arr.length; i++) {
if (!obj[arr[i].departmentId]) {
deparement_array.push(arr[i]);
obj[arr[i].departmentId] = true;
}
}
console.log("去重后的部门数组:", JSON.stringify(deparement_array));
return this.setTreeData(array, deparement_array);
},
//第二步:实现岗位和子岗位层级关系
setTreeData(arr, arr1) {
// 删除所有的children,以防止多次调用
arr.forEach(function (item) {
delete item.children;
});
let map = {}; //构建map
arr.forEach(i => {
map[i.id] = i; //构建以id为键 当前数据为值
});
let treeData = [];
arr.forEach(child => {
const mapItem = map[child.pId]; //判断当前数据的pId是否存在map中
if (mapItem) {
//存在则表示当前数据不是最顶层的数据
//注意: 这里的map中的数据是引用了arr的它的指向还是arr,当mapItem改变时arr也会改变,踩坑点
(mapItem.children || (mapItem.children = [])).push(child); //这里判断mapItem中是否存在child
} else {
//不存在则是顶层数据
treeData.push(child);
}
});
console.log("封装好的岗位数组:", JSON.stringify(treeData));
//最后一步:合并部门和岗位的层级关系(将岗位层级放到所属部门下children数组下)
for (let a = 0; a < treeData.length; a++) { // 封装好的岗位层级的数组
for (let b = 0; b < arr1.length; b++) {//父 部门数组
if (treeData[a].departmentId === arr1[b].departmentId) {
(arr1[b].children = []).push(treeData[a]);//1.arr1添加一个属性,并声明是数组 2.往数组中添加对象
}
}
}
console.log("终于得到符合el-tree的数据格式:", JSON.stringify(arr1));
return arr1;
},
//树形菜单筛选数据方法,配合input的(watch中)filterText一起使用。
filterNode(value, data) {
if (!value) return true;
return data.nameCn.indexOf(value) !== -1;
},
//当前el-tree选中项(只要将服务端数据封装成el-tree想要的格式,这里方法可以直接拿到点击的对象!)
handleNodeClick(data) {
console.log(data);
},
},
};
</script>
<style>
.el-tree {
color: #000;
}
.el-menu--horizontal > .el-menu-item.is-active {
/* 顶部菜单项选中时的颜色 */
border-bottom: 2px solid #009944;
/* 顶部菜单栏底线颜色 */
color: #303133;
}
.el-tree-node__expand-icon {
/* 树形菜单三角标颜色 */
color: #999;
}
.el-tree-node__content:hover {
/* 树形菜单鼠标悬浮的字体颜色及背景颜色 */
color: #ffffff;
background-color: #009944;
}
.el-tree-node:focus > .el-tree-node__content {
/* 树形菜单选中时的字体颜色及背景颜色 */
color: #ffffff;
background-color: #009944;
}
.el-tree--highlight-current .el-tree-node.is-current > .el-tree-node__content {
/* 树形菜单选中时的字体颜色及背景颜色 */
color: #ffffff;
background-color: #009944;
}
.el-button__content:hover {
color: #ffffff;
background-color: #009944;
}
.el-scrollbar__wrap {
margin-bottom: 0px !important;
}
/**根据ID或员工姓名查询时,显示的侧边栏样式**/
.sidebar-left {
color: #7a7a7a;
/*background-color: #3a8ee6;*/
height: 1200px;
overflow: auto;
}
.sidebar-left-content {
padding: 6px 12px;
margin: 6px 0;
cursor: pointer;
font-size: 14px;
display: flex;
justify-content: space-between;
align-items: center;
}
.sidebar-left-content2 {
background-color: #009944;
color: white;
}
.sidebar-left-content:hover {
color: #009944;
font-size: 14.5px;
background-color: #eeeeee;
}
.condition {
background-color: #eeeeee;
padding: 8px 28px;
/*color: #8c8c8c;*/
cursor: pointer;
font-size: 14px;
}
/**点击后改变背景色和文字颜色**/
.click_sty {
background-color: #009944;
color: white;
}
@media screen and (min-height: 0px) and (max-height: 749px) {
#edit {
overflow: auto;
height: 500px;
}
}
@media screen and (min-height: 750px) and (max-height: 10900px) {
#edit {
overflow: auto;
height: 700px;
}
}
</style>
后语:
虽然是一个不是很难的功能,但是对于我来说花费不少时间去实现,主要就是初期不知道如何将服务器返回的JSON数据,转换成el-tree的数据格式,最后实现功能后,深感自己JavaScript知识薄弱。