Java+zTree审批人员选择

article/2025/7/12 17:11:20

实现一个类似于钉钉审批人员选择的功能。

这里使用zTree实现组织架构树。

实体类需要有id,pId实现上下级关系。

company.java getter/setter略。

private int company_id;//公司idprivate String company_name;//公司名称private String remark;//备注信息private String foundTime;//成立时间private int company_pid;//上级idprivate int user_id;private String name;private int dept_id;private String dept_name;private int id;private int pid;private List<Company> companyChildren=new ArrayList<>();private List<Dept> deptChildren=new ArrayList<>();private String pCName;//上级名称private List<Company> children = new ArrayList<>();

dept.java

private int dept_id; //部门idprivate String dept_name;//部门名称private String name;//部门别名private int company_id;//所属公司idprivate String remark;//备注信息private int dept_pid;//上级部门idprivate String company_name;private int id;private int pid;private List<Dept> deptChildren=new ArrayList<>();private List<Job> jobChildren=new ArrayList<>();private List<Dept> children=new ArrayList<>();private String pName;//上级部门

job.java

private int job_id;//idprivate String job_name ;//职务名称private int job_pid;//上级idprivate int dept_id;//所属公司private int status;private String name;private int id;private int pid;private int c_id;//公司idprivate String c_name;//公司名private int c_pid;//公司上级idprivate int d_id;//部门idprivate String d_name;//部门名private int d_pid;//部门上级idprivate String d_pName;//部门上级名称private String j_pName;//上级职位private String remark;//备注信息private List<Dept> jobDeptChildren=new ArrayList<>();private List<Job> jobChildren=new ArrayList<>();private List<User> userChildren=new ArrayList<>();private List<Job> children=new ArrayList<>();

user.java 根据自己的需求写吧,字段太多这里就不写了。

框架使用SSM,数据库MySQL。使用mybatis实现一对多。

companyMapper.java

List<Company> queryZtreeCompanyListByPid();

companyMapper.xml

