ExtJS中的树的使用和总结

ExtJS中的树的使用和总结

一.TreePanel 配置参数:

root:Ext.tree.TreeNode 		//根节点
loader:Ext.tree.TreeLoader 	//数据加载器
checkModel:"single" 		//复选框只能单选,多选为:multiple,级联:cascade  
trackMouseOver:false 		//是否只有叶子节点可选
rootVisible:false 			//false不显示根节点,默认为true
autoScroll:true 			//超过范围自动出现滚动条
animate:true 				//展开和收缩时的动画效果
enableDrag:true 			//树的节点可以拖动,注意不是Draggable
enableDD:true 				//不仅可以拖动,还可以通过Drag改变节点的层次结构(drap和drop)
enableDrop:true 			//仅仅drop
lines:true 					//节点间的虚线条
useArrows:true 				//侧三角,false则为"+-"

二.TreeNode的基本配置参数:

id:"id"						//节点ID
text:"节点文本" 			//节点显示的文本
cls:"folder/file"			//节点显示的样式:文件夹或文件
pid:"id"					//父节点的ID
leaf:true 					//是否是叶子节点
expanded:fasle 				//是否展开,默认不展开
checked:false 				//true则在text前有个选中的复选框,false则text前有个未选中的复选框,默认没有任何框框
href:"http://www.123.com"	//节点的链接地址
hrefTarget:"mainFrame" 		//打开节点链接地址默认为blank,可以设置为iframe名称id,则在iframe中打开
qtip:"提示" 				//提示信息,不过要有Ext.QuickTips.init();
singleClickExpand:true 		//用单击文本展开,默认为双击

三.树节点的数据分析:

1.节点数据分为父节点和子节点,父节点需要以文件夹形式显示。

2.子节点与父节点的关联通过pid实现

例如:

[
  {
    "id": "01",
    "text": "企业科",
    "cls": "folder",
    "children": [
      {
        "id": "qyk1",
        "text": "企业科一号用户",
        "cls": "file",
        "pid": "01",
        "leaf": true,
        "autoid": 0,
        "expanded": false
      },
      {
        "id": "qyk2",
        "text": "企业库二号用户",
        "cls": "file",
        "pid": "01",
        "leaf": true,
        "autoid": 0,
        "expanded": false
      }
    ],
    "leaf": false,
    "autoid": 0,
    "expanded": false
  }
]

注意一些属性名称:

 

四.实例分析:

1.创建触发域:

var selectedAuditRow;//定义全局变量————获取点击列表某一行时通过复选框获得的行号。  
     
/*1.创建触发域*/  
var auditTrigger = new Ext.form.TriggerField({  
    emptyText:"请选择...",  
    allowBlank:false,  
    readOnly:true,  
    onTriggerClick:function(e){    //单击触发按钮触发的事件  
        selectedAuditRow = auditSm.getSelected();  
        auditTreeWin.show();  
        auditRoot.reload();     //每次点击触发域时重新加载树
    }  
});  

2.创建Record:

/*2.创建Record*/  
var auditRecord = new Ext.data.Record.create([  
    {name:"did",type:"string"},  
    {name:"dname",type:"string"},  
    {name:"sdid",type:"string"},  
    {name:"sdname",type:"string"},  
    {name:"title",type:"string"},  
    {name:"orderid",type:"int"},  
    {name:"auditUserId",type:"string"}
]);

3.创建Store:

/*3.创建Store*/  
var auditStore = new Ext.data.Store({  
    url:"getAuditDetail.up?doType=getAuditDetail",  
    reader: new Ext.data.JsonReader({  
        root:"data"  
    },auditRecord)  
});

4.创建表格复选框和ColumnModel:

