Ext 树型菜单(增删改查)

 

首先看数据库的构造:

    第一个是总的类别表(例表1[emergencytype]),此表中存放的是总的类别表,理论是不可编辑的,表中详细信息见表1-1.

    第二个是总的分类别表下的小类别(例表2[emergencyworkflow]),所做的主要操作,是对表2的增删改查.表中详细信息见表2-2.

首先

   表1:

       

   表1-1:

     

   表2:

    

   表2-2:

    

  

 

首先是根据表的结构的结构生成树:

  

 var treeloader=new Ext.tree.TreeLoader({dataUrl:'tree.aspx?action=getAll'});

 var tree=new Ext.tree.TreePanel({

        autoWidth:true,

        autoHeight:true,

        animate:false,//开启动画效果

        enableDD:false,//不允许子节点拖动

        rootVisible:false,

        loader:treeloader

     });

     tree.on('dblclick',function(node,e){nodeClickEvent(node);});

     tree.on('contextmenu', contextmenu, tree);

      //定义树的跟节点

      var root=new Ext.tree.AsyncTreeNode({

        draggable:false, //不能拖放

        expanded :true

      }); 

   

      tree.setRootNode(root);

      tree.expandAll(); //设置的是全部展开.

其中contextmenu设置的是树形节点的右击菜单,方法如下:

      function contextmenu(node, e) {

// if(node.getDepth() > 1)

// {

            var treeMenu = new Ext.menu.Menu( {

                    items : [

                        new Ext.menu.Item( {

                            text : '添加',

                            icon:'../../Image/Workflow/ICO/TTWeather.ico',

                            handler : addTreeNode.createCallback(node)

                        }),

                        new Ext.menu.Item( {

                            text : '添加子项',

                            icon:'../../Image/Workflow/ICO/LowPriority.ico',

                            handler : addChildTreeNode.createCallback(node)

                        }),

                        new Ext.menu.Item( {

                            text : '删除',

                            icon:'../../Image/Workflow/ICO/exit.ico',

                            handler : deleteTreeNode.createCallback(node)

                        }),

                        new Ext.menu.Item( {

                            text : '重命名',

                            icon:'../../Image/Workflow/ICO/favicon.ico',

                            handler : renameTreeNode.createCallback(node)

                        })

                    ]

                });

            treeMenu.showAt(e.getXY());

       // }

    }

 因为理论上第一节点是不可编辑的,但是为了把功能做全,就让第一菜单也具有增删改查的功能.所有把菜单的节点深度(node.getDepth()>1)限制注消掉了.

 菜单上的四个不同的方法如下:

 在方法中有几个变量都需要用到,所有需要设置几个全局变量:

           var rightClickTreeNode = null;  //右键点击树节点