<!-- 总公司 --><resultMap id="companyTop" type="com.ys.entity.Company"><result column="id" property="id" javaType="java.lang.Integer"/><result column="name" property="name" javaType="java.lang.String"/><result column="pid" property="pid" javaType="java.lang.Integer"/><result column="foundTime" property="foundTime" javaType="java.lang.String"/><!-- 总公司 - 部门 --><collection column="id" property="deptChildren" javaType="java.util.ArrayList" select="queryDeptByCompanyId"></collection><!-- 总公司 - 分公司 --><collection column="id" property="companyChildren" javaType="java.util.ArrayList" select="queryCompanyChildren"></collection></resultMap><!-- 总公司-部门 --><resultMap type="com.ys.entity.Dept" id="companyChildrenDept"><result column="id" property="id" javaType="java.lang.Integer"/><result column="name" property="name" javaType="java.lang.String"/><result column="id" property="id" javaType="java.lang.Integer"/><result column="company_id" property="company_id" javaType="java.lang.Integer"/><!--部门-子部门 --><collection column="{id=id,company_id=company_id}" property="deptChildren" javaType="java.util.ArrayList" select="queryDeptChildrenByDeptId"></collection><!--部门-职位 --><collection column="id" property="jobChildren" javaType="java.util.ArrayList" select="queryDeptChildrenJobByDeptId"></collection></resultMap><!-- 部门-职位 --><resultMap type="com.ys.entity.Job" id="deptChildrenJob"><result column="id" property="id" javaType="java.lang.Integer"/><result column="name" property="name" javaType="java.lang.String"/><result column="pid" property="pid" javaType="java.lang.Integer"/><result column="dept_id" property="dept_id" javaType="java.lang.Integer"/><!--职位 - 人员 --><collection column="id" property="userChildren" javaType="java.util.ArrayList" select="queryjobChildrenUserByJobId"></collection></resultMap><!--职位 - 人员 --><resultMap type="com.ys.entity.User" id="jobChildrenUser"><result column="id" property="id" javaType="java.lang.Integer"/><result column="name" property="name" javaType="java.lang.String"/><result column="userName" property="userName" javaType="java.lang.String"/><result column="jobNumber" property="jobNumber" javaType="java.lang.Integer"/><result column="touxiang" property="touxiang" javaType="java.lang.String"/></resultMap><!-- 总公司 --><select id="queryZtreeCompanyListByPid" resultMap="companyTop">select company_id as id , company_name as name , company_pid as pid ,foundTime from sys_company where company_pid=0</select><!-- 总公司 - 部门 --><select id="queryDeptByCompanyId" resultMap="companyChildrenDept">select dept_id as id,dept_name as name,dept_pid as pid ,company_id from sys_dept where dept_pid=0 and company_id=#{id}</select><!-- 部门-子部门 --><select id="queryDeptChildrenByDeptId" resultMap="companyChildrenDept">select dept_id as id,dept_name as name,dept_pid as pid ,company_id from sys_dept where dept_pid=#{id} and company_id=#{company_id}</select><!-- 部门-职位 --><select id="queryDeptChildrenJobByDeptId" resultMap="deptChildrenJob">select job_id as id ,job_name as name, job_pid as pid ,dept_id from sys_job where dept_id=#{id}</select><!--职位 - 人员 --><select id="queryjobChildrenUserByJobId" resultMap="jobChildrenUser">select user_id as id,name,userName,jobNumber,touxiang from sys_user where job_id=#{id}</select><!-- 分公司 --><resultMap id="companyChildren" type="com.ys.entity.Company"><result column="id" property="id" javaType="java.lang.Integer"/><result column="name" property="name" javaType="java.lang.String"/><result column="pid" property="pid" javaType="java.lang.Integer"/><result column="foundTime" property="foundTime" javaType="java.lang.String"/><!-- 分公司-部门 --><collection column="{id=id,pid=pid}" property="deptChildren" javaType="java.util.ArrayList" select="queryDeptByCompanyChildrenId"></collection></resultMap><!-- 分公司 --><select id="queryCompanyChildren" resultMap="companyChildren">select company_id as id , company_name as name , company_pid as pid ,foundTime from sys_company where company_pid=#{id} and company_pid!=0</select><!-- 分公司 - 部门 --><select id="queryDeptByCompanyChildrenId" resultMap="companyChildrenDept">select dept_id as id,dept_name as name,dept_pid as pid ,company_id from sys_dept where company_id=#{id} and dept_pid=(select dept_id from sys_dept where dept_pid=0 and company_id=#{pid})</select>

这里是一对多的查询,网上有很多类似的讲解很容易理解。

接着是companyService.java

public List<Company> queryZtreeCompanyListByPid(){return mapper.queryZtreeCompanyListByPid();}

companyController.java

@RequestMapping(value="queryCompanyOneToMany",method={RequestMethod.GET,RequestMethod.POST})@ResponseBodypublic List<Company> queryZtreeCompanyListByPid(){return  service.queryZtreeCompanyListByPid();}

接下来是JSP,前端框架是layui 。引入zTree的JS/CSS、layui的JS/CSS。

<link type="text/css" rel="stylesheet" href="${ctxStatic}/zTree/css/metroStyle/metroStyle.css"/>
<!-- zTree的核心库 -->
<script type="text/javascript" src="${ctxStatic}/zTree/js/jquery.ztree.core.min.js"></script>
<!-- zTree的复选框 -->
<script type="text/javascript" src="${ctxStatic}/zTree/js/jquery.ztree.excheck.min.js"></script>
<script type="text/javascript" src="${ctxStatic}/zTree/js/jquery.ztree.exedit.min.js"></script>
<style type="text/css">
.layui-form-pane .layui-form-label{width:130px;
}.auItem{min-width:550px;
}
.approval{width:85px;
}
.approval p{width:100%;height:59px;cursor:pointer;overflow:hidden;text-align: center;
}
.approval p img{min-width:50px;min-height:50px;width:55px;height:55px;border: 2px solid #00c0ef;
}
.approval p:hover img:first-child{display:none;
}
.add img{min-width:50px;min-height:50px;width:55px;height:55px;cursor: pointer;
}
.approval span,.add span{display: block;text-align:center;font-size:14px;
}
</style>
<fieldset class="layui-elem-field"><legend>审批人</legend><div class="layui-field-box"><!-- 添加审批人 --><div class="layui-form-item auItem"><div class="layui-inline approvalUsers"></div><div class="layui-inline add"><img src="${ctxStatic}/images/addUser.png" class="layui-circle"><span>添加</span></div></div></div>
</fieldset>