/*4.创建ColumnModel*/ 
var auditSm = new Ext.grid.CheckboxSelectionModel();
var auditCm = new Ext.grid.ColumnModel({
    columns:[
        auditSm,
        {
            header:"编号",
            dataIndex:"id",
            hidden:true
        },{
            header:"部门编号",
            dataIndex:"did",
            hidden:true
        },{
            header:"部门名称",
            dataIndex:"dname",
            width:170,
            renderer:function(v){
                return dname;
            }
        },{
            header:"科室编号",
            dataIndex:"sdid",
            hidden:true
        },{
            header:"科室名称",
            dataIndex:"sdname",
            width:170,
            renderer:function(v){
                return sdname;
            }
        },{
            header:"流程名称",
            dataIndex:"title",
            editor:new Ext.form.TextField({   
                id:"title"  
            }),
            width:190
        },{
            header:"流程顺序",
            dataIndex:"orderid",
            width:140
        },{
            id:"auditUserId",
            header:"审核用户ID",
            dataIndex:"auditUserId",
            editor:auditTrigger,
            width:195
        }
    ]
});

5.创建GridPanel:

/*5.创建GridPanel*/ 
var auditGrid = new Ext.grid.EditorGridPanel({
title:"审核流程明细",
store:auditStore,
cm:auditCm,
sm:auditSm,
border:true,
bodyBorder:true,
split: true,
clicksToEdit:1,    
stripeRows: true,//斑马线
loadMask:{msg:"正在加载数据,请稍后......"},
height:250,
tbar:[
    {  
        text:"保存流程",  
        iconCls:"save",
        handler:saveAuditDetail
    },{  
        text:"增加流程",  
        iconCls:"add",  
        handler:function(){  
            if(sdid == 0) {
                Ext.Msg.alert("系统提示","请先选择科室再增加审核流程");
                return;
            }
            var newAudit = new auditRecord({   //此处创建新的Record  
                    did:did,//此处的did,dname,sdid,sdname是全局变量,在其他地方赋值,此处不详述
                    dname:dname,
                    sdid:sdid, 
                    sdname:sdname,
                    title:'',  
                    orderid:order,  
                    auditUserid:''
                });  
                auditGrid.stopEditing();         //关闭表格的编辑状态  
                auditStore.add(newAudit);  
                auditGrid.startEditing(0, 0);    //激活第一行第一列的编辑状态  
        }
    },{  
        text:"删除流程",  
        iconCls:"remove",
        handler:removeAuditDetail
    }  
      ]
});

6.创建树:

/*6.创建树*/  
//6.1 定义根节点  
var auditRoot = new Ext.tree.AsyncTreeNode({  
    id:'tree-root',  
    text:"部门",  
    expanded:true,    //根节点默认展开(注意和TreePanel中的rootVisible:true的联系)
    draggable:false   //根节点不可拖动  
});  
//6.2 定义节点数据加载器  
var auditLoader = new Ext.tree.TreeLoader({  
    dataUrl:'getKeshiUsersByGrade.up?doType=getKeshiUsersByGrade',  //此处不是url,和Store的Proxy不同  
    baseParams :{pid:''},  
    baseAttrs:{uiProvider:Ext.tree.TreeCheckNodeUI} //必须有该项,不然树节点无法出现选择框  
});  
//6.3 定义数据加载前触发方法  
auditLoader.on("beforeload",function(treeLoader,node){  
    auditRoot.setText(dname);     //加载前重新设置树的根节点的名称
    treeLoader.baseParams.pid = node.id;  
    treeLoader.baseParams.did = did;  //加载前给定pid和did参数
},this);  

//6.4 定义树形面板,用于显示数据  
var auditTree = new top.Ext.tree.TreePanel({    /**注意top!!!*/  
    root:auditRoot,      //根节点  
    loader:auditLoader,  //数据加载器  
    checkModel:"single", //复选框只能单选,多选为:multiple,级联:cascade  
    rootVisible:true,    //显示根节点  
    autoScroll:true,      
    animate:false,  
    enableDD:false,      //不允许子节点拖动  
    onlyLeafCheckable:true,  
    /* trackMouseOver:false,
    useArrows:true, */
    width:250,  
    listeners:{"click":function(node){  
        if(!node.isLeaf()){   
            node.toggle(); //点击可展开可收缩  
        }else{
	node.ui.toggleCheck();
}   
    }}  
});  

注意:

1.树的加载器里必须加上uiProvider,用于显示复选框

 

2.加载前传入参数,在后台通过request.getParameter("param")方式获取

 

后台取数:

 

