数据库树形结构,EasyUI Tree 树

通过 $.fn.tree.defaults 重写默认的 defaults。

树(tree)在网页中以树形结构显示分层数据。它向用户提供展开、折叠、拖拽、编辑和异步加载功能。

image

树的数据格式(Tree Data Format)
每个节点可以包括下列属性:

id:节点的 id,它对于加载远程数据很重要。 --对应id
text:要显示的节点文本。----对应name
state:节点状态,‘open’ 或 ‘closed’,默认是 ‘open’。当设置为 ‘closed’ 时,该节点有子节点,并且将从远程站点加载它们。
checked:指示节点是否被选中。
attributes:给一个节点添加的自定义属性。
children:定义了一些子节点的节点数组。
实例:我们需要这个结构的json

[{
    "id":1,
    "text":"Folder1",
    "iconCls":"icon-save",
    "children":[{
		"text":"File1",
		"checked":true
    },{
		"text":"Books",
		"state":"open",
		"attributes":{
			"url":"/demo/book/abc",
			"price":100
		},
		"children":[{
			"text":"PhotoShop",
			"checked":true
		},{
			"id": 8,
			"text":"Sub Bookds",
			"state":"closed"
		}]
    }]
},{
    "text":"Languages",
    "state":"closed",
    "children":[{
		"text":"Java"
    },{
		"text":"C#"
    }]
}]

###用法比较简单

树(tree)定义在

    元素中。该标记可定义叶节点和子节点。节点将是 ul 列表内的
  • 元素。下面演示了将被用于制作嵌套在 ul 元素内的树节点的元素。

ul id="tt" class="easyui-tree">
    <li>
		<span>Folder</span>
		<ul>
			<li>
				<span>Sub Folder 1</span>
				<ul>
					<li><span><a href="#">File 11</a></span></li>
					<li><span>File 12</span></li>
					<li><span>File 13</span></li>
				</ul>
			</li>
			<li><span>File 2</span></li>
			<li><span>File 3</span></li>
		</ul>
	</li>
    <li><span>File21</span></li>
</ul>

