1. 程式人生 > >建立省-市-人員的三級選單

建立省-市-人員的三級選單

由於人員有兩三千,需求要按省-市-人員三級選單展示,便於勾選,起初的想法是ajax獲取使用者資料,然後迴圈按省市構造人員展示結構,但是測試發現數據量過大,導致頁面卡死。無奈只有採用後臺拼接好頁面結構的字串,然後前端獲取資料後在最外層div直接append的方式來提高展示速度。測試兩千多使用者展示在6-7秒。下面是簡要實現方式:

1、前端頁面:

<!DOCTYPE html >
<%@include file="/common/jsp/header.jsp"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>選單首頁</title>
<script type="text/javascript"
	src="${ctx}/webResources/js/jquery-3.3.1.min.js"></script>
<script type="text/javascript"
	src="${ctx}/webResources/bootstrap-3.3.7/js/bootstrap.min.js"></script>
<script type="text/javascript"
	src="${ctx}/webResources/js/jquery.itab.1.2.js"></script>
<script type="text/javascript"
	src="${ctx}/webResources/js/sidebar-menu.js"></script>
<style type="text/css">
	a:link,a:visited{
 text-decoration:none;  /*超連結無下劃線*/
}
a:hover{
 text-decoration:underline;  /*滑鼠放上去有下劃線*/
}
li {list-style-type:none;margin:0px;white-space: nowrap;}
.consureBtn {
	width: 30px;
	height: 25px;
	background: #0188fb;
	border: none;
	color: white;
	margin-left: 0px;
	margin-top:10px;
	position:absolute;
	bottom:0px;
	right:10px;
}
</style>
</head>
<script type="text/javascript">
$(document).ready(function(){
	$("#part1").css("height","397px");
	$(".btn-default").css("margin-top","-10px");
	getUsers();
	});
 	
 	function getUsers(){
		$(".menu ul").css("display","none");
 		$(".menu").html('');
 		//ajax獲取使用者資料
 		var url='showUsers.action';
 		var data={userId:$('#userId').val(),userName:$("#userName").val()};
 		$.ajax({
 			url:url,
 			data:data,
 			dataType:'json',
 			async:false, //必須是同步,否則頁面在資料載入完成前就渲染結束
 			success:function(obj){
 				if(obj.result){
 					var arr=obj.data;
					$(".menuLeft").append(arr);
 				}else{
					alert(obj.message);
				}
 			},
 			error:function(){
 				alert("資料載入失敗");
 			}
 		});
 		initMenu();
 	}
 	
 	/* 放棄這種在頁面迴圈建立html結構的方式,採用後臺直接生成
 		function getUsers(){
		$(".menu ul").css("display","none");
 		$(".menu").html('');
 		var url='showUsers.action';
 		var data={userId:$('#userId').val(),userName:$("#userName").val()};
 		$.ajax({
 			url:url,
 			data:data,
 			dataType:'json',
 			async:false, //必須是同步
 			success:function(obj){
 				if(obj.result){
 					var arr=obj.data;
					for(var i=0;i<arr.length;i++){
					var provEl='<li id="{provSec}"><input class="yeye" type="checkbox" value="selectAll" title="全選" onclick="choseThis(this)">'
			 				+'<a href="###"><img class="jiahao" alt="" src="${ctx}/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;">'
			 				+'<span>{provName}</span></a><ul style="text-align:left;margin-left: -23px;"></ul></li>';
			 		var cityEl='<li  id="{citySec}"><input class="father" type="checkbox" value="selectAll" title="全選" onclick="choseThis(this)">'
			 		        +'<a href="#"><img class="jiahao" alt="" src="${ctx}/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;">'
			 		        +'<span>{cityName}</span></a><ul style="text-align:left;margin-left: -22px;"></ul></li>';
			 		var userEl='<li id="{userId}"><input class="child" type="checkbox" onclick="choseThis(this)"><a href="#">{userName}</a></li>';
			 		var provId=arr[i].provId;
					var provName =arr[i].provName;
					var cityId = arr[i].cityId;
					var cityName=arr[i].cityName;
					var userId=arr[i].userId;
					var userName=arr[i].userName;
						//判斷省份節點是否存在存在就直接新增元素,否則就先建立省份節點再新增元素
						if(!document.getElementById(provId)){
							var str=provEl.replace("{provName}",provName).replace("{provSec}",provId);
							$(".menuLeft").append(str);
							
						}
						if(!document.getElementById(cityId)){
								var str=cityEl.replace("{cityName}",cityName).replace("{citySec}",cityId);
								$("#"+provId).find('ul').eq(0).append(str);
								
							}
						var str=userEl.replace("{userId}",userId).replace("{userName}",userName);
						$("#"+cityId).find('ul').eq(0).append(str);
					}
 				}else{
					alert(obj.message);
				}
 			},
 			error:function(){
 				alert("資料載入失敗");
 			}
 		});
 		initMenu();
 	} */
 	
 	function initMenu(){
    	$(".menu ul").css("display","none");    //檔案準備好後,ul的樣式為隱藏
        $(".menu a").on("click",function(){       //點選a的時候就執行以下函式
           $(this).next().toggle(function(){
           	if($(this).css("display")=='none'){
           		$(this).prev().children(".jiahao").attr("src","{ctx}/common/img/jiahao.png");
           	}else{
           		$(this).prev().children(".jiahao").attr("src","{ctx}/common/img/jianhao.png");
           	}
           });  //toggle提供為隱藏和顯示相互轉換的方法    意思是點選的這個 元素的下一個元素是顯示的話就隱藏,是隱藏的話就顯示
        });
    }
    