7.创建存放树的窗口:

var auditTreeWin = new top.Ext.Window({    /**注意top!!!*/  
    title:"用户选择",  
    layout:"fit",  
    closeAction:"hide",  
    modal:true,  
    width:250,  
    height:250,  
    items:auditTree,  
    buttons:[  
        {  
            text:"确定",  
            handler:function(e){  /*点击选择树节点并将值显示在触发域的方法!*/
                var node = auditTree.getChecked();    //获取被选中的树节点  
                if(!node || node.length < 1){  
                    top.Ext.Msg.alert("系统提示","请选择用户!");  
                    return;  
                }  
                var name = new Array();  
                var value = new Array();  
                for (var i = 0; i < node.length; i++) {  
                    name.push(node[i].text);  
                    value.push(node[i].id);  
                }  
                var data = selectedAuditRow.data;    //获取选择的行的Record的Data数据对象  
                /*data["auditUserId"]= name.join(); —— —— 此处用这种方式给触发域赋值出错!!!必须用下面的方式!!! */    
                auditTrigger.setValue(name.join());  
                auditTreeWin.hide();  
            }  
        },{  
            text:"取消",  
            handler:function(){  
                auditTreeWin.hide();  
            }  
        }  
    ]  
});  

注意:此处的树窗口和树面板需要加上“top”,否则无法显示。




 

8.创建单击触发域显示树窗口并显示选中项被勾选的方法:

/* 单击触发域打开树窗口并显示勾选项 */
auditTrigger.onTriggerClick = clickTriggerFun;
function clickTriggerFun(e){
	auditTreeWin.show();
	var parentNodes = auditRoot.childNodes;
	if(parentNodes.length > 0) {
		showCheckedNode(parentNodes);
	}
	else {
		loadTree();//节点为0,则先加载树
	}
}

/* 加载科室用户并勾选对应项 */
function loadTree(){
	auditLoader.on("load",function(treeLoader,node){
		showCheckedNode(node.childNodes);
	});
}

/* 勾选对应的选中项,并展开选中项的父目录 */
function showCheckedNode(parentNodes){
	//先展开再收缩父节点,让子节点充分显示
	for (var i = 0; i < parentNodes.length; i++) {
		parentNodes[i].expand();
		parentNodes[i].collapse();
	}
	//先循环清楚全部勾选项
	for (var i = 0; i < parentNodes.length; i++) {
		var childNodes = parentNodes[i].childNodes;
		for (var j = 0; j < childNodes.length; j++) {
			childNodes[j].ui.toggleCheck(false);
		}
	}
	//将触发域中的内容字符串分割为一个数组
	var tgValue = auditTrigger.getValue();
	childNodes = auditRoot.childNodes;
	var checkedArr = null;
	if(tgValue != null) {
		checkedArr = tgValue.split(",");
	}
	//循环对比,相对应的进行勾选
	if(checkedArr != null && checkedArr.length > 0) {
		for (var i = 0; i < parentNodes.length; i++) {
			var childNodes = parentNodes[i].childNodes;
			for (var j = 0; j < childNodes.length; j++) {
				var text = childNodes[j].text;
				for (var k = 0; k < text.length; k++) {
					if(checkedArr[k] == text) {
						childNodes[j].ui.toggleCheck(true);//勾选
						childNodes[j].parentNode.expand();//展开父节点
					}
				}
			}
		}
	}
}

9.创建保存科室审核流程明细的方法,只保存修改过的信息:

/*创建保存科室审核流程明细的方法,只保存修改过的信息*/  
function saveAuditDetail(){  
    var rcds = auditStore.getModifiedRecords();     //获取修改过的记录集Records  
    if(rcds&&rcds.length>0){  
        Ext.Msg.wait("正在保存...");  
        var rows=new Array();  
        for(var i=0;i<rcds.length;i++){  
            var rs = rcds[i];    //获取指定下标的某一行的记录Record  
            var row=new Object();  
            var fields=rs.data;    //获取该行记录的数据Data  
            row = {did:fields.did,sdid:fields.sdid,title:fields["title"],orderid:fields["orderid"],auditUserId:fields["auditUserId"]};  
            rows.push(row);    //注意此处获取属性方式:obj.id或者obj["id"]皆可  
        }                      //因为此处obj是data,是一个对象,这些id,name都是data的属性  
                               //如果直接用record,则可以用它在Extjs中定义的get方法:rs.get("id")  
        Ext.Ajax.request({     
            url: 'updateAuditDetail.up?doType=updateAuditDetail',     
            method:'POST',  
            timeout:30000,    
            success: result,  
            failure: function(){Ext.Msg.alert('失败','未成功提交数据!'); },  
            params:{updateSets :Ext.encode(rows)}   //将数组转化为JSON字符串
        });  
        function result(response, options){  
            var result = Ext.util.JSON.decode(response.responseText);  
            if(result.success){  
                Ext.Msg.hide();  
                Ext.Msg.show({  
                        title:'成功',  
                        msg: '数据保存成功',  
                        buttons: Ext.Msg.OK,  
                        icon: Ext.MessageBox.INFO  
                });   
                //保存成功后刷新修改过的脏数据。  
                auditStore.rejectChanges();  
                auditStore.reload();  
           }else{  
              Ext.Msg.hide();  
              Ext.Msg.alert('失败','保存数据未成功!');  
           }  
        }   
    }  
}  

注意:Ext.encode(arr)方法可将数组转化为JSON字符串

 

10.创建删除科室审核流程明细的方法,删除复选框勾选的记录:

/*创建删除科室审核流程明细的方法,删除复选框勾选的记录*/  
function removeAuditDetail(){  
    var rcs = auditGrid.getSelectionModel().getSelections();  
    if(!rcs||rcs.length<1){  
        Ext.Msg.alert("提示","请先选择要删除的行");  
        return;  
    }  
    else{  
        Ext.Msg.confirm("确认删除","请确认是否删除选中的科室审核流程明细?",function(btn){  
            if(btn == "yes"){//选中"是"的按钮  
                Ext.Msg.wait("正在删除...");  
                var ids = new Array();  
                for (var i = 0; i < rcs.length; i++) {  
                    ids.push(rcs[i].get("id"));  
                }  
                //异步发请求  
                Ext.Ajax.request({  
                    url:"deleteAuditDetails.up?doType=deleteAuditDetails",  
                    method:"POST",  
                    params:{auditIds:ids.join(",")},  
                    success:function(response,option){  
                        var result = Ext.decode(response.responseText);  
                        if (result.success) {  
                            Ext.Msg.alert("成功","选中的科室审核流程明细已成功删除!");  
                            auditStore.rejectChanges();  
                            auditStore.reload();  
                        }  
                    },  
                    failure:function(response,option){  
                        Ext.Msg.alert("失败","删除过程中发生错误!");  
                    }  
                });  
            }  
        });  
    }  
}  

注意:Ext.decode(jsonStr)方法可将JSON字符串转化为对象或数组

 

11.查询、保存(更新)、删除的Servlet:

if ("getAuditDetail".equals(action)) {  //查询
    String sdid = request.getParameter("sdid");
    UserPostDao userPostDao = new UserPostDao();
    List auditDetails = userPostDao.getKeshiAuditDetailsBySdid(sdid);
    String data = JSON.toJSONString(auditDetails);  //集合转Json字符串
    json = "{\"data\":" + data + "}"; 
    response.setContentType("text/json;charset=UTF-8");  
    out = response.getWriter();  
    out.print(json);        
    out.close();
    return;
}else if("updateAuditDetail".equals(action)){  //保存(更新)
    UserPostDao userPostDao = new UserPostDao();
    String sData = request.getParameter("updateSets");
    List<KeshiAuditDetail> auditDetails = JSON.parseArray(sData, KeshiAuditDetail.class);  //字符串转集合
    boolean done = userPostDao.updateKeshiAuditDetails(auditDetails);
    String str=null;
    if(done){
        str="{success:true}";
    }else{
        str="{success:false}";
    }
    response.setContentType("text/html;charset=UTF-8");
    out=response.getWriter();
    out.print(str);     
    out.close();
    return;
}else if("deleteAuditDetails".equals(action)){   //删除
    String ids = request.getParameter("auditIds");
    UserPostDao userPostDao = new UserPostDao();
    boolean done = userPostDao.deleteAllKeshiAuditDetails(ids);
    String str =null;
    if(done){
        str="{success:true}";
    }else{
        str="{success:false}";
    }
    response.setContentType("text/html;charset=UTF-8");
    out=response.getWriter();
    out.print(str);     
    out.close();
    return;
}