然后是JS代码。

function openTree2(){var index2=layer.open({type: 1,title: "审批人",closeBtn: 2,shadeClose: false,area: ['300px','80%'],content: '<div class="zTreeDemoBackground left"><ul id="ztree2" class="ztree"> </ul></div>',          btn: ['确定', '取消'],yes:function (index2,value) {getChildNodes2();layer.close(index2);},success:function(){
//            layer.alert('',{skin: 'layui-layer-molv',icon:7,closeBtn: 1,anim:3,btn:['知道了','关闭']});if(window.sessionStorage.getItem("layFlag")=="false" || window.sessionStorage.getItem("layFlag")==undefined){var con= layer.confirm('多选审批人请务必顺序选择!', {btn: ['不再提示','关闭'] //按钮,icon:7,anim:3 }, function(){window.sessionStorage.setItem("layFlag","true");layer.close(con);}, function(){window.sessionStorage.setItem("layFlag","false");});}}});var zTreeObj;//树属性的定义  var setting = {//页面上的显示效果  view: {  selectedMulti: false}, check : {  enable: true,chkboxType: { "Y": "", "N": "" }},callback:{beforeCheck: zTreeBeforeCheck,//选中之前  判断onCheck: zTreeOnCheck,getChildNodes2:getChildNodes2}};var checkNode2;function zTreeBeforeCheck(treeId, treeNode) {if(treeNode.jobNumber==undefined || treeNode.jobNumber==null || treeNode.jobNumber==0){layer.msg('此节点不是用户节点,不可选中!',{icon:2,time:2000,shift:6});return false;}else{if(treeNode.id==$('#userId').val()){layer.msg('审批人不能选择自己!',{icon:2,time:2000,shift:6});return false;} }};function zTreeOnCheck(event, treeId, treeNode) {var treeObj = $.fn.zTree.getZTreeObj("ztree2");var nodes = treeObj.getCheckedNodes(true);checkNode2=nodes;};var zNodes;$.ajax({async:false,cache:false,type:'post',dataType:'json',url:getPath+'queryCompanyOneToMany',success:function(data){deleteEmptyProperty(data);zNodes=data;}});function deleteEmptyProperty(object){for (var i in object) {var value = object[i];if (typeof value === 'object') {if (Array.isArray(value)) {if (value.length == 0) {//alert(object[i]);delete object[i];continue;}else{ var a=[];if(i=='jobChildren'){for (var j = 0; j < object[i].length; j++) {a.push(object[i][j]);}delete object[i];}else if(i=='userChildren'){for (var j = 0; j < object[i].length; j++) {a.push(object[i][j]);}delete object[i]; }else if(i=='deptChildren'){for (var j = 0; j < object[i].length; j++) {a.push(object[i][j]);}delete object[i]; }else if(i=='companyChildren'){for (var j = 0; j < object[i].length; j++) {a.push(object[i][j]);}delete object[i]; }else if(i=='jobDeptChildren'){for (var j = 0; j < object[i].length; j++) {a.push(object[i][j]);}delete object[i];}if(a.length>0&&object["children"]!=undefined){for (var k = 0; k < object["children"].length; k++) {a.push(object["children"][k]);}object["children"]=a;}else if(a.length>0 && object["children"]==undefined){object["children"]=a;} }}deleteEmptyProperty(value);if (isEmpty(value)) {delete object[i];}} else {if (value === '' || value === null || value === undefined) {delete object[i];} else {}}}}function isEmpty(object) {for (var name in object) {return false;}return true;}$(function() {  $.fn.zTree.init($("#ztree2"), setting, zNodes);  var treeObj = $.fn.zTree.getZTreeObj("ztree2");treeObj.expandAll(true);});function getChildNodes2(){if(checkNode2.length>0){var html="";var length=$('.approvalUsers div').length+1;//console.log((length+checkNode.length));if((length+checkNode2.length)<12){for (var i = 0; i < checkNode2.length; i++) {var img=(checkNode2[i].touxiang=='' || checkNode2[i].touxiang==null || checkNode2[i].touxiang==undefined) ? getPath+"static/images/NoImg.png" : checkNode2[i].touxiang;if($('.approvalUsers div').length==0){html+='<div class="layui-inline approval" id="approval'+(length+i)+'">'+'<p>'+'<img src="'+img+'" class="layui-circle">'+'<img src="'+getPath+'static/images/removeUser.png" class="layui-circle">'+'</p>'+'<span>'+checkNode2[i].name+'</span>'+'<input type="hidden" name="approval_user_id'+(length+i)+'" value="'+checkNode2[i].id+'" lay-verify="required">'+'</div>';}else{var inputV=[];$('.approvalUsers div').each(function(){inputV.push(Number($(this).find('input').val()));});if(inputV.length>0 && $.inArray(checkNode2[i].id,inputV)!=-1){layer.msg('审批人已存在,不可添加',{icon:5,shift:6,time:1000},function(){html="";return false;});break;}else{html+='<div class="layui-inline approval" id="approval'+(length+i)+'">'+'<p>'+'<img src="'+img+'" class="layui-circle">'+'<img src="'+getPath+'static/images/removeUser.png" class="layui-circle">'+'</p>'+'<span>'+checkNode2[i].name+'</span>'+'<input type="hidden" name="approval_user_id'+(length+i)+'" value="'+checkNode2[i].id+'" lay-verify="required">'+'</div>';}}}if(html!=""){$('.approvalUsers').append(html); }if($('.approvalUsers div').length==10){$('.add').hide();}}else{layer.msg('人数溢出,最多可添加'+(11-length)+'人!',{icon:5,shift:6,time:2000});}}};
};$('.add').click(function(){openTree2();
})
$(document).on('click','.approval p img',function(){removeApprovalUser($(this));
});
function removeApprovalUser(_this){var div=_this.parent().parent();var length=div.parent().find('div').length+1;div.remove(); var name=div.find('input').attr('name');var index=Number(name.substring(name.length-1,name.length));for(var i=index+1,j=length;i<j;i++){var img=$("#approval"+i+"").find('p img:eq(0)').attr('src');var thisName=$("#approval"+i+"").find('span').text();var inputVal=$("#approval"+i+"").find('input').val();$("#approval"+i+"").replaceWith('<div class="layui-inline approval" id="approval'+(i-1)+'">'+'<p>'+'<img src="'+img+'" class="layui-circle">'+'<img src="'+getPath+'static/images/removeUser.png" class="layui-circle">'+'</p>'+'<span>'+thisName+'</span>' +'<input type="hidden" name="approval_user_id'+(i-1)+'" value="'+inputVal+'" lay-verify="required">'+'</div>');}if(length<12){$('.add').show();}
};

这里审批人可以多选,最终以顺序显示,最多为十个人,可以根据实际情况更改代码。

其中 deleteEmptyProperty(object) 函数用于处理后台返回的集合数据,这个数据是不能直接显示为树结构的,需要对其结构处理。更改为zTree可以实现分级的结构 ,这里以children分级实现,并对集合数据做去空处理,最终显示为树结构,然后做勾选判断。

最终效果
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述


http://chatgpt.dhexx.cn/article/YlAcjPBH.shtml

相关文章

element-tree 实现部门-人员选择(支持ID相同)

使用element-tree实现id相同的选择 相同人员可在不同部门出现, 当勾选其中一个人员时,其它部门的相同人员也要勾选上右侧可进行删除已勾选人员, 并且树状图勾选状态取消若有勾选,进入时候默认选中 效果如下: 例如: 点击勾选总经办的王五,技术部的王五也要勾选上,右侧删除王五…

【Mobile Org】适用于移动端/H5的组织部门/角色/人员选择组件

Mobile Org Introduction 移动端组织架构数据选择方案&#xff0c;包括组织机构、角色以及人员等分类&#xff0c;支持单选、多选、关键字段自定义以及多种事件及插槽等&#xff0c;适用于大部分组织选人场景。 支持懒加载回调&#xff0c;点击获取当前组织下的子组织及人员…

使用VUE自定义组件封装部门选择功能

背景 照惯例&#xff0c;先交待下背景&#xff0c;从真实需求出发&#xff0c;讲述实现效果、设计思路和实现方式。 软件系统中&#xff0c;会有一些常见常用的选择功能&#xff0c;如部门选择、人员选择等&#xff0c;用于填报表单&#xff0c;使用频率很高。直接使用一方面会…

选择部门(多层级)下人员

一、顶部部门选中标题栏&#xff08;部门面包屑&#xff09; 1.使用水平滚动的ListView&#xff08;HorizontalListView&#xff09;&#xff0c;代码搜索一下就能找到&#xff0c; 2.右监听可以使用符号文字>&#xff08;代码&#xff1a;>&#xff09;&#xff0c;也…

阿里云成立13年首次实现年度盈利;iPhone14有望实现息屏显示;Android 13将采用华为研发的只读文件系统 |EA周报...

EA周报 2022年5月27日 每个星期7分钟&#xff0c;元宝带你喝一杯IT人的浓缩咖啡&#xff0c;了解天下事、掌握IT核心技术。 周报看点 1、成立13年首次年度盈利&#xff0c;阿里云2022财年赚11亿 2、博通官宣610亿美元收购VMware 3、Android 13 将默认采用华为开发的只读文件系统…

【ELT.ZIP】OpenHarmony啃论文俱乐部—数据密集型应用内存压缩

本文出自ELT.ZIP团队&#xff0c;ELT<>Elite(精英)&#xff0c;.ZIP为压缩格式&#xff0c;ELT.ZIP即压缩精英。成员&#xff1a; 上海工程技术大学大二在校生合肥师范学院大二在校生清华大学大二在校生成都信息工程大学大一在校生黑龙江大学大一在校生华南理工大学大一在…

Nydus 镜像扫描加速

文&#xff5c;余硕 上海交通大学22届毕业生 阿里云开发工程师 从事云原生底层系统的开发和探索工作。 本文 6369 字 阅读 16 分钟 GitLink 编程夏令营是在 CCF 中国计算机学会指导下&#xff0c;由 CCF 开源发展委员会&#xff08;CCF ODC&#xff09;举办的面向全国高校学生的…

定了,6大领域93个开源任务,阿里开源导师带你参与中科院开源之夏2022

今年&#xff0c;由阿里巴巴开源导师参与的30个核心开源社区再次加入中国科学院软件研究所开源软件供应链点亮计划支持下的系列高校开源活动——开源之夏2022&#xff0c;共开放93个开源任务。通过本活动&#xff0c;同学们可以在顶级开源导师的指导下&#xff0c;通过3个月的时…

龙蜥操作系统 Anolis OS 8.6 - 来自阿里云的 CentOS 8 100% 兼容发行版

请访问原文链接&#xff1a;https://sysin.org/blog/anolis-os-8/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org Anolis OS 8 是 OpenAnolis 社区推出的完全开源、中立、开放的发行版&#xff0c;它支持多计算架构&#x…

remove是什么意思计算机语言,remove是什么意思?remove是什么意思?

remove()是C语言中的函数&#xff0c;一般作用是删除数组、链表对象所有的元素。函数原型是intremove(char*filename)。 函数功能 remove()函数用于删除指定的文件&#xff0c;其原型如下&#xff1a; int remove(char *filename); 函数声明2&#xff1a; templateinline bool …

Linux 知:文件系统

文章目录 1. 前言2. 文件2.1. 一切皆文件2.2. 文件属性2.3. 目录结构2.4. 文件路径 3. 文件系统3.1. 文件系统种类3.2. 文件系统特性3.2.1. 格式化3.2.2. 格式 3.3. EXT 族文件系统3.3.1. EXT2 文件系统3.3.1.1. data block&#xff08;数据区块&#xff09;3.3.1.2. inode tab…

8 亿邮件地址泄露,源于邮件验证服务;腾讯推出微信公众号直播工具

(给技术最前线加星标&#xff0c;每天看技术热点) 转自&#xff1a;开源中国、solidot、cnBeta、腾讯科技、快科技等 【技术资讯】 0、8 亿邮件地址遭泄露&#xff0c;源于邮件验证服务 近日&#xff0c;Security Discovery 安全研究人员 Bob Diachenko 发现了一个150 GB 大小、…

LWN: 5.17 合并窗口第一部分!

关注了就能看到更多这么棒的文章哦&#xff5e; 5.16 Merge window, part 1 By Jonathan CorbetNovember 4, 2021DeepL assisted translationhttps://lwn.net/Articles/874683/ 截止到撰写此文的时候&#xff0c;Linus Torvalds 已经为 5.16 版本内核而向内核合入了 6800 个 no…

Linux出现Read-only file system错误解决方法

执行命令时遇到如下错误 这个问题是文件系统受损导致得&#xff0c;fstab文件未正确配置 解决方法&#xff1a; df -hT  #查看一下分区及挂载信息 fsck -a /dev/sda3  -a &#xff1a;检查文件系统&#xff0c;有异常便自动修复 执行完毕之后重启服务器 reboot 进入服务器&…

只需 6 步,你就可以搭建一个云原生操作系统原型

编者按&#xff1a;过去的三年对基础软件领域来说是不平凡的三年&#xff0c;是波涛汹涌的三年。随着国际形势和行业格局的变化&#xff0c;大家一定充分感受到了云原生和操作系统这两个话题的热度。那么当云原生和操作系统这两个热点话题相遇的时候&#xff0c;会发生什么故事…

Linux 内核源代码情景分析(四)

系列文章目录 Linux 内核设计与实现 深入理解 Linux 内核 Linux 设备驱动程序 Linux设备驱动开发详解 深入理解Linux虚拟内存管理 Linux 内核源代码情景分析&#xff08;一&#xff09; Linux 内核源代码情景分析&#xff08;二&#xff09; Linux 内核源代码情景分析&#xff…

TWS蓝牙耳机推荐哪个?2022国产无线蓝牙耳机推荐

随着各大手机厂商逐渐取消了传统的耳机插孔后&#xff0c;就有越来越多的人开始使用蓝牙耳机了。即使是过去一直觉得蓝牙耳机不太实用&#xff0c;最后也无法摆脱“真香理论”&#xff01;&#xff01;在蓝牙技术的快速发展的今天&#xff0c;蓝牙耳机在连接性能和音质方面取得…

女生小清新高颜值蓝牙耳机分享,低延迟高性价比TWS蓝牙耳机推荐

在电子竞技空前火热的今天,玩家对于游戏耳机的要求不仅仅停留在能听见声音的层面。特别是目前比较火热的射击类游戏对于游戏耳机的要求更加高,一款出色的游戏耳机可以让玩家在战场上“如虎添翼”,不仅如此,对于玩家而言,游戏时间基本两三个小时起步,因此长期佩戴的舒适性…

真无线蓝牙耳机什么牌子好?TWS蓝牙耳机推荐

蓝牙耳机的形态可以说是多种多样了&#xff0c;随着时代的发展&#xff0c;蓝牙耳机变成了我们不可或缺的东西&#xff0c;左右耳两只小小的耳机&#xff0c;搭配一个耳机仓。整个过程仅需要打开蓝牙就行&#xff0c;非常方便。那么在蓝牙耳机的带领下&#xff0c;什么款式的蓝…

2022TWS蓝牙耳机推荐,盘点600元真无线蓝牙耳机

近年来&#xff0c;随着蓝牙技术的发展和续航能力的提升&#xff0c;蓝牙耳机开始进入了"真"无线时代。在短短的几年内&#xff0c;TWS耳机成为了大家竞相占领的重要“城池”&#xff0c;各类蓝牙耳机如雨后春笋般出现。今天就来说说被各大网友推荐上榜单的音质好的蓝…