</script>
//引如勾選人員的操作js
<script type="text/javascript"
	src="${ctx}/common/js/menuMove.js"></script>
<body> 
	<div id="tree" style="width:600px;text-align:center;">
	<input type='hidden' value='${userId }' id='userId'>
	<div style="width:300px;float:left;border-right:1px solid #ccc;">
	<input type="text"  id="userName" style="width:200px;margin-left:18px;height:20px;padding-left:10px;border:1px solid #C7C7C7;"placeholder="搜尋人員">
	<img src="${ctx }/common/img/sousuo.png"  style="width:20px;height:20px;top:10px;cursor:pointer;position: absolute;margin-top:2px;"  onclick="getUsers();">
	<div class="queryUsers" style="width:230px;margin-top:0px;height:300px;overflow:auto;float:right;margin-right:10px;">
<ul class="menuLeft menu" style="margin-left:-40px;text-align:left;" vlaue='menuLeft'>
<!--  -->
    <%-- <li  id='1'><input class='yeye' type="checkbox"  value="selectAll" title="全選" onclick="choseThis(this)"><a href="###"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>A系統</span></a>
 
        <ul style="text-align:left;margin-left: 103px;">
             <li id='11'><input class='father' type="checkbox"  value="selectAll" title="全選" onclick="choseThis(this)"><a href="#"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>部門1</span></a>
                <ul>
                    <li id='111'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件1</a></li>
                    <li id='112'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件2</a></li>
                </ul>
            </li>
              <li id='12'><input class='father' type="checkbox" id="c1" value="selectAll" title="全選" onclick="choseThis(this)"><a href="#"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>部門1</span></a>
                <ul>
                    <li id='121'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件111111111111111</a></li>
                    <li id='122'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件2</a></li>
                </ul>
            </li>
        </ul>
    </li>
       <li id='2'><input id='' class='yeye' type="checkbox"  value="selectAll" title="全選" onclick="choseThis(this)"><a href="###"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>B系統</span></a>
 
        <ul>
             <li id='21'><input class='father' type="checkbox"  value="selectAll" title="全選" onclick="choseThis(this)"><a href="#"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>部門1</span></a>
                <ul>
                    <li id='211'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件312</a></li>
                    <li id='212'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件321</a></li>
                </ul>
            </li>
              <li id='22'><input class='father' type="checkbox" id="c1" value="selectAll" title="全選" onclick="choseThis(this)"><a href="#"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>部門1</span></a>
                <ul>
                    <li id='221'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件21</a></li>
                    <li id='222'><input class='child' type="checkbox" onclick="choseThis(this)"><a href="#">文件21</a></li>
                </ul>
            </li>
        </ul>
    </li> --%>
        </ul>