注意:

1.用FastJsontoJSONString(obj/list);方法可以将对象或集合转化为相应的Json字符串

Dao方法获取数据的方式不同将导致转化的数据不同:

(1).普通集合:——错误方式

List list = query.list();
//获取到的是一堆Object数组的集合,Object数组没有属性——即没有键值对,所以转化的json字符串为非键值对格式的错误Json格式的字符串

转化的Json数据为:

[{0,"01",0,0,1,"企业科",0},{0,"qyk1",0,1,2,"企业科一号用户","01",0}]

(2).指定对象的集合:——正确方式

List<KeshiAuditDetail> auditDetails = query.addEntity(KeshiAuditDetail.class).list();

转化的Json数据为:

[
  {
    "autoid": 0,
    "bm": "01",
    "expand": 0,
    "isLeaf": 0,
    "level": 1,
    "mc": "企业科",
    "selected": 0
  },
  {
    "autoid": 0,
    "bm": "qyk1",
    "expand": 0,
    "isLeaf": 1,
    "level": 2,
    "mc": "企业科一号用户",
    "pid": "01",
    "selected": 0
  }
]

 
2.用FastJsonJSON.parse(jsonStr);方法可将Json字符串转化为对象
3.用FastJsonJSON.parseArray(jsonStr, T.class);方法可将Json字符串转化为指定类的集合

 

五.树节点数据的获取和解析:

1.用于从数据库获取分级数据的实体类:

/**
 * 用于从数据库获取分级数据,
 * 并作为等待解析的树节点数据的实体类
 */
public class SimpleBean {
    private String bm;      //id
    private String mc;      //text
    private String pid;     //关联的父节点ID
    private String href;
    private int level;      //节点所在层次;
    private int isLeaf;     //节点是否是叶子节点;
    private int selected;   //节点是否被选择;
    private String target;  //链接打开的位置
    private int expand;     //描述树节点时,表示是否展开
    private long autoid;
    ......
    ...
    ..
}

2.获取并解析树节点数据的Servlet:

if("getKeshiUsersByGrade".equals(action)){//按级别
    String jsonStr="";
    TreeDao tdao=new TreeDao();
    UserPostDao userPostDao = new UserPostDao();
    String did = request.getParameter("did")==null?"0":request.getParameter("did");
    //分级加载参数pid和loadAll的设置:
    String pid=request.getParameter("pid")==null?"":request.getParameter("pid");
    if(pid!=null&&(pid.startsWith("tree-root")||pid.startsWith("p-tree-root"))){
        pid="";//首次加载时,从根目录加载,pid为根节点AsyncTreeNode的id!
    }
    String sloadAll=request.getParameter("loadAll");
    int loadAll = 1;//loadAll:1:一次性全部加载,0:分级加载(点击树目录时加载)
    if (sloadAll != null && !sloadAll.equals("")) {
        loadAll=Integer.parseInt(sloadAll);
    }
    //获取数据并转化为树的格式的json数据:
    if ("".equals(pid) ) {
        List items = userPostDao.getKeshiUsersByGrade(did, pid, loadAll);
        //JSON.toJSONString(items);  转化后的是普通的Json格式数据,而非树所规定的Json格式
        jsonStr=tdao.getTreeNodesOfJson(items,loadAll,pid);
    }
    response.setContentType("text/json;charset=UTF-8");
    out=response.getWriter();
    out.print(jsonStr);     
    out.close();
    return;
}

3.Dao——获取分级数据:

/**
 * 获取科室用户制度树,按级别分类
 * @param pid
 * @param loadAll
 * @return
 */