//获取最上层节点ID,即父类别ID,在数据库中指EMERGENCYWORKFLOW表TYPE_ID字段,该字段与EMERGENCYTYPE表PK_ID字段关联,级联删除。

    function getNodeTypeID(node)

    {

        if(node.getDepth() != 1)

        {

            return getNodeTypeID(node.parentNode);

        }

        return node.attributes.attributes.pk_id;

    }

   

    //添加节点菜单函数

    var addTreeNode = function(node)

    {

        rightClickTreeNode = node;

        Ext.MessageBox.prompt('节点名称', '请输入新节点名称:', addTreeNodeAjax);

       

    };

    //添加节点菜单处理函数

    function addTreeNodeAjax(btn,text)

    {

        if(btn == 'ok')

        {

            if(text.Trim() == '')

            {

                Ext.Msg.alert('友情提示','节点名称不能为空!');

                rightClickTreeNode = null;

                return;

            }

            else

            {

                var typeId = getNodeTypeID(rightClickTreeNode);

                text = encodeURI(text.Trim());

                var depth=rightClickTreeNode.getDepth();

                if(depth!='1')

                {

  treeloader.dataUrl =  'tree.aspx?                      action=addTreeNode&pid='+rightClickTreeNode.parentNode.attributes.attributes.pk_id+'&depth='+rightClickTreeNode.getDepth()

 +'&typeId='+typeId+'&newNode='+text;

                }

                else

                {

                 treeloader.dataUrl =  tree.aspx?action=addTreeNode&depth='+rightClickTreeNode.getDepth()+'&newNode='+text;

                }

                root.reload();

                tree.expandAll();

                rightClickTreeNode = null;

 

            }

        }

    };

   

    //添加子节点菜单函数

    var addChildTreeNode = function (node)

    {

        rightClickTreeNode = node;

        Ext.MessageBox.prompt('友情提示', '请输入子节点名称:', addChildTreeNodeAjax);

    };

   

    //添加子节点菜单处理函数

    function addChildTreeNodeAjax(btn,text)

    {

        if(btn == 'ok')

        {

            if(text.Trim() == '')

            {

                Ext.Msg.alert('友情提示','子节点名称不能为空!');

                rightClickTreeNode = null;

                return;

            }

            else

            {

                var depth=rightClickTreeNode.getDepth();

                var typeId = getNodeTypeID(rightClickTreeNode);

                text = encodeURI(text.Trim());

                if(depth!='1')

                {

                  treeloader.dataUrl =  'tree.aspx?action=addChildTreeNode&id='+rightClickTreeNode.attributes.attributes.pk_id+'&typeId='+typeId+'&newNode='+text;

                } 

                else

                {

                 treeloader.dataUrl =  'tree.aspx?action=addChildTreeNode&typeId='+typeId+'&newNode='+text;

                }

               

                root.reload();

                tree.expandAll();

                rightClickTreeNode = null;

            }

        }

    };

    //删除树节点函数

    var deleteTreeNode = function(node)

    {

        rightClickTreeNode = node;

        Ext.MessageBox.confirm('友情提示', '确定删除节点吗?(注意:此动作将同时删除该节点下的所有子节点)',deleteChildTreeNodeAjax);

    };

    //删除树节点处理函数

    function deleteChildTreeNodeAjax(btn)

    {

        if(btn == 'yes')

        {

            var depth=rightClickTreeNode.getDepth();            

            treeloader.dataUrl =  'tree.aspx?action=deleteChildTreeNode&depth='+depth+'&id='+rightClickTreeNode.attributes.attributes.pk_id;           

            root.reload();

            tree.expandAll();

            rightClickTreeNode = null;

        }

    };

    //重命名树节点函数

    var renameTreeNode = function (node)

    {

        rightClickTreeNode = node;

        Ext.MessageBox.prompt('友情提示', '请输入新节点名称:', renameTreeNodeAjax,this,false,node.text);

    };

    //重命名树节点处理函数

    function renameTreeNodeAjax(btn,text)

    {

        if(btn == 'ok')

        {

            if(text.Trim() == '')

            {

                Ext.Msg.alert('友情提示','子节点名称不能为空!');

                rightClickTreeNode = null;

                return;

            }

            else if(text.Trim() == rightClickTreeNode.text)

            {

                Ext.Msg.alert('友情提示','请输入不同的名称!');

                rightClickTreeNode = null;

                return;

            }

            else

            {

                text = encodeURI(text.Trim());

                var depth=rightClickTreeNode.getDepth();

                treeloader.dataUrl =  tree.aspx?action=renameTreeNode&depth='+depth+'&id='+rightClickTreeNode.attributes.attributes.pk_id+'&newName='+text;

                root.reload();

                tree.expandAll();

                rightClickTreeNode = null;

            }

        }

    }

  :

   一个树形菜单一般不会单独做一个页面,一般都会放到一个别的容器里(ViewPort);

   

    先定义在ViewPort前面一个Panel:

  var managePanel = new Ext.Panel({

        title:'管理页面',

        height: 800,

        width : 700,

        layout:'absolute',

        renderTo : 'Div',

        tbar: new Ext.Toolbar({

            enableOverflow: true,

            disabled : true,

            items: [

            {

                text: '添加节点',

                icon : '../../Image/Workflow/ICO/Events.ico',

                handler: createNode.createCallback(null)

            },'-',{

                text: '添加线条',

                icon : '../../Image/Workflow/ICO/Events.ico',

                menu: [{

                        text: '左箭头',

                        handler: createLine.createCallback('左箭头')

                    },{

                        text: '右箭头',

                        handler: createLine.createCallback('右箭头')

                    }]

            },'-',{

                text: '删除选中项',

                icon : '../../Image/Workflow/ICO/Events.ico',

                handler: deleteItem.createCallback()

            },'-',{

                text: '面板大小',

                icon : '../../Image/Workflow/ICO/Events.ico',

                menu: [{

                        text: '设置高度',

                        handler: setHeight.createCallback()

                    },{

                        text: '设置宽度',

                        handler: setWidth.createCallback()

                    }]

            }]

        })

    });

 var viewport = new Ext.Viewport({

        header : false,

        layout:'border',

        items:[{

            region:'west',

            id:'west-panel',

            headerCfg :{align:'center',cls: 'x-panel-header'},

            title:'应急预案流程',

            split:true,

            width: 200,

            minSize: 175,

            maxSize: 350,

            collapsible: true,

            autoScroll:true,

            items: [{

                header:false,

                border:false,

                items:[tree]                            

            }]

        },

        {

            region:'center',

            id : 'center-panel',

            //autoWidth:true,

            autoScroll : true,

            height:500,

            width:500,

            layout:'anchor',

            items:[managePanel]                          // panel自己可以在前面初始定义一个.

        }]

    });

 所有有方法都是向后台发送请求,然后后台根据不同的action来执行不同的方法.一般都把方法归总到一个类CS文件(App_Code/tree.cs):

  (1) 生成树的方法如下:

            //获得总节点的所有信息

 public static string GetAllType()

    {

        string result = "";

        try

        {

            string sql = "select * from emergencytype";

            DataTable typeDT = dbHelpSql.Query(sql);

            string pid = "";

            TreeNode root = new TreeNode("根节点", "根节点");

            TreeNode node = null;

            foreach (DataRow row in typeDT.Rows)

            {

                pid = row["PK_ID"].ToString();

                node = new TreeNode(row["TYPE"].ToString(), pid);

                BuildWorkFlowChild(node);

                root.ChildNodes.Add(node);

            }

            result = JsonHelper.GetJSTreeJSONData(root.ChildNodes);

        }

        catch (Exception ex)

        {

            result = "{" + JsonHelper.GetErrorJson(ex.Message) + "}";

        }

        return result;

    }

        //根据总节点获得此节点下所有的子节点信息

    private static void BuildWorkFlowChild(TreeNode node)

    {

        try

        {

            string sql = string.Format("select * from emergencyworkflow where type_id = {0} order by pk_Id,parent_id", node.Value);

            DataTable dt = dbHelpSql.Query(sql);

            BuildNode(node, dt);

        }

        catch (Exception ex)

        {

            throw new Exception(ex.Message);

        }

    }

    //创建父节点下所有子节点

    private static void BuildNode(TreeNode node, DataTable source)

    {

        TreeNode tNode = null;

        DataView dv = null;

        DataTable tDt = null;

        foreach (DataRow row in source.Rows)

        {

            if (row["PARENT_ID"].ToString() == "")

            {

                tNode = new TreeNode(row["NODE_DESC"].ToString(), row["PK_ID"].ToString());

                dv = source.DefaultView;

                dv.RowFilter = string.Format("parent_id = '{0}'", tNode.Value);

                tDt = dv.ToTable();

                if (tDt.Rows.Count > 0)

                {

                    BuildChildNode(tNode, tDt, source);

                }

                node.ChildNodes.Add(tNode);

            }

 

        }

    }

    //若子节点下还有下一级,则遍历循环

    private static void BuildChildNode(TreeNode node, DataTable fDT, DataTable source)

    {

        TreeNode tNode = null;

        DataView dv = null;

        DataTable tDt = null;

        foreach (DataRow row in fDT.Rows)

        {

            tNode = new TreeNode(row["NODE_DESC"].ToString(), row["PK_ID"].ToString());

            dv = source.DefaultView;

            dv.RowFilter = string.Format("parent_id = '{0}'", tNode.Value);

            tDt = dv.ToTable();

            if (tDt.Rows.Count > 0)

            {

                BuildChildNode(tNode, tDt, source);

            }

            node.ChildNodes.Add(tNode);

        }

    }

 