</div>
</div>
<div style="width:200px;float:left;">
	<div>
		<span>已選擇的人員</span>
		<img alt="" src="${ctx}/common/img/del.png" style="width:20px;height:20px;position:absolute;right:50px;cursor:pointer;" onmouseover="sureDel(this);" onmouseout="notDel(this);" onclick="deleteUsers();" title='移除'>
	</div>
	<div class="selectedUsers" style="width:250px;margin-top:0px;max-height:300px;overflow-y:auto;float:left;margin-left:25px;">
<ul class="menuRight menu"style="margin-left:-25px;text-align:left;" vlaue='menuRight'>
      <%--  <li><input type="checkbox" id="c1"  value="selectAll" title="全選" onclick="choseThis(this);"><a href="###"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>A系統</span></a>
 
        <ul>
             <li><input type="checkbox" id="c1" value="" title="全選" value="selectAll" onclick="choseThis(this);"><a href="#"><img class="jiahao"alt="" src="${ctx }/common/img/jiahao.png" style="width:15px;height:15px;margin-right:6px;"><span>部門1</span></a>
                <ul>
                    <li><input type="checkbox" onclick="choseThis(this);"><a href="#">文件1</a></li>
                    <li><input type="checkbox" onclick="choseThis(this);"><a href="#">文件2</a></li>
                </ul>
            </li>
           
        </ul>
    </li> --%>
</ul>
</div>
</div>
<div>
<button class="consureBtn " onclick="submitUsers()" id="addUser"
			style="width:80px;">提交</button>
</div>
</div>
</body>
</html>

前端頁面主要分為左右兩部分,左側用於展示使用者,右側展示左側勾選的使用者。

2、引入複製左側結構到右側的menuMove.js

 //聯級選單移動