public List getKeshiUsersByGrade(String did,String pid,int loadAll){
    List nodes=null;
    Session session = null;
    try{
        session =HibernateUtil.getSession();
        session.beginTransaction(); 
        StringBuffer treeSql = new StringBuffer("select * from(select bm,mc,pid,isleaf,level from(");
        treeSql.append(" select sdid as bm,sdname as mc, null as pid, 0 as isleaf from sub_department where pdid = ");
        treeSql.append(did);    
        treeSql.append(" union select u.userid as bm, u.name as mc, k.sdid as pid, 1 as isleaf from users u join user_keshi k on u.userid = k.userid");
        treeSql.append(" )connect by prior bm=pid start with pid is null )");
        if(loadAll==0){//分级加载
            if (pid == null||"".equals(pid))
                treeSql.append(" WHERE PID IS NULL ");
            else
                treeSql.append(" WHERE PID='").append(pid).append("'");
        }
        nodes = session.createSQLQuery(treeSql.toString())
        .addScalar("bm")
        .addScalar("pid")
        .addScalar("mc")
        .addScalar("isLeaf",Hibernate.INTEGER)
        .addScalar("level",Hibernate.INTEGER)
        .setResultTransformer(Transformers.aliasToBean(SimpleBean.class)).list();
        //此处直接用query.addEntity(SimpleBean.class);应该亦可,未验证
        session.getTransaction().commit();  
    }catch(Throwable e){
        log.error(e.toString());
        HibernateUtil.endSession(session);
    }finally{
        HibernateUtil.endSession(session);
    }
    return nodes;
}

注意:
获取分级数据时,要对获取到的数据的值的格式进行规范。

 

4.解析树节点数据的工具类:

import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
import com.huaxia.entity.SimpleBean;

/**
 * 创建时间: 2014年12月26日 上午11:39:36
 * 类描述:
 */
public class ParseTreeUtil {
    
    /**
     * 树节点的解析
     * @param items     //需要解析的数据集合
     * @param loadAll   //分级加载/一次性加载
     * @param pid       //关联的父节点ID
     * @return
     * @throws Exception
     */
    public String getTreeNodesOfJson(List items,int loadAll,String pid)throws Exception {
        if(items==null)return "";
        JSONArray jItems=new JSONArray();
        try{
            if(loadAll==1){//一次载入,从顶级编码开始,递归的加入子节点
                for(int i=0;i<items.size();i++){
                    SimpleBean oi=(SimpleBean)items.get(i);
                    if(oi.getPid()==null||"".equals(oi.getPid())){
                        jItems.put(parseOptionItem(items,oi,null,0));
                        
                    }
                }
            }else{
                for(int i=0;i<items.size();i++){
                    SimpleBean oi=(SimpleBean)items.get(i);
                    JSONObject ji=new JSONObject();
                    ji.put("id", oi.getBm());
                    ji.put("pid", oi.getPid());
                    ji.put("text", oi.getMc());
                    ji.put("leaf", oi.getIsLeaf()==1);
                    ji.put("cls",oi.getIsLeaf()==1?"file":"folder");
                    ji.put("expanded", oi.getExpand()==1);
                    ji.put("autoid", oi.getAutoid());
                    jItems.put(ji);
                }
            }
        }catch(Exception e){
            throw new Exception("编码解析为JSON格式时发生错误:"+e.toString());
        }
        return jItems.toString();
    }
    
    
    private JSONObject parseOptionItem(List initItems,SimpleBean oi,Map mcids,int checkById)throws Exception{
        if(oi==null){
            return null;
        }
        JSONObject ji=new JSONObject();
        ji.put("id", oi.getBm());
        ji.put("pid", oi.getPid());
        ji.put("text", oi.getMc());
        ji.put("leaf", oi.getIsLeaf()==1);
        ji.put("cls",oi.getIsLeaf()==1?"file":"folder");
        ji.put("expanded", oi.getExpand()==1);
        ji.put("autoid", oi.getAutoid());
        if(mcids!=null){
            if(checkById==1){
                ji.put("checked", mcids.containsKey(String.valueOf(oi.getBm())));
            }else{
                ji.put("checked", mcids.containsKey(String.valueOf(oi.getAutoid())));
            }
        }
        
        //检查当前节点的子节点
        String nextPid=oi.getBm();
        JSONArray cArray=new JSONArray();
        for(int i=0;i<initItems.size();i++){
            SimpleBean item=(SimpleBean)initItems.get(i);
            if(item!=null&&nextPid.equals(item.getPid())){//找到子节点,分别递归形成子节点分支的集合。
                cArray.put(parseOptionItem(initItems,item,mcids,checkById));
            }
        }
        if(cArray.length()>0){
            ji.put("children", cArray);
        }
        return ji;
    }
}