(2)增删改查的方法:

            1.增加同级树的节点(根据深度来判断)

    // 添加树节点

    public static string AddTreeNode(string pid, string name, string depth, string typeId)

    {

        string result = "";

        try

        {

            string sql;

            if (depth == "1")

            {

                sql = string.Format("insert into emergencytype(pk_id, type)values(SEQ_EMERGENCYTYPE.NEXTVAL,'{0}')", name);

            }

            else if (depth == "2")

            {

                sql = string.Format("insert into emergencyworkflow values(SEQ_EMERGENCYWORKFLOW.Nextval,'{0}',null,{1},null)", name, typeId);

            }

            else

            {

                sql = string.Format("insert into emergencyworkflow values(SEQ_EMERGENCYWORKFLOW.Nextval,'{0}',{1},{2},null)", name, pid, typeId);

            }

            if (dbHelpSql.ExecuteSql(sql) == 1)

            {

                result = GetAllType();

            }

        }

        catch (Exception ex)

        {

            result = "{" + JsonHelper.GetErrorJson(ex.Message) + "}";

        }

        return result;

    }

2.增加树的子节点

    // 添加子节点

    public static string AddChildTreeNode(string id, string name, string typeId)

    {

        string result = "";

        try

        {

            string sql;

            if (id == null || string.IsNullOrEmpty(id))

            {

                sql = string.Format("insert into emergencyworkflow values(SEQ_EMERGENCYWORKFLOW.Nextval,'{0}',null,{1},null)", name, typeId);

            }

            else

            {

                sql = string.Format("insert into emergencyworkflow values(SEQ_EMERGENCYWORKFLOW.Nextval,'{0}',{1},{2},null)", name, id, typeId);

            }

            if (dbHelpSql.ExecuteSql(sql) == 1)

            {

                result = GetAllType();

            }

        }

        catch (Exception ex)

        {

            result = "{" + JsonHelper.GetErrorJson(ex.Message) + "}";

        }

        return result;

    }

     3.删除树的节点(同时删除以此节点为父节点的节点)

    // 删除指定ID节点及其子节点

    public static string DeleteTreeNode(string id, string depth)

    {

        string result = "";

        OracleConnection con = null;

        OracleTransaction trans = null;

        OracleCommand cmd = null;

        string sql;

        try

        {

            con = dbHelpSql.GetOracleConnection();

            con.Open();

            trans = con.BeginTransaction();

            cmd = con.CreateCommand();

            cmd.Transaction = trans;

            if (depth == "1")

            {

 

                sql = string.Format("delete emergencytype where pk_id = {0}", id);

                cmd.CommandText = sql;

                cmd.ExecuteNonQuery();

 

                sql = string.Format("delete emergencyworkflow where type_id = {0} ", id);

                cmd.CommandText = sql;

                cmd.ExecuteNonQuery();

                trans.Commit();

            }

            else

            {

                sql = string.Format("delete emergencyworkflow where pk_id = {0} or parent_id = {0} ", id);

                cmd.CommandText = sql;

                cmd.ExecuteNonQuery();

                trans.Commit();

            }

            //if (dbHelpSql.ExecuteSql(sql) > 0)

            //{

            result = GetAllType();

            //  }

        }

        catch (Exception ex)

        {

            result = "{" + JsonHelper.GetErrorJson(ex.Message) + "}";

            trans.Rollback();

        }

        finally

        {

            if (cmd != null)

            {

                cmd.Dispose();

            }

            if (trans != null)

            {

                trans.Dispose();

            }

            if (con != null)

            {

                con.Dispose();

            }

        }

        return result;

    }

          4.重命子节点

    // 重命名指定id树节点

    public static string RenameTreeNode(string id, string newName, string depth)

    {

        string result = "";

        try

        {

            string sql;

            if (depth != "1")

            {

                sql = string.Format("update emergencyworkflow set node_desc = '{0}' where pk_id = {1} ", newName, id);

            }

            else

            {

                sql = string.Format("update emergencytype set type = '{0}' where pk_id = {1} ", newName, id);

            }

            if (dbHelpSql.ExecuteSql(sql) == 1)

            {

                result = GetAllType();

            }

        }

        catch (Exception ex)

        {

            result = "{" + JsonHelper.GetErrorJson(ex.Message) + "}";

        }

        return result;

    }

 