$(document).ready(function(){
        /*$(".menu ul").css("display","none");    //檔案準備好後,ul的樣式為隱藏
        $(".menu a").on("click",function(){       //點選a的時候就執行以下函式
           $(this).next().toggle(function(){
           	if($(this).css("display")=='none'){
           		$(this).prev().children(".jiahao").attr("src","/${ctx}/common/img/jiahao.png");
           		
           	}else{
           		$(this).prev().children(".jiahao").attr("src","/${ctx}/common/img/jianhao.png");
           	}
           });  //toggle提供為隱藏和顯示相互轉換的方法    意思是點選的這個 元素的下一個元素是顯示的話就隱藏,是隱藏的話就顯示
        });*/
    });
    
	function choseThis(obj) {
		var value = $(obj).attr("value");
		if (obj.checked == false) {
			if(value == 'selectAll'){
				var li=$(obj).parent();
				var checkboxs=li.find("input[type='checkbox']");
				for(var i=0;i<checkboxs.length;i++){
					checkboxs.eq(i).prop('checked',false);
				}
			}
			$(obj).parent().parent().prev().prev().prop("checked",false);
			$(obj).parent().parent().parent().parent().prev().prev().prop("checked",false);
		} else {
			//查詢
			//leftToRight(obj);	
			if (value == 'selectAll') {
				var li=$(obj).parent();
				var checkboxs=li.find("input[type='checkbox']");
				for(var i=0;i<checkboxs.length;i++){
					if(checkboxs.eq(i).prop('checked')){
						continue;
					}
					checkboxs.eq(i)[0].checked=true;
				}
			}
			var ul=$(obj).parent().parent();
			var allLen=ul.find("input[type='checkbox']").length;
			var trueLen=ul
					.find("input[type='checkbox']:checked").length;
			if (allLen==trueLen) {
				ul.prev().prev().prop("checked",true);
			}
			var ulFather=ul.parent().parent();
			if(ulFather.find("input[type='checkbox']").length==ulFather.find("input[type='checkbox']:checked").length){
				ul.parent().parent().prev().prev().prop('checked',true);
			}
			//查詢
			leftToRight(obj);	
		}
	}
	//將左側的人員移到右側
	function leftToRight(obj) {
		var cls=$(obj).attr("class");
		if(cls=='yeye'){
			if($(obj).parent().parent().attr("class").startsWith('menuRight')){
				return;
			}
			var ul=$(obj).parent();
			var id=ul.attr("id");
			var menuRight=$('.menuRight').find('#'+id);
			if(menuRight.length!=0&&menuRight.find('input[type="checkbox"]:checked').length==ul.find('input[type="checkbox"]:checked').length){
				return;
			}
			$('.menuRight').find('#'+id).remove();
			ul=ul.clone(true);
			ul.children('input[type="checkbox"]:checked').prop("checked",false);
			//省下面的li
			ul.find('ul').css('margin-left','-22px');
			//市下面的li
			ul.find('ul').find('li').find('ul').css('margin-left','-22px');
			$('.menuRight').append(ul);
		}else if(cls=='father'){
		if($(obj).parent().parent().parent().parent().attr("class").startsWith('menuRight')){
				return;
			}
			var ulLi=$(obj).parent();
			var li=$(obj).parent().parent().parent();
			var id=li.attr("id");
		 	var ul=$(obj).parent().parent();
			var menuRightLi=$('.menuRight').children('#'+id);
			var id1=ulLi.attr('id');
			if(menuRightLi.length!=0){
				li=$('.menuRight').children('#'+id);
				ul=li.children("ul");
				var childLi=ul.children("#"+id1);
				childLi.remove();
				//console.log('===='+childLi.get(0));
				ulLi=ulLi.clone(true);
				ulLi.children('input[type="checkbox"]:checked').prop('checked',false);
				ul.append(ulLi);
				ulLi=null;
			}else{
			var input=ul.prev().prev().clone(true);
			var a=ul.prev().clone(true);
				li=li.clone(true);
				ul=ul.clone(true);
				ulLi=ulLi.clone(true);
				ulLi.children('input[type="checkbox"]:checked').prop('checked',false);
				//console.log(input.get(0));
				//console.log(a.get(0));
				ul.html(ulLi);
				//console.log(ul.get(0));
				//console.log(ulLi.get(0));
				li.html('');
				li.append(input);
				li.append(a); 
				li.append(ul);
				$('.menuRight').append(li);
				a=input=ul=ulLi=li=null;
			}
			$('.menuRight').find('ul').css('margin-left','-22px');
			$('.menuRight').find('ul').find('li').find('ul').css('margin-left','-22px');
		}else if(cls=='child'){
			if($(obj).parent().parent().parent().parent().parent().parent().attr("class").startsWith('menuRight')){
				return;
			}
			var li=$(obj).parent().clone(true);
			li.children('input[type="checkbox"]:checked').prop('checked',false);
			var ul=$(obj).parent().parent().clone(true);
			var inputChild=$(obj).parent().parent().prev().prev().clone(true);
			var aChild=$(obj).parent().parent().prev().clone(true);
			var ulFather=$(obj).parent().parent().parent().parent().clone(true);
			var input=$(obj).parent().parent().parent().parent().prev().prev().clone(true);
			var a=$(obj).parent().parent().parent().parent().prev().clone(true);
			var liFather=$(obj).parent().parent().parent().clone(true);
			var liYeye=$(obj).parent().parent().parent().parent().parent().clone(true);
			var yeyeId=liYeye.attr("id");
			var righYes=$('.menuRight').children('#'+yeyeId);
			if(righYes.length>0){
				var fatherId=liFather.attr("id");
				var ul1=righYes.children('ul');
				var liFather1=ul1.children('#'+fatherId);
				
				if(liFather1.length>0){
					ul=liFather1.children('ul');
					var id=li.attr('id');
					var li1=ul.children('#'+id);
					if(li1.length>0){
						//如果存在該子節點則無需操作
					}else{
						ul.append(li);
					}
				}else{
				ul.html('');
				ul.append(li);
				liFather.html('');
				liFather.append(inputChild);
				liFather.append(aChild);
				liFather.append(ul);
				ul1.append(liFather);
				}
			}else{
			ul.html('');
			ul.append(li);
			liFather.html('');
			liFather.append(inputChild);
			liFather.append(aChild);
			liFather.append(ul);
			ulFather.html('');
			ulFather.append(liFather);
			liYeye.html('');
			liYeye.append(input);
			liYeye.append(a);
			liYeye.append(ulFather);
			$('.menuRight').append(liYeye);
			}
		li=ul=inputChild=aChild=ulFather=input=a=liFather=liYeye=null;
		}
	}	
	function sureDel(obj) {
		obj.src = '/${ctx}/common/img/del1.png';
	}
	function notDel(obj) {
		obj.src = '/${ctx}/common/img/del.png';
	}
	//將dom元素轉成字串
