版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36476972/article/details/79394201
实现一个类似于钉钉审批人员选择的功能。
这里使用zTree实现组织架构树。
实体类需要有id,pId实现上下级关系。
company.java getter/setter略。
private int company_id;//公司id
private String company_name;//公司名称
private String remark;//备注信息
private String foundTime;//成立时间
private int company_pid;//上级id
private 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; //部门id
private String dept_name;//部门名称
private String name;//部门别名
private int company_id;//所属公司id
private String remark;//备注信息
private int dept_pid;//上级部门id
private 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;//id
private String job_name ;//职务名称
private int job_pid;//上级id
private int dept_id;//所属公司
private int status;
private String name;
private int id;
private int pid;
private int c_id;//公司id
private String c_name;//公司名
private int c_pid;//公司上级id
private int d_id;//部门id
private String d_name;//部门名
private int d_pid;//部门上级id
private 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})
@ResponseBody
public 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分级实现,并对集合数据做去空处理,最终显示为树结构,然后做勾选判断。
最终效果