附录: (JSON处理类[App_Code/JsonHelper.cs]中的方法)

   

        /// <summary>

    /// 将TreeNode数组中的每一个节点及其全部子节点转换为Json格式字符串

    /// </summary>

    /// <param name="nodes"></param>

    /// <returns></returns>

    public static string GetJSTreeJSONData(TreeNodeCollection nodes)

    {

        StringBuilder treeString = new StringBuilder();

        //构建JSON开头

        treeString.Append("[");

 

        //foreach (TreeNode node in nodes)

        for (int i = 0; i < nodes.Count;i++ )

        {

           

            //如果有子节点,则进行子节点构建

            if (nodes[i].ChildNodes.Count != 0)

            {

                treeString.Append("{ attributes: {pk_id: '" + nodes[i].Value + "'}, text:'" + nodes[i].Text + "',expanded: false");

                RecurrenceBuildJSTreeJSONData(treeString, nodes[i]);

            }

            else

            {

                treeString.Append("{ attributes: {pk_id: '" + nodes[i].Value + "'}, text:'" + nodes[i].Text + "',leaf: true");

            }

            //构建节点结尾

            treeString.Append("}");

            if(i != nodes.Count -1)

            {

                treeString.Append(",");

            }

        }

       

        treeString.Append("]");

 

        return treeString.ToString();

    }

 

    /// <summary>

    /// 将单个节点及其所有子节点转换为Json格式字符串

    /// </summary>

    /// <param name="nodes"></param>

    /// <returns></returns>

    public static string GetJSTreeJSONData(TreeNode nodes)

    {

        StringBuilder treeString = new StringBuilder();

 

        //构建JSON开头

        treeString.Append("[");

 

        //构建节点

        treeString.Append("{ attributes: {pk_id: '" + nodes.Value + "'}, text:'" + nodes.Text + "',expanded: false");

        //如果有子节点,则进行子节点构建

        if (nodes.ChildNodes.Count != 0)

        {

            RecurrenceBuildJSTreeJSONData(treeString, nodes);

        }

        //构建节点结尾

        treeString.Append("}");

 

        //构建JSON结尾

        treeString.Append("]");

 

        return treeString.ToString();

    }

     

    private static void RecurrenceBuildJSTreeJSONData(StringBuilder treeString, TreeNode nodes)

    {

        //构建子节点开头

        treeString.Append(",children: [");

 

        for (int i = 0; i < nodes.ChildNodes.Count; i++)

        {

            treeString.Append("{ attributes: {pk_id: '" + nodes.ChildNodes[i].Value + "'},  text:'" + nodes.ChildNodes[i].Text + "'");

 

            if (nodes.ChildNodes[i].ChildNodes.Count != 0)

                RecurrenceBuildJSTreeJSONData(treeString, nodes.ChildNodes[i]);

            else

                treeString.Append(",leaf:true");

            //构建最后一条节点的结尾

            if (i == nodes.ChildNodes.Count - 1)

                treeString.Append("}");

            //构建非最后一条节点的结尾

            else

                treeString.Append("},");

        }

 

        //构建子节点结尾

        treeString.Append("]");

    }

        /// <summary>

    /// 转换异常信息为同一的Json数据格式

    /// </summary>

    /// <param name="msg"></param>

    /// <returns></returns>

    public static string GetErrorJson(string msg)

    {

        if(msg.IndexOf("/n") > 0)

        {

            msg = msg.Substring(0, msg.IndexOf("/n"));

        }

        return "err:{msg:'" + msg + "'}";

    }

 

    /// <summary>

    /// 将DataTable数据转换为Json表格数据格式

    /// </summary>

    /// <param name="dt"></param>

    /// <returns></returns>

    public static string GetTableJson(DataTable dt)

    {

        //{success;true,data:{clientName: "Fred. Olsen Lines",   portOfLoading:"FXT",portOfDischarge: "OSL"}}

        string data = "data:[";

        if (dt != null && dt.Rows.Count > 0)

        {

            foreach(DataRow row in dt.Rows)

            {

                data += "{";

                foreach(DataColumn column in dt.Columns)

                {

                    data += column.ColumnName + ":'" + row[column].ToString() + "',";

                }

                data = data.Substring(0, data.Length - 1);

                data += "},";

            }

            data = data.Substring(0, data.Length - 1);

        }

        data += "]";

        return data;

    }

    

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值