function domToString (node) {  
     var tmpNode = $('<div></div>');
     tmpNode.append(node.clone(true));
     var str = tmpNode.html();
     tmpNode = node = null; // 解除引用,以便於垃圾回收  
     return str;  
}


function deleteUsers(){
	
	var checkedUsers=$('.menuRight').find('input[type="checkbox"]:checked');
	if(checkedUsers.length==0){
		alert('請選擇需要刪除的人員');
		return;
	}
	//ul:menuLeft
	var leftCheckeds=$('.menuLeft').find('input[type="checkbox"]:checked').parent().parent();
	for(var i=0;i<checkedUsers.length;i++){
		var id=checkedUsers.eq(i).parent().attr('id');
		checkedUsers.eq(i).parent().remove();
		//console.log(leftCheckeds.find('#'+id).attr('id'));
		leftCheckeds.find('#'+id).find('input[type="checkbox"]').prop('checked',false);
		//如果同級中沒有被選擇的checkbox就將父級置為未選擇
		if(leftCheckeds.find('#'+id).parent().find('input[type="checkbox"]:checked').length==0){
			leftCheckeds.parent().parent().find('input[type="checkbox"]').prop('checked',false);
		}
		//如果同級中沒有被選擇的checkbox就將父級置為未選擇
		if(leftCheckeds.find('#'+id).parent().parent().parent().find('input[type="checkbox"]:checked').length==0){
			leftCheckeds.find('#'+id).parent().parent().parent().parent().find('input[type="checkbox"]').prop('checked',false);
		}
	}
}

3、後臺接收ajax請求的java方法,這裡也是重點,需要拼接好三級選單的結構:

首先是查詢資料庫獲取省份Id、省份名稱、地市Id、地市名稱、使用者Id、使用者名稱稱,然後分別將省份、地市和使用者的html結構放到map中用於後面的迴圈拼接。