树(Tree)也可以在一个空的

    元素中定义,可使用 javascript 加载数据。

    $('#tt').tree({ url:'tree_data.json' });

    其中 url:‘tree_data.json’ 文档里是写死的获取的是本地的json文件 我们可以写映射地址,获取数据库的信息

    使用 loadFilter 来处理来自 ASP.NET web 服务的 json 数据。

    $('#tt').tree({
        url: ...,
        loadFilter: function(data){
    		if (data.d){
    			return data.d;
    		} else {
    			return data;
    		}
        }
    });
    

    data 就是从后台返回的数据

    具体可以查看Easyui Tree树中文文档:http://www.jeasyui.net/plugins/185.html
    数据库 选用的是 tb_item_cat

    CREATE TABLE `tb_item_cat` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '类目ID',
      `parent_id` bigint(20) DEFAULT NULL COMMENT '父类目ID=0时,代表的是一级的类目',
      `name` varchar(50) DEFAULT NULL COMMENT '类目名称',
      `status` int(1) DEFAULT '1' COMMENT '状态。可选值:1(正常),2(删除)',
      `sort_order` int(4) DEFAULT NULL COMMENT '排列序号,表示同级类目的展现次序,如数值相等则按名称次序排列。取值范围:大于零的整数',
      `is_parent` tinyint(1) DEFAULT '1' COMMENT '该类目是否为父类目,1为true,0为false',
      `created` datetime DEFAULT NULL COMMENT '创建时间',
      `updated` datetime DEFAULT NULL COMMENT '创建时间',
      PRIMARY KEY (`id`),
      KEY `parent_id` (`parent_id`,`status`) USING BTREE,
      KEY `sort_order` (`sort_order`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1183 DEFAULT CHARSET=utf8 COMMENT='商品类目';
    

    image.png

    ###流程

    1.通过parent_id 查询分类的列表

    在item-add.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
    <link href="/js/kindeditor-4.1.10/themes/default/default.css" type="text/css" rel="stylesheet">
    <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script>
    <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script>
    <div style="padding:10px 10px 10px 10px">
    	<form id="itemAddForm" class="itemForm" method="post">
    	    <table cellpadding="5">
    	        <tr>
    	            <td>商品类目:</td>
    	            <td>
    	            	<a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">选择类目</a>
    	            	<input type="hidden" name="cid" style="width: 280px;"></input>
    	            </td>
    	        </tr>
    	        <tr>
    	            <td>商品标题:</td>
    	            <td><input class="easyui-textbox" type="text" name="title" data-options="required:true" style="width: 280px;"></input></td>
    	        </tr>
    	        <tr>
    	            <td>商品卖点:</td>
    	            <td><input class="easyui-textbox" name="sellPoint" data-options="multiline:true,validType:'length[0,150]'" style="height:60px;width: 280px;"></input></td>
    	        </tr>
    	        <tr>
    	            <td>商品价格:</td>
    	            <td><input class="easyui-numberbox" type="text" name="priceView" data-options="min:1,max:99999999,precision:2,required:true" />
    	            	<input type="hidden" name="price"/>
    	            </td>
    	        </tr>
    	        <tr>
    	            <td>库存数量:</td>
    	            <td><input class="easyui-numberbox" type="text" name="num" data-options="min:1,max:99999999,precision:0,required:true" /></td>
    	        </tr>
    	        <tr>
    	            <td>条形码:</td>
    	            <td>
    	                <input class="easyui-textbox" type="text" name="barcode" data-options="validType:'length[1,30]'" />
    	            </td>
    	        </tr>
    	        <tr>
    	            <td>商品图片:</td>
    	            <td>
    	            	 <a href="javascript:void(0)" class="easyui-linkbutton picFileUpload">上传图片</a>
    	                 <input type="hidden" name="image"/>
    	            </td>
    	        </tr>
    	        <tr>
    	            <td>商品描述:</td>
    	            <td>
    	                <textarea style="width:800px;height:300px;visibility:hidden;" name="desc"></textarea>
    	            </td>
    	        </tr>
    	        <tr class="params hide">
    	        	<td>商品规格:</td>
    	        	<td>
    	        		
    	        	</td>
    	        </tr>
    	    </table>
    	    <input type="hidden" name="itemParams"/>
    	</form>
    	<div style="padding:5px">
    	    <a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()">提交</a>
    	    <a href="javascript:void(0)" class="easyui-linkbutton" onclick="clearForm()">重置</a>
    	</div>
    </div>
    <script type="text/javascript">
    	var itemAddEditor ;
    	//页面初始化完毕后执行此方法
    	$(function(){
    		//创建富文本编辑器
    		itemAddEditor = TAOTAO.createEditor("#itemAddForm [name=desc]");
    		//初始化类目选择和图片上传器
    		TAOTAO.init({fun:function(node){
    			//根据商品的分类id取商品 的规格模板,生成规格信息。第四天内容。
    			//TAOTAO.changeItemParam(node, "itemAddForm");
    		}});
    	});
    	//提交表单
    	function submitForm(){
    		//有效性验证
    		if(!$('#itemAddForm').form('validate')){
    			$.messager.alert('提示','表单还未填写完成!');
    			return ;
    		}
    		//取商品价格,单位为“分”
    		$("#itemAddForm [name=price]").val(eval($("#itemAddForm [name=priceView]").val()) * 100);
    		//同步文本框中的商品描述
    		itemAddEditor.sync();
    		//取商品的规格
    		/*
    		var paramJson = [];
    		$("#itemAddForm .params li").each(function(i,e){
    			var trs = $(e).find("tr");
    			var group = trs.eq(0).text();
    			var ps = [];
    			for(var i = 1;i<trs.length;i++){
    				var tr = trs.eq(i);
    				ps.push({
    					"k" : $.trim(tr.find("td").eq(0).find("span").text()),
    					"v" : $.trim(tr.find("input").val())
    				});
    			}
    			paramJson.push({
    				"group" : group,
    				"params": ps
    			});
    		});
    		//把json对象转换成字符串
    		paramJson = JSON.stringify(paramJson);
    		$("#itemAddForm [name=itemParams]").val(paramJson);
    		*/
    		//ajax的post方式提交表单
    		//$("#itemAddForm").serialize()将表单序列号为key-value形式的字符串
    		$.post("/item/save",$("#itemAddForm").serialize(), function(data){
    			if(data.status == 200){
    				$.messager.alert('提示','新增商品成功!');
    			}
    		});
    	}
    	
    	function clearForm(){
    		$('#itemAddForm').form('reset');
    		itemAddEditor.html('');
    	}
    </script>
    
    
    

    在JS中 工具类 common.js

    Date.prototype.format = function(format){ 
        var o =  { 
        "M+" : this.getMonth()+1, //month 
        "d+" : this.getDate(), //day 
        "h+" : this.getHours(), //hour 
        "m+" : this.getMinutes(), //minute 
        "s+" : this.getSeconds(), //second 
        "q+" : Math.floor((this.getMonth()+3)/3), //quarter 
        "S" : this.getMilliseconds() //millisecond 
        };
        if(/(y+)/.test(format)){ 
        	format = format.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 
        }
        for(var k in o)  { 
    	    if(new RegExp("("+ k +")").test(format)){ 
    	    	format = format.replace(RegExp.$1, RegExp.$1.length==1 ? o[k] : ("00"+ o[k]).substr((""+ o[k]).length)); 
    	    } 
        } 
        return format; 
    };
    
    var TT = TAOTAO = {
    	// 编辑器参数
    	kingEditorParams : {
    		//指定上传文件参数名称
    		filePostName  : "uploadFile",
    		//指定上传文件请求的url。
    		uploadJson : '/pic/upload',
    		//上传类型,分别为image、flash、media、file
    		dir : "image"
    	},
    	// 格式化时间
    	formatDateTime : function(val,row){
    		var now = new Date(val);
        	return now.format("yyyy-MM-dd hh:mm:ss");
    	},
    	// 格式化连接
    	formatUrl : function(val,row){
    		if(val){
    			return "<a href='"+val+"' target='_blank'>查看</a>";			
    		}
    		return "";
    	},
    	// 格式化价格
    	formatPrice : function(val,row){
    		return (val/1000).toFixed(2);
    	},
    	// 格式化商品的状态
    	formatItemStatus : function formatStatus(val,row){
            if (val == 1){
                return '正常';
            } else if(val == 2){
            	return '<span style="color:red;">下架</span>';
            } else {
            	return '未知';
            }
        },
        
        init : function(data){
        	// 初始化图片上传组件
        	this.initPicUpload(data);
        	// 初始化选择类目组件
        	this.initItemCat(data);
        },
        // 初始化图片上传组件
        initPicUpload : function(data){
        	$(".picFileUpload").each(function(i,e){
        		var _ele = $(e);
        		_ele.siblings("div.pics").remove();
        		_ele.after('\
        			<div class="pics">\
            			<ul></ul>\
            		</div>');
        		// 回显图片
            	if(data && data.pics){
            		var imgs = data.pics.split(",");
            		for(var i in imgs){
            			if($.trim(imgs[i]).length > 0){
            				_ele.siblings(".pics").find("ul").append("<li><a href='"+imgs[i]+"' target='_blank'><img src='"+imgs[i]+"' width='80' height='50' /></a></li>");
            			}
            		}
            	}
            	//给“上传图片按钮”绑定click事件
            	$(e).click(function(){
            		var form = $(this).parentsUntil("form").parent("form");
            		//打开图片上传窗口(实现多图片上传的功能multiimage)
            		KindEditor.editor(TT.kingEditorParams).loadPlugin('multiimage',function(){
            			var editor = this;
            			editor.plugin.multiImageDialog({
    						clickFn : function(urlList) {
    							var imgArray = [];
    							KindEditor.each(urlList, function(i, data) {
    								imgArray.push(data.url);
    								form.find(".pics ul").append("<li><a href='"+data.url+"' target='_blank'><img src='"+data.url+"' width='80' height='50' /></a></li>");
    							});
    							form.find("[name=image]").val(imgArray.join(","));
    							editor.hideDialog();
    						}
    					});
            		});
            	});
        	});
        },
        
        // 初始化选择类目组件
        initItemCat : function(data){
        	$(".selectItemCat").each(function(i,e){
        		var _ele = $(e);
        		if(data && data.cid){
        			_ele.after("<span style='margin-left:10px;'>"+data.cid+"</span>");
        		}else{
        			_ele.after("<span style='margin-left:10px;'></span>");
        		}
        		_ele.unbind('click').click(function(){
        			$("<div>").css({padding:"5px"}).html("<ul>")
        			.window({
        				width:'500',
        			    height:"450",
        			    modal:true,
        			    closed:true,
        			    iconCls:'icon-save',
        			    title:'选择类目',
        			    onOpen : function(){
        			    	var _win = this;
        			    	$("ul",_win).tree({
        			    		url:'/item/cat/list',
        			    		animate:true,
        			    		onClick : function(node){
        			    			if($(this).tree("isLeaf",node.target)){
        			    				// 填写到cid中
        			    				_ele.parent().find("[name=cid]").val(node.id);
        			    				_ele.next().text(node.text).attr("cid",node.id);
        			    				$(_win).window('close');
        			    				if(data && data.fun){
        			    					data.fun.call(this,node);
        			    				}
        			    			}
        			    		}
        			    	});
        			    },
        			    onClose : function(){
        			    	$(this).window("destroy");
        			    }
        			}).window('open');
        		});
        	});
        },
        
        createEditor : function(select){
        	return KindEditor.create(select, TT.kingEditorParams);
        },
        
        /**
         * 创建一个窗口,关闭窗口后销毁该窗口对象。<br/>
         * 
         * 默认:<br/>
         * width : 80% <br/>
         * height : 80% <br/>
         * title : (空字符串) <br/>
         * 
         * 参数:<br/>
         * width : <br/>
         * height : <br/>
         * title : <br/>
         * url : 必填参数 <br/>
         * onLoad : function 加载完窗口内容后执行<br/>
         * 
         * 
         */
        createWindow : function(params){
        	$("<div>").css({padding:"5px"}).window({
        		width : params.width?params.width:"80%",
        		height : params.height?params.height:"80%",
        		modal:true,
        		title : params.title?params.title:" ",
        		href : params.url,
    		    onClose : function(){
    		    	$(this).window("destroy");
    		    },
    		    onLoad : function(){
    		    	if(params.onLoad){
    		    		params.onLoad.call(this);
    		    	}
    		    }
        	}).window("open");
        },
        
        closeCurrentWindow : function(){
        	$(".panel-tool-close").click();
        },
        
        changeItemParam : function(node,formId){
        	$.getJSON("/item/param/query/itemcatid/" + node.id,function(data){
    			  if(data.status == 200 && data.data){
    				 $("#"+formId+" .params").show();
    				 var paramData = JSON.parse(data.data.paramData);
    				 var html = "<ul>";
    				 for(var i in paramData){
    					 var pd = paramData[i];
    					 html+="<li><table>";
    					 html+="<tr><td colspan=\"2\" class=\"group\">"+pd.group+"</td></tr>";
    					 
    					 for(var j in pd.params){
    						 var ps = pd.params[j];
    						 html+="<tr><td class=\"param\"><span>"+ps+"</span>: </td><td><input autocomplete=\"off\" type=\"text\"/></td></tr>";
    					 }
    					 
    					 html+="</li></table>";
    				 }
    				 html+= "</ul>";
    				 $("#"+formId+" .params td").eq(1).html(html);
    			  }else{
    				 $("#"+formId+" .params").hide();
    				 $("#"+formId+" .params td").eq(1).empty();
    			  }
    		  });
        },
        getSelectionsIds : function (select){
        	var list = $(select);
        	var sels = list.datagrid("getSelections");
        	var ids = [];
        	for(var i in sels){
        		ids.push(sels[i].id);
        	}
        	ids = ids.join(",");
        	return ids;
        },
        
        /**
         * 初始化单图片上传组件 <br/>
         * 选择器为:.onePicUpload <br/>
         * 上传完成后会设置input内容以及在input后面追加<img> 
         */
        initOnePicUpload : function(){
        	$(".onePicUpload").click(function(){
    			var _self = $(this);
    			KindEditor.editor(TT.kingEditorParams).loadPlugin('image', function() {
    				this.plugin.imageDialog({
    					showRemote : false,
    					clickFn : function(url, title, width, height, border, align) {
    						var input = _self.siblings("input");
    						input.parent().find("img").remove();
    						input.val(url);
    						input.after("<a href='"+url+"' target='_blank'><img src='"+url+"' width='80' height='50'/></a>");
    						this.hideDialog();
    					}
    				});
    			});
    		});
        }
    };
    
    

    其中

    // 初始化选择类目组件
        initItemCat : function(data){
        	$(".selectItemCat").each(function(i,e){
        		var _ele = $(e);
        		if(data && data.cid){
        			_ele.after("<span style='margin-left:10px;'>"+data.cid+"</span>");
        		}else{
        			_ele.after("<span style='margin-left:10px;'></span>");
        		}
        		_ele.unbind('click').click(function(){
        			$("<div>").css({padding:"5px"}).html("<ul>")
        			.window({
        				width:'500',
        			    height:"450",
        			    modal:true,
        			    closed:true,
        			    iconCls:'icon-save',
        			    title:'选择类目',
        			    onOpen : function(){
        			    	var _win = this;
        			    	$("ul",_win).tree({
        			    		url:'/item/cat/list',
        			    		animate:true,
        			    		onClick : function(node){
        			    			if($(this).tree("isLeaf",node.target)){
        			    				// 填写到cid中
        			    				_ele.parent().find("[name=cid]").val(node.id);
        			    				_ele.next().text(node.text).attr("cid",node.id);
        			    				$(_win).window('close');
        			    				if(data && data.fun){
        			    					data.fun.call(this,node);
        			    				}
        			    			}
        			    		}
        			    	});
        			    },
        			    onClose : function(){
        			    	$(this).window("destroy");
        			    }
        			}).window('open');
        		});
        	});
        },
        
        createEditor : function(select){
        	return KindEditor.create(select, TT.kingEditorParams);
        },
    
    

    这个部分用到的异步的ajax 我们做的目的是 点击后弹出的窗口 跟后台数据库获取数据

    有url 的映射地址 我们就可以写controller

    在数据库里 写一下sql语句 查询 parent_id =1 的类目
    image.png

    对应com.foreknow.mapper包下 TbItemMapper.xml 的实现类 sql 写法

    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Long" >
      select 
      <include refid="Base_Column_List" />
      from tb_item_cat
      where id = #{id,jdbcType=BIGINT}
    </select>
    
    

    json 为了转格式 在foreknow-common 下 com.foreknow.common.pojo包
    创建 EUTreeNdode.java

    package com.foreknow.common.pojo;
    /**
    树的数据格式(Tree Data Format)
    每个节点可以包括下列属性:
    
    id:节点的 id,它对于加载远程数据很重要。
    text:要显示的节点文本。
    state:节点状态,'open' 或 'closed',默认是 'open'。当设置为 'closed' 时,该节点有子节点,并且将从远程站点加载它们。
     * @author Administrator
     *
     */
    public class EUTreeNdode {
    
    	private  long id;
    	private String text;
    	private String state;
    	public long getId() {
    		return id;
    	}
    	public void setId(long id) {
    		this.id = id;
    	}
    	public String getText() {
    		return text;
    	}
    	public void setText(String text) {
    		this.text = text;
    	}
    	public String getState() {
    		return state;
    	}
    	public void setState(String state) {
    		this.state = state;
    	}
    	
    }
    
    

    ###然后写业务层 service ItemCatService.java

    package com.foreknow.service;
    
    import java.util.List;
    
    import com.foreknow.common.pojo.EUTreeNdode;
    
    public interface ItemCatService {
    /**
     * 根据patentId查询分类
     * 
     * @param patentId
     * @return
     */
    	public  List<EUTreeNdode> getCatList(long patentId);
    }
    
    
    

    返回值是EUTreeNdode.java 对应的Json 属性

    我根据id 查出来的是多条数据,而且 我们的json 格式里没有List集合 所以跟之前的分页查询 rows 和total 不一样 我们这次返回值是 List

    然后写实现类ItemCatServiceImpl.java

    
    package com.foreknow.service.impl;
    /**
     * 树形
     */
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import com.foreknow.common.pojo.EUTreeNdode;
    import com.foreknow.mapper.TbItemCatMapper;
    import com.foreknow.pojo.TbItemCat;
    import com.foreknow.pojo.TbItemCatExample;
    import com.foreknow.pojo.TbItemCatExample.Criteria;
    import com.foreknow.service.ItemCatService;
    @Service
    public class ItemCatServiceImpl implements ItemCatService {
    
    	@Autowired
    	private TbItemCatMapper tbItemCatMapper;
    	
    	@Override
    	public List<EUTreeNdode> getCatList(long parentId) {
    		TbItemCatExample example = new TbItemCatExample();
    //		Criteria  根据条件查询   封装好的方法 parent_id
    		Criteria criteria = example.createCriteria();
    		criteria.andParentIdEqualTo(parentId);
    		List<TbItemCat> list = tbItemCatMapper.selectByExample(example);
    		//我们返回的是list  创建一个list
    		List<EUTreeNdode> resultList = new ArrayList<>();
    		//对原有的 list  进行便利   没便利一次  就拿到一个TbItemCat cat
    		for (TbItemCat cat : list) {
    			EUTreeNdode node = new EUTreeNdode();
    			//要把list里赋值   保存到resultList 里
    			node.setId(cat.getId());
    			node.setText(cat.getName());
    			//三元运算符?  两种状态
    			node.setState(cat.getIsParent()?"closed":"open");
    			resultList.add(node);
    		}
    		return resultList;
    	}
    
    }
    
    

    方法在com.foreknow.pojo 用自动生成工具生成的

    TbItemCat.java 和TbItemCatExample.java 条件

    其中TbItemCatExample.java 中image.png
    我们给的条件不是id 是 parent_id

    TbItemCat.java中 private Boolean isParent; 属性 能获取到parent boolen类型

    最后写ItemCatController.java 映射地址 对应 comment.js 后台的取json的

    package com.foreknow.controller;
    
    import java.util.List;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.foreknow.common.pojo.EUTreeNdode;
    import com.foreknow.service.ItemCatService;
    
    
    @Controller
    @RequestMapping("/item/cat")
    public class ItemCatController {
    	@Autowired
    	private ItemCatService itemCatService;
    	
    	@RequestMapping("/list")
    	@ResponseBody
    	//restful  判断一下  如果要是没拿到的话  我们加一个默认值  是0  
    	public List<EUTreeNdode> getCatList(@RequestParam(value="id",defaultValue="0") long parentId) {
    		List<EUTreeNdode> list = itemCatService.getCatList(parentId);
    		return list;
    	}
    
    }
    
    

    ###最后更新一下工程
    输入http://localhost:8088/index
    image.png

    image.png

    猜你喜欢

    转载自blog.csdn.net/qq_30225725/article/details/86655933
    今日推荐