部门视图优化改造

This commit is contained in:
yujh 2024-10-18 16:15:43 +08:00
parent c3efda91b4
commit 0e23df6a78
5 changed files with 401 additions and 108 deletions

View File

@ -4,6 +4,8 @@
<meta charset="UTF-8">
<!-- import CSS -->
<link rel="stylesheet" href="../apps/com.awspaas.user.apps.yili.integration/components/icon.css">
<link rel="stylesheet" href="../apps/com.awspaas.user.apps.yili.integration/css/department1.css">
<link rel="stylesheet" href="../apps/com.awspaas.user.apps.gpt_interface/css/gpt.css">
<script>
var sid = '<#sid>';
@ -11,13 +13,69 @@
</head>
<body>
<div id="app">
<div id="floatingChatIcon" >
<img src="../apps/com.awspaas.user.apps.gpt_interface/img/robot-icon.png" alt="Chat Bot" @click="openGptHome" >
<el-dialog
:visible.sync="dialogVisible"
width="80%"
custom-class="custom-dialog"
append-to-body>
<iframe :src="newPageUrl" frameborder="0" style="width: 100%; height: 100%;"></iframe>
<span slot="footer" class="dialog-footer">
<el-button @click="closeDialog">关闭</el-button>
</span>
<p>{{param1}}</p>
</el-dialog>
</div>
<div id="main">
<div id="leftDiv" ref="searchDiv">
<div class="cartTitle">
<span style="padding-top: 10px; display: inline-block;">部门视图</span>
<div style="float:right;">
<div style="float: left;">
<span style="float: left;line-height: 35px; font-weight:normal; font-size: 14px;">搜索:</span>
<!-- 筛选区域 -->
<div class="section">
<div>
<div class="cartTitleDiv">
<span class="section-title">筛选发布部门</span>
<el-popover
placement="top-start"
title="请选择发布部门"
width="600"
trigger="hover"
>
<div id="postSearchCart">
<div class="search">
<el-input
placeholder="输入关键字进行过滤"
v-model="filterText" style="width:80%;">
</el-input>
<el-checkbox v-model="checked1" label="全选" border @change="chooseAll"
style="float:right;width:18%"></el-checkbox>
</div>
<div class="" style="height: 400px;overflow-y: auto;overflow-x: hidden;">
<el-tree
:data="list"
show-checkbox
ref="tree"
empty-text="该部门下暂无文件"
node-key="ID"
:props="defaultProps"
:filter-node-method="filterNode"
:default-checked-keys="idjson"
@check="handleCheckChange"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span :title="node.data.name ">{{ node.data.name }}</span>
</span>
</el-tree>
</div>
</div>
<i slot="reference" class="ico dropDown"></i>
</el-popover>
</div>
<div class="cartTitleDiv">
<el-button type="primary" size="mini" @click="resetData">重置</el-button>
</div>
<div class="cartTitleDiv">
<span class="section-title">搜索文件名:</span>
<el-input
placeholder="输入关键字搜索"
v-model="filtertreeText"
@ -25,25 +83,43 @@
<i slot="prefix" class="el-input__icon el-icon-search"></i>
</el-input>
</div>
<div style="float:right">
<span style="float: left;line-height: 35px; font-weight:normal; font-size: 14px;">文件类型:</span>
<el-select v-model="selectvalue" placeholder="请选择" @change="selcetchangetype" >
<div class="cartTitleDiv">
<span class="section-title">筛选文件类型:</span>
<el-select v-model="selectvalue" placeholder="请选择" @change="selcetchangetype">
<el-option
v-for="item in selectoptions"
:key="item.value"
:label="item.label"
:value="item.value" >
:value="item.value">
</el-option>
</el-select>
<el-button type="primary" size="mini" icon="el-icon-arrow-down" v-if="isExpand==false" @click="expandTree">展开</el-button>
<el-button type="primary" size="mini" icon="el-icon-arrow-up" v-if="isExpand==true" @click="foldTree">折叠</el-button>
</div>
</div>
</div>
<div id="processList" v-loading="g_loading" style="width: 100%; height: 100%" >
<!-- 部门信息区域 -->
<div class="section" style="font-size: 14px;border: 0px solid #D4F0FF;background-color: #E6F7FF;padding: 2px;margin-left: 7px;">
<div class="deptInfoDiv" style="padding-left: 4px;">
<i slot="reference" class="ico tips"></i>
<span v-if="doesItExist==true" class="limited-text">已选择</span>
<span v-if="doesItExist==false" class="limited-text">暂无发布部门</span>
</div>
<div class="deptInfoDiv">
<el-tooltip class="item" effect="dark" :content="concatenatedNamesTooltip">
<span class="limited-text">{{concatenatedNames}}</span>
</el-tooltip>
<span>发布的文件(制度总数:{{ policyFileNum }} 流程总数:{{ processFileNum
}}</span>
</div>
<div class="deptInfoDiv-button">
<el-checkbox v-model="checkedInfo" label="隐藏架构" @change="showOrHideInfo" border size="mini"></el-checkbox>
<el-button type="primary" size="mini" icon="el-icon-arrow-down" v-if="isExpand==false && checkedInfo == false" @click="expandTree">展开</el-button>
<el-button type="primary" size="mini" icon="el-icon-arrow-up" v-if="isExpand==true && checkedInfo == false" @click="foldTree">折叠</el-button>
</div>
</div>
<div id="processList" v-loading="g_loading" style="width: 100%;overflow-y:auto;" >
<div class="collspse">
<el-tree
v-if="checkedInfo == false"
:data="options"
:props="defaultProps1"
ref="treeNode"
@ -70,77 +146,59 @@
</label>
</span>
</el-tree>
<el-table v-if="checkedInfo == true"
:show-header ="false"
:data="fitlerNoFrameOptions"
style="width: 100%;height: auto;">
<el-table-column
style="width: 100%;">
<template slot-scope="node">
<a :href="node.row.path" style="color: #2E74B5" target="_blank">
<img src="../apps/com.awspaas.user.apps.yili.integration/static/icon2.png"
v-if="node.row.fileType == 'processFile'"
style="vertical-align: middle; width: 15px;height: 15px;border-radius:100%"/>
<img src="../apps/com.awspaas.user.apps.yili.integration/static/icon1.png"
v-if="node.row.fileType == 'policyFile'"
style="vertical-align: middle; width: 15px;height: 15px;border-radius:100%"/>
<img src="../apps/com.awspaas.user.apps.yili.integration/static/icon4.png"
v-if="node.row.fileType == 'guideFile'"
style="vertical-align: middle; width: 15px;height: 15px;border-radius:100%"/>
<img src="../apps/com.awspaas.user.apps.yili.integration/static/icon3.png"
v-if="node.row.fileType == 'formFile'"
style="vertical-align: middle; width: 15px;height: 15px;border-radius:100%"/>
{{ node.row.name }}
<!--<em style="font-style:normal;margin-left: 100px;float: right;">发布时间:{{node.data.time}}</em><em style="font-style:normal;margin-left: 100px;float: right;">编制人:{{node.data.people}}</em>-->
</a>
</template>
</el-table-column>
</el-table>
</div>
</div>
<div style="text-align: center;position: absolute;width: 68%;top: 13%;z-index: 200;background: #ffffff;height: 500px;line-height: 300px;" v-if="loadding==true">数据加载中...</div>
<div style="text-align: center;position: absolute;width: 78%;top: 19%;z-index: 1200;background: #ffffff;height: 500px;line-height: 300px;" v-if="loading==true">数据加载中...</div>
</div>
<div id="rightDiv" ref="rightHeight">
<div id="rightTop">
<div id="rightBottom">
<div id="infoCart">
<div class="cartTitle" style="margin-bottom:30px">
<span>基本信息</span>
<div class="cartTitle" style="text-align: center;">
<img style="width: 60px;height:60px;" id="currentUserPhoto" :src="userPhoto">
</div>
<div class="cartTab">
<el-button :class="tab===1?'':'is-plain'" @click="navtab(1)" type="success" size="mini">部门信息</el-button>
<el-button :class="tab===2?'':'is-plain'" @click="navtab(2)" type="primary" size="mini" icon="el-icon-search">部门查询</el-button>
<div v-show="tab==1" id="person" v-for="personInfo in personInfos">
<div class="personInfo leftwidth" style="font-weight:bold">{{ personInfo.title}}</div>
<div class="personInfo rightwidth">{{ personInfo.text }}</div>
</div>
<div v-show="tab==2" id="postSearchCart">
<div class="search">
<el-input
placeholder="输入关键字进行过滤"
v-model="filterText" style="width:80%;">
</el-input>
<el-checkbox v-model="checked1" label="全选" border @change="chooseAll" style="float:right;width:18%"></el-checkbox>
</div>
<div class="" style="height: 400px;overflow-y: auto;overflow-x: hidden;">
<el-tree
:data="list"
show-checkbox
ref="tree"
empty-text="该部门下暂无文件"
node-key="ID"
:props="defaultProps"
:filter-node-method="filterNode"
:default-checked-keys="idjson"
@check="handleCheckChange"
>
<span class="custom-tree-node" slot-scope="{ node, data }">
<span :title="node.data.name ">{{ node.data.name }}</span>
</span>
</el-tree>
</div>
</div>
</div>
</div>
</div>
<div id="rightBottom">
<div id="infoCart1">
<div class="cartTitle">
<span>部门流程数据统计</span>
<div class="button-content">
<!-- 查询岗位直接相关文件 -->
<el-button @click="openPersionInfo" type="primary" size="small">
查询岗位直接相关文件
</el-button>
</div>
<div class="cartTab">
<div class="postArea">
<div class="postInfo icon1"><i></i> 制度总数<span> {{ policyFileNum }}</span></div>
<div class="postInfo icon2"><i></i> 流程总数<span> {{ processFileNum }}</span></div>
<div class="postInfo icon3"><i></i> 表单模版<span> {{ formFileNum }}</span></div>
<div class="postInfo icon4"><i></i> 操作指导<span> {{ guideFileNum }}</span></div>
<div style="clear:both; padding: 20px 40px 10px 0; font-size: 14px;
color: #d20000;">
部门视图默认只展示您所在部门发布的文件,更多其他文件可点击“部门查询”查阅
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
@ -157,6 +215,10 @@
name: "Department",
data() {
return {
dialogVisible: false,
newPageUrl: '', // 新页面的 URL可以是相对路径或绝对路径
param1:"",
loading:true,
g_loading: true,
filtertreeText:'',
isExpand:false,
@ -164,6 +226,8 @@
selectoptions: [],
selectvalue: '',
options: [],
noFrameOptions:[],
fitlerNoFrameOptions:[],
defaultkey: [],
defaultProps1: {
children: 'children',
@ -171,6 +235,8 @@
},
tab: 1,
personInfos: [],
userPhoto:'',
departmentId:'',
// 右侧部门树数据
list: [],
defaultProps: {
@ -184,19 +250,88 @@
guideFileNum: '',//操作指导数量
formFileNum: '',//表单/模板数量
treelist: [],
treeListNodes: [],//选择树的中文集合
idjson:[],
checked1:false//选中状态
checkedInfo:false,
checked1:false,//选中状态
concatenatedNamesTooltip:'暂无发布部门',
doesItExist:false
};
},
mounted(){
this.$nextTick(() => {
debugger;
this.treelist = this.$refs.tree.getCheckedKeys()
this.treeListNodes = this.$refs.tree.getCheckedNodes();
});
},
computed: {
concatenatedNames() {
const filterOutChildren = (nodes) => {
// 创建一个集合来存储需要保留的节点ID
const toKeep = new Set();
// 递归函数,用于检查节点是否应被保留
function shouldKeep(node) {
// 如果节点ID已在toKeep中则无需再次检查
if (toKeep.has(node.ID)) return true;
// 遍历所有节点包括当前节点的子节点检查当前节点是否在其他节点的children中
for (const otherNode of nodes) {
if (otherNode.children && otherNode.children.some(child => child.ID === node.ID)) {
// 如果当前节点是某个节点的子节点,则不保留
return false;
}
}
// 如果节点通过了所有检查则添加到toKeep集合中
toKeep.add(node.ID);
return true;
}
// 遍历所有节点,检查并标记哪些节点应该被保留
for (const node of nodes) {
shouldKeep(node);
}
// 根据toKeep集合过滤出需要保留的节点
const filteredNodes = nodes.filter(node => toKeep.has(node.ID));
filteredNodes.sort((a, b) => a.TLEVEL - b.TLEVEL);
return filteredNodes;
};
if(this.treeListNodes.length === 0){
return '';
}
const processedNodes = filterOutChildren(this.treeListNodes);
let names = processedNodes.map(node => node.name).join(',');
if (names === '') {
names = '';
this.doesItExist = false;
this.concatenatedNamesTooltip = "暂无发布部门";
}else{
this.doesItExist = true;
this.concatenatedNamesTooltip = names;
names +=":";
}
if (names.length > 10) {
// 这里简单地在第10个字符后截断并添加省略号
return names.slice(0, 10) + '...';
}
return names;
}
},
created() {
this.rightTreedatabind()
this.rightTreedatabind();
this.setDefault();
this.leftTreedatabind();
},
watch: {
filtertreeText(val){
this.$refs.treeNode.filter(val)
if(this.checkedInfo==true){
this.fitlerNoFrameOptions = this.noFrameOptions.filter(option => {
return option.name.toLowerCase().includes(val.toLowerCase());
});
}else{
this.$refs.treeNode.filter(val);
}
},
filterText(val) {
this.$refs.tree.filter(val);
@ -209,8 +344,7 @@
this.roleList = "";
// 判断按钮的状态
if (this.checked1) {
loadding=true;
this.loading=true;
// 设置
this.$refs.tree.setCheckedNodes(this.list);
} else {
@ -221,7 +355,7 @@
this.selectdept = JSON.stringify(this.treelist)
this.options = []
if (this.treelist.length == 0) {
this.selectdept = ''
this.selectdept = []
}
this.leftTreedatabind()
},
@ -231,7 +365,13 @@
if(this.filtertreeText == ""){
return
}else{
this.$refs.treeNode.filter(this.filtertreeText)
if(this.checkedInfo==true){
this.fitlerNoFrameOptions = this.noFrameOptions.filter(option => {
return option.name.toLowerCase().includes(this.filtertreeText.toLowerCase());
});
}else{
this.$refs.treeNode.filter(this.filtertreeText);
}
}
},
navtab(e){
@ -262,18 +402,21 @@
//右侧树结构
rightTreedatabind() {
debugger;
let _this = this;
$.ajax({
url: api.rightTreeurl,
data: {},
dataType: "json",
type: "post",
async: true,
async: false,
success: function (res) {
_this.g_loading = false;
loadding=false;
_this.loading=false;
_this.list = res.data.deptTree;
_this.personInfos = res.data.personInfos;
_this.userPhoto = res.data.userPhoto;
_this.departmentId = res.data.departmentId;
if(res.data.fileTypes.length > 0) {
for (let i = 0; i < res.data.fileTypes.length; i++) {
let obj = {
@ -304,34 +447,78 @@
})
.then((res) => {
_this.g_loading = false
loadding=false;
if (res.data.fileMaps.length > 0) {
_this.loading=false;
if(res.data !== undefined){
if (res.data.fileMaps.length > 0) {
_this.options = res.data.fileMaps;
res.data.fileMaps.forEach(element => {
_this.defaultkey.push(element.ID)
});
}
let count = res.data.filesCount;
_this.processFileNum = count.processFileNum
_this.policyFileNum = count.policyFileNum
_this.guideFileNum = count.guideFileNum
_this.formFileNum = count.formFileNum
}
//最后搜索一下
this.search();
_this.options = res.data.fileMaps;
});
},
leftTreedatabindNew() {
let _this = this;
let qs = Qs;
this.options = []
let params = {
dept: _this.selectdept,
fileType: _this.filetype
}
$.ajax({
url: api.leftTreeurl,
method: 'post',
data: qs.stringify(params),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then((res) => {
_this.g_loading = false
_this.loading = false;
if (res.data.fileMaps.length > 0) {
var fileMaps = res.data.fileMaps;
var newMaps =this.filterFileMaps(fileMaps);
//过滤架构的数据
//var newMaps = fileMaps.filter(file => file.nodeType !== 'frame');
_this.noFrameOptions = newMaps;
_this.fitlerNoFrameOptions = newMaps;
res.data.fileMaps.forEach(element => {
_this.defaultkey.push(element.ID)
});
//最后搜索一下
this.search();
}
let count = res.data.filesCount;
_this.processFileNum = count.processFileNum
_this.policyFileNum = count.policyFileNum
_this.guideFileNum = count.guideFileNum
_this.formFileNum = count.formFileNum
});
},
handleCheckChange(data) {
this.treelist = this.$refs.tree.getCheckedKeys()
this.treeListNodes = this.$refs.tree.getCheckedNodes();
this.selectdept = JSON.stringify(this.treelist)
this.options = []
if (this.treelist.length == 0) {
this.selectdept = ''
this.selectdept = []
} else {
this.loading = true;
}
if(this.checkedInfo==true){
this.leftTreedatabindNew();//隐藏架构的
}else{
loadding=true;
}
this.leftTreedatabind()
this.leftTreedatabind();//不需要隐藏架构
}
},
selcetchangetype(e) {
loadding=true;
this.loading=true;
this.filetype = this.selectvalue
this.options = []
this.leftTreedatabind()
@ -344,13 +531,70 @@
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
},
openPersionInfo() {
window.open("./w?sid=" + sid + "&cmd=com.awspaas.user.apps.yili.integration.service.ToPageService_toPersonView");
},
showOrHideInfo() {
this.loading = true;
if(this.checkedInfo==true){
this.leftTreedatabindNew();//隐藏架构的
}else{
this.leftTreedatabind();//不需要隐藏架构
}
},
resetData(){
this.idjson=[];
this.idjson.push(this.departmentId);
this.treelist = this.$refs.tree.getCheckedKeys()
var nodeObj =this.$refs.tree.getNode(this.departmentId);
var nodeArry = [];
nodeArry.push(nodeObj.data)
this.$refs.tree.setCheckedNodes(nodeArry);
this.treeListNodes = this.$refs.tree.getCheckedNodes();
this.selectdept = [];
this.processFileNum = '';//流程数量
this.policyFileNum = '';//制度数量
if(this.checkedInfo==true){
this.leftTreedatabindNew();//隐藏架构的
}else{
this.leftTreedatabind();//不需要隐藏架构
}
},
filterFileMaps(items) {
const result = [];
items.forEach(item => {
if (item.nodeType !== 'frame') {
result.push({ ...item }); // 复制对象以避免直接引用原始对象(可选)
}
if (item.children && item.children.length > 0) {
// 递归调用以处理子对象
const childrenResult = this.filterFileMaps(item.children);
result.push(...childrenResult); // 将子对象的结果合并到当前结果中
}
});
return result;
},
setDefault(){
this.treelist.push(this.departmentId);
this.idjson.push(this.departmentId);
},
openGptHome() {
//let url = "https://chatgpt-uat.dcin-test.digitalyili.com/welcome?from=libchat&lib=ef2b50fd79c52577d51222bc58b231d7&priv=1&sid=" + sid ;
//this.fullscreen = window.innerWidth <= 768; // 小屏幕时全屏显示
this.newPageUrl = "https://yiligpt.x.digitalyili.com/libchat?lib=51682983f4d291acdd6945a9b9e86d5c&priv=1&sid=" + sid;
this.param1=sid;
this.dialogVisible = true;
},
closeDialog() {
this.dialogVisible = false;
}
},
});
</script>
<style scoped>
#main {
margin-top: 20px;
height: 100%;
background: #FFFFFF;
clear: both;
@ -359,7 +603,7 @@
#leftDiv {
height:100%;
float: left;
width: 70%;
width: 80%;
min-height: 810px;
border-right: 10px solid #eeeeee;
padding-right: 20px;
@ -371,7 +615,7 @@
}
#rightDiv {
height: 100%;
width: 29.99%;
width: 19.99%;
float: left;
}
#rightTop {
@ -420,7 +664,6 @@
font-size: 12px;
display: block;
height: 30px;
border-bottom: 1px solid gainsboro;
padding-bottom: 5px;
text-indent: 10px;
}
@ -435,12 +678,11 @@
/deep/ .el-input{width: auto!important;}
.el-input--prefix .el-input__inner{padding-left: 45px; height: 35px;line-height: 35px; width: 90%;}
.el-input__icon{line-height: 35px;}
.el-input--suffix .el-input__inner{ height: 35px;line-height: 35px; width: 90%;}
.el-input--suffix .el-input__inner{ height: 35px;line-height: 35px; width: 100%;}
#postSearchCart .el-input{width: 81%!important;}
.el-input__suffix{right: 25px;}
/* 左侧手风琴样式 */
.el-tree-node{margin-bottom: 5px}
.el-tree-node__content{ background-color: #f1f5fa!important;padding: 4px 10px!important;}
.el-tree-node__content{ background-color: #f1f5fa!important;padding: 6px 10px!important;}
.el-tree-node__children{margin:0 10px; background: #FFFFFF;}
.el-tree-node__children .el-tree-node__content{background: #FFFFFF!important; border-bottom: 1px solid #eceff5}
.custom-tree-node{display: block; width: 100%}
@ -455,7 +697,7 @@
.collspse {
width: 98%;
margin-left: 1.5%;
margin-top: 30px;
margin-top:4px;
}
.collapseIteamTitle {
width: 500px;
@ -488,6 +730,12 @@
line-height: 30px;
font-size: 14px;
}
.custom-dialog .el-dialog__body {
/* 设置高度为 70%,注意这里可能需要额外的 CSS 来处理滚动条和布局问题 */
height: 70vh; /* 使用视口高度viewport height的 70% */
overflow: auto; /* 允许内容滚动 */
}
.postInfo.icon1 i{display: block; width: 32px;height: 32px; float: left; background: url("../apps/com.awspaas.user.apps.yili.integration/static/icon1.png") no-repeat; background-size: 100%;border-radius: 100%; margin-right: 10px}
.postInfo span{display:block;color: #639; font-size: 20px;margin-left: 6px}
.postInfo.icon2 i{display: block; width: 32px;height: 32px; float: left; background: url("../apps/com.awspaas.user.apps.yili.integration/static/icon2.png") no-repeat; background-size: 100%;border-radius: 100%; margin-right: 10px}

View File

@ -0,0 +1,47 @@
@charset "utf-8";
.dropDown{
display: inline-block;
height: 15px;
width: 15px;
background-position: 0px 0px;
background: url(../img/dropDown.png) no-repeat;
background-size: contain;
}
.tips{
display: inline-block;
height: 15px;
width: 15px;
background-position: 0px 0px;
background: url(../img/tips.png) no-repeat;
background-size: contain;
}
.section {
width: 100%;
background-color: #fff;
padding: 6px 6px 3px 6px;
}
.section div{
justify-content: flex-end;
display: inline-block;
line-height: 30px;
padding-right: 20px;
}
.deptInfoDiv-button{
float: right;
}
#processList{
overflow:auto;
flex-grow: 1; /* 撑满剩余空间 */
}
.button-content{
margin-top: 20px;
height: 30px;
line-height: 35px;
display: grid;
place-items: center;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -1634,18 +1634,16 @@ public class DataViewService
currentLoginMap.put("title", "部门");
currentLoginMap.put("text", uc.getDepartmentModel().getPathNameOfCache());
currentLoginMaps.add(currentLoginMap);
currentLoginMap = new LinkedHashMap<>();
currentLoginMap.put("title", "岗位");
currentLoginMap.put("text", uc.getUserModel().getPositionName());
currentLoginMaps.add(currentLoginMap);
ro.put("personInfos", currentLoginMaps);
System.out.println("SDK.getPortalAPI().getUserPhoto(uc, uc.getUID()) = " + SDK.getPortalAPI().getUserPhoto(uc, uc.getUID()));
ro.put("userPhoto",SDK.getPortalAPI().getUserPhoto(uc, uc.getUID()));
ro.put("departmentId",uc.getDepartmentModel().getId());
List<RowMap> deptMaps = DBSql.getMaps("SELECT ID,PARENTDEPARTMENTID,DEPARTMENTNAME,LAYER,ORDERINDEX FROM ORGDEPARTMENT WHERE COMPANYID='8911e732-b42a-4556-853f-ad32761bcbee' AND CLOSED='0' AND DEPARTMENTNAME NOT IN ('澳优','系统管理','项目开发人员部门','奶酪事业部','离退人员部门','集团领导')", new Object[0]);
String nodeType = null;
ArrayList<Map> deptNodes = new ArrayList<>();
for (RowMap deptMap : deptMaps) {