@RequestMapping("/showUserMenu")
  public void showUsersOutGroup2(String userId,String userName){
      //省去查詢資料的條件部分。。。
      List<Object[]> modelList=this.userDataService.findUsers(paraMap);
      if(modelList.size()==0){
          this.getResponseError("-1", "...");
          return;
      }
      Map<String,Object> mapResults=new HashMap<String,Object>();
      //儲存省-省的html結構的資料
      Map<String,Object> provMap=new HashMap<String,Object>();
      //儲存省-[市-市的html結構]的資料
      Map<String,Map<String,Object>> cityMap=new HashMap<String,Map<String,Object>>();
      //儲存省-[市-[市下面的使用者的html結構列表]]
      Map<String,Map<String,List<String>>> userMap=new HashMap<String,Map<String,List<String>>>();
      for(Object[] o:modelList){
          //Map<String,Object> map=new HashMap<String,Object>();
          String provId="";
          String cityId="";
          if (null==o[3])
          {
              provId="其他";
          }else {
              provId=o[3].toString();
          }
          if (null==o[4])
          {
              cityId="其他";
          }else {
              cityId=o[4].toString();
          }
					//省份的html結構如下,省份的結構裡包含市的
          String provEl="<li id=\""+provId+"\"><input class=\"yeye\" type=\"checkbox\" value=\"selectAll\" title=\"全選\" onclick=\"choseThis(this)\"><a href=\"###\"><img class=\"jiahao\" alt=\"\" src=\"${ctx}/common/img/jiahao.png\" style=\"width:15px;height:15px;margin-right:6px;\"><span>"+provId+"</span></a><ul style=\"text-align:left;margin-left: -23px;\">";
          //市的html結構如下,市的html結構要包含使用者的
          String cityEl="<li  id=\""+cityId+"\"><input class=\"father\" type=\"checkbox\" value=\"selectAll\" title=\"全選\" onclick=\"choseThis(this)\"><a href=\"#\"><img class=\"jiahao\" alt=\"\" src=\"${ctx}/common/img/jiahao.png\" style=\"width:15px;height:15px;margin-right:6px;\"><span>"+cityId+"</span></a><ul style=\"text-align:left;margin-left: -22px;\">";
          //使用者的html結構如下
          String userEl="<li id=\""+o[0].toString()+"\"><input class=\"child\" type=\"checkbox\" onclick=\"choseThis(this)\"><a href=\"#\">"+o[1].toString()+"</a></li>";
          //如果省份map不存在該省份的鍵就直接插入,否則不用插入
          if (!provMap.containsKey(provId))
          {
              provMap.put(provId, provEl);
          }
          //如果地市map沒有該省份的鍵就插入省份資料和新建地市map儲存
          if (!cityMap.containsKey(provId))
          {
              Map<String,Object> cityNode= new HashMap<String,Object>();
              cityNode.put(cityId, cityEl);
              cityMap.put(provId, cityNode);
          }else {
              //如果地市map存在該省份的鍵就獲取該省份對應的地市map並判斷是否已經插入該地市,如果存在就不插入否則就插入
              if (!cityMap.get(provId).containsKey(cityId))
              {
                  cityMap.get(provId).put(cityId, cityEl);
              }
          }
          //預設使用者資料沒有重複,直接插入
          if (null!=userMap.get(provId))
          {
              if (null!=userMap.get(provId).get(cityId))
              {
                  //避免重還是判斷一下存不存在重複
                  if (!userMap.get(provId).get(cityId).contains(userEl))
                  {
                      userMap.get(provId).get(cityId).add(userEl);
                  }
              }else {
                  //如果省份節點存在,地市節點不存在
                  List<String> users=new ArrayList<String>();
                  users.add(userEl);
                  userMap.get(provId).put(cityId, users);
              }
          }else {
              //如果不存在該省份的鍵先建立物件再插入值
              Map<String,List<String>> cityNode= new HashMap<String,List<String>>();
              List<String> users=new ArrayList<String>();
              users.add(userEl);
              cityNode.put(cityId, users);
              userMap.put(provId, cityNode);
          }
      }
      //這個htmlStruc就是拼接的最終要到前端展示的三級選單的結構
      String htmlStruc=createUserStruc(provMap,cityMap,userMap);
      mapResults.put("result", true);
      mapResults.put("data", htmlStruc);
      try {
          response.getWriter().println(JSONObject.fromObject(mapResults));
      } catch (IOException e) {
          e.printStackTrace();
      }
  }
//下面是提取出來的將省市使用者html結構組合起來的方法
//將單獨儲存的省、市、人員html結構組合在一起
public String createUserStruc( Map<String,Object> provMap,Map<String,Map<String,Object>> cityMap,Map<String,Map<String,List<String>>> userMap){
  //下面是拼接整個省-市-使用者的html結構
    StringBuffer sb=new StringBuffer();
    String prov="";
    //遍歷省份節點,拼接每個省份的html結構
    for (Map.Entry<String, Object> provEntry:provMap.entrySet())
    {
        String provId=provEntry.getKey();
        //如果臨時儲存省份id的變數的值和省份map獲取的key不一致說明到下一個省份了這時需要拼接上結束標籤
        if (!provId.equals(prov))
        {
            //prov為空說明還沒拼接前面部分,不需要拼接結束標籤
            if (!"".equals(prov))
            {
                sb.append("</ul></li>");
            }
            prov=provId;
        }
        sb.append(provEntry.getValue());
        //遍歷該省份對應的地市map
        for (Map.Entry<String,Object> cityEntry:cityMap.get(provId).entrySet())
        {
            String cityId=cityEntry.getKey();
            sb.append(cityEntry.getValue());
            //獲取省-市對應的使用者list拼接使用者結構
            List<String> users = userMap.get(provId).get(cityId);
            for (int i = 0; i < users.size(); i++ )
            {
                sb.append(users.get(i));
            }
            sb.append("</ul></li>");
        }
    }
    return sb.toString();
}