Dao方法获取到的List转化为普通的JSON数据如下:

[
  {
    "autoid": 0,
    "bm": "01",
    "expand": 0,
    "isLeaf": 0,
    "level": 1,
    "mc": "企业科",
    "selected": 0
  },
  {
    "autoid": 0,
    "bm": "qyk1",
    "expand": 0,
    "isLeaf": 1,
    "level": 2,
    "mc": "企业科一号用户",
    "pid": "01",
    "selected": 0
  },
  {
    "autoid": 0,
    "bm": "qyk2",
    "expand": 0,
    "isLeaf": 1,
    "level": 2,
    "mc": "企业库二号用户",
    "pid": "01",
    "selected": 0
  },
  {
    "autoid": 0,
    "bm": "02",
    "expand": 0,
    "isLeaf": 0,
    "level": 1,
    "mc": "行财科",
    "selected": 0
  },
  {
    "autoid": 0,
    "bm": "xck1",
    "expand": 0,
    "isLeaf": 1,
    "level": 2,
    "mc": "行财科一号用户",
    "pid": "02",
    "selected": 0
  },
  {
    "autoid": 0,
    "bm": "xck2",
    "expand": 0,
    "isLeaf": 1,
    "level": 2,
    "mc": "行财科二号用户",
    "pid": "02",
    "selected": 0
  }
]

解析成树节点格式的JSON数据如下:

[
  {
    "id": "01",
    "text": "企业科",
    "cls": "folder",
    "children": [
      {
        "id": "qyk1",
        "text": "企业科一号用户",
        "cls": "file",
        "pid": "01",
        "leaf": true,
        "autoid": 0,
        "expanded": false
      },
      {
        "id": "qyk2",
        "text": "企业库二号用户",
        "cls": "file",
        "pid": "01",
        "leaf": true,
        "autoid": 0,
        "expanded": false
      }
    ],
    "leaf": false,
    "autoid": 0,
    "expanded": false
  }
]
  {
    "id": "02",
    "text": "行财科",
    "cls": "folder",
    "children": [
      {
        "id": "xck1",
        "text": "行财科一号用户",
        "cls": "file",
        "pid": "02",
        "leaf": true,
        "autoid": 0,
        "expanded": false
      },
      {
        "id": "xck2",
        "text": "行财科二号用户",
        "cls": "file",
        "pid": "02",
        "leaf": true,
        "autoid": 0,
        "expanded": false
      }
    ],
    "leaf": false,
    "autoid": 0,
    "expanded": false
  }
]
六.获取树节点分级数据的SQL语句的分析: 1.用户表数据:

 
2.科室表数据:

 
3.用户科室关联表数据:

 
4.按照树节点格式查询科室数据:
select sdid as bm, sdname as mc, null as pid, 0 as isleaf
  from sub_department
 where pdid = 1;

 
5.查询与科室关联的用户数据:
select u.userid as bm, u.name as mc, k.sdid as pid, 1 as isleaf
  from users u
  join user_keshi k
    on u.userid = k.userid;

 
6.查询科室用户分级数据:
select *
  from (select bm, mc, pid, isleaf, level
          from (select sdid as bm, sdname as mc, null as pid, 0 as isleaf
                  from sub_department
                 where pdid = 1
                union
                select u.userid as bm,
                       u.name   as mc,
                       k.sdid   as pid,
                       1        as isleaf
                  from users u
                  join user_keshi k
                    on u.userid = k.userid)
        connect by prior bm = pid
         start with pid is null);

   图示:

 

 
         

猜你喜欢

转载自zyjustin9.iteye.com/blog/2170196