html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="../../Scripts/bootstrap/js/bootstrap/css/bootstrap.css" rel="stylesheet" /> <link href="../../Scripts/bootstrap/js/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet" /> <link href="../../Scripts/bootstrap/js/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" /> <link href="../../Scripts/bootstrap/js/jquery.treegrid.min.css" rel="stylesheet" /> <script src="../../Scripts/bootstrap/js/jQuery1.11.3.min.js"></script> <script src="../../Scripts/bootstrap/js/bootstrap/js/bootstrap.min.js"></script> <script src="../../Scripts/bootstrap/js/bootstrap-table/bootstrap-table.min.js"></script> <script src="../../Scripts/bootstrap/js/bootstrap-table/locale/bootstrap-table-zh-CN.min.js"></script> <script src="../../Scripts/bootstrap/js/jquery.treegrid.js"></script> <script src="../../Scripts/bootstrap/js/bootstrap-table/jquery.treegrid.ajax.js"></script> <style> tr.checked-item { background-color: #d4e1f5 !important; } </style> </head> <body> <table id="table"></table> <script> $(function () { var name = parent.$("#FullBodyContent_MainName").val(); var $table = $("#table"); $table.myAjaxTreeTable({ url: 'treegrid.ashx?func=tree', ajaxParams: { name: name,type:"sbxj" }, rootidValue: "", striped: true, expandColumn: 0, columns: [ { field: 'name', title: '名称', }, { field: 'step', title: '步骤' }, { field: 'required', title: '关键点' }, ], }); }) </script> </body> </html>
ashx:
using Ext.Net; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Web; using XLT.QC.Domain; using XLT.QC.Entity; namespace XLT.QC.Web.Admin.RepairAdmin { /// <summary> /// treegrid 的摘要说明 /// </summary> public class treegrid : IHttpHandler { TestingMachineProcessDomain _testDomain = new TestingMachineProcessDomain(); public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string func = context.Request["func"]; switch (func) { case "tree": getTreeGridData(context); break; case "childtree": getChildNodeData(context); break; default: break; } } public void getTreeGridData(HttpContext context) { string type = context.Request["type"]; string name = context.Request["name"]; DataSet ds = _testDomain.getNodeData(name,type); List<MachineProcess> list = new List<MachineProcess>(); for (int i = 0; i < ds.Tables[0].Rows.Count; i++) { MachineProcess entity = new MachineProcess(); entity.name = ds.Tables[0].Rows[i]["Name"].ToString(); entity.id = ds.Tables[0].Rows[i]["Id"].ToString(); entity.pid = ds.Tables[0].Rows[i]["Pid"].ToString(); if (!string.IsNullOrWhiteSpace(ds.Tables[0].Rows[i]["Step"].ToString())) { entity.step = Convert.ToInt32(ds.Tables[0].Rows[i]["Step"]); } if (!string.IsNullOrWhiteSpace(ds.Tables[0].Rows[i]["Level"].ToString())) { entity.level = Convert.ToInt32(ds.Tables[0].Rows[i]["Level"]); } entity.required = ds.Tables[0].Rows[i]["Required"].ToString(); entity.isLeaf= true; list.Add(entity); } string jsonStr = JSON.Serialize(list); context.Response.Write(jsonStr); } public void getChildNodeData(HttpContext context) { string pid = context.Request["pid"]; string type = context.Request["type"]; string table = "TestingMachineProcess"; if (type=="sbxj") { table = "ArtificialProcess"; } string sql = "select Id,Pid,Name,Step,Level,QualityStandard,Required from " + table + " where Pid='" + pid + "' and (IsValid is null or IsValid=1) order by Step asc"; DataSet ds = ISS.DataAccess.DbHelper.ExecuteDataSetBySql(sql); List<MachineProcess> list = new List<MachineProcess>(); for (int i = 0; i < ds.Tables[0].Rows.Count; i++) { MachineProcess entity = new MachineProcess(); entity.name = ds.Tables[0].Rows[i]["Name"].ToString(); entity.id = ds.Tables[0].Rows[i]["Id"].ToString(); entity.pid = ds.Tables[0].Rows[i]["Pid"].ToString(); if (!string.IsNullOrWhiteSpace(ds.Tables[0].Rows[i]["Step"].ToString())) { entity.step = Convert.ToInt32(ds.Tables[0].Rows[i]["Step"]); } if (!string.IsNullOrWhiteSpace(ds.Tables[0].Rows[i]["Level"].ToString())) { entity.level = Convert.ToInt32(ds.Tables[0].Rows[i]["Level"]); } entity.required = ds.Tables[0].Rows[i]["Required"].ToString(); IDataReader dr = ISS.DataAccess.DbHelper.ExecuteReaderBySql("select COUNT(1) num from TestingMachineProcess where Pid='" + entity.id + "' "); if (dr.Read()) { if (Convert.ToInt32(dr["num"].ToString()) > 0) { entity.isLeaf = true; } else { entity.isLeaf = false; } } dr.Close(); dr.Dispose(); list.Add(entity); } string jsonStr = JSON.Serialize(list); context.Response.Write(jsonStr); } public class MachineProcess { public string id { get; set; } /// <summary> /// 父节点 /// </summary> public string pid { get; set; } /// <summary> /// 名称 /// </summary> public string name { get; set; } /// <summary> /// 步骤 /// </summary> public int step { get; set; } /// <summary> /// 级别 /// </summary> public int level { get; set; } /// <summary> /// 质量标准说明 /// </summary> //public string QualityStandard { get; set; } /// <summary> /// /// </summary> public bool isLeaf { get; set; } /// <summary> /// 关键点 /// </summary> public string required { get; set; } } public bool IsReusable { get { return false; } } } }
js:
(function ($) { "use strict"; $.fn.myAjaxTreeTable = function (options, param) { // 如果是调用方法 if (typeof options == 'string') { return $.fn.myAjaxTreeTable.methods[options](this, param); } // 如果是初始化组件 options = $.extend({}, $.fn.myAjaxTreeTable.defaults, options || {}); // 是否有radio或checkbox var hasSelectItem = false; var target = $(this); // 在外层包装一下div,样式用的bootstrap-table的 var _main_div = $("<div class='fixed-table-container'></div>"); target.before(_main_div); _main_div.append(target); target.addClass("table table-hover treegrid-table table-bordered"); if (options.striped) { target.addClass('table-striped'); } // 工具条在外层包装一下div,样式用的bootstrap-table的 if (options.toolbar) { var _tool_div = $("<div class='fixed-table-toolbar' style='display:none;'></div>"); var _tool_left_div = $("<div class='bs-bars pull-left'></div>"); _tool_left_div.append($(options.toolbar)); _tool_div.append(_tool_left_div); _main_div.before(_tool_div); } // 得到根节点 target.getRootNodes = function (data) { // 指定Root节点值 var _root = options.rootidValue ? options.rootidValue : ""; var result = []; $.each(data, function (index, item) { // 这里兼容几种常见Root节点写法 // 默认的几种判断 var _defaultRootFlag = item[options.pid] == '0' || item[options.pid] == 0 || item[options.pid] == null || item[options.pid] == ''; if (!item[options.pid] || (_root ? (item[options.pid] == options.rootidValue) : _defaultRootFlag)) { result.push(item); } // 添加一个默认属性,用来判断当前节点有没有被显示 item.isShow = false; }); return result; }; var j = 0; // 递归获取子节点并且设置子节点 target.getChildNodes = function (data, parentNode, parentIndex, tbody) { $.each(data, function (i, item) { if (item[options.pid] == parentNode[options.id]) { var tr = $('<tr></tr>'); var nowParentIndex = (parentIndex + (j++) + 1); tr.addClass('treegrid-' + nowParentIndex); tr.addClass('treegrid-parent-' + parentIndex); tr.addClass('unknow'); tr.attr("isLeaf", item.isLeaf); tr.attr("level", item.level); target.renderRow(tr, item); item.isShow = true; tbody.append(tr); target.getChildNodes(data, item, nowParentIndex, tbody) } }); }; target.renderChildRows = function (data, parentNode, parentIndex, tbody) { var html = ""; var parentNum = $(tbody).attr('class').split(" ")[2]; $.each(data, function (i, item) { var tr = $('<tr></tr>'); var nowParentIndex = parentIndex; tr.addClass('treegrid-' + nowParentIndex + i); tr.addClass('treegrid-parent-' + parentIndex); tr.addClass('unknow'); tr.attr("isLeaf", item.isLeaf); tr.attr("level", item.level); target.renderRow(tr, item); item.isShow = true; html += tr.get(0).outerHTML; }); tbody.after(html); }; // 行添加内容 target.renderRow = function (tr, item) { $.each(options.columns, function (index, column) { // 判断有没有选择列 if (index == 0 && column.field == 'selectItem') { hasSelectItem = true; var td = $('<td style="text-align:center;36px"></td>'); if (column.radio) { var _ipt = $('<input name="select_item" type="radio" value="' + item[options.id] + '"></input>'); td.append(_ipt); } if (column.checkbox) { var _ipt = $('<input name="select_item" type="checkbox" value="' + item[options.id] + '"></input>'); td.append(_ipt); } tr.append(td); } else { var html = "<td mainid='" + item[options.id] + "' style='text-align:left;'>"; var level = parseInt(item.level); if (index == 0) { if (item.pid != "") { for (var i = 0; i < level; i++) { html += "<span class='treegrid-indent'></span>"; } } html += "<span class='treegrid-expander'></span>" + item[column.field] + "</td>"; } else { html += item[column.field] + "</td>"; } // 增加formatter渲染 if (column.formatter) { td.html(column.formatter.call(this, item, index)); } tr.append($(html)); } }); } // 加载数据 target.load = function (parms) { // 加载数据前先清空 target.html(""); // 构造表头 var thr = $('<tr></tr>'); $.each(options.columns, function (i, item) { var th = null; // 判断有没有选择列 if (i == 0 && item.field == 'selectItem') { hasSelectItem = true; th = $('<th style="text-align:' + item.valign + ';36px"></th>'); } else { th = $('<th style="text-align:' + item.valign + ';padding:10px;' + ((item.width) ? ('' + item.width) : '') + '"></th>'); } th.text(item.title); thr.append(th); }); var thead = $('<thead class="treegrid-thead"></thead>'); thead.append(thr); target.append(thead); // 构造表体 var tbody = $('<tbody class="treegrid-tbody"></tbody>'); target.append(tbody); // 添加加载loading var _loading = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">正在努力地加载数据中,请稍候……</div></td></tr>' tbody.html(_loading); // 默认高度 if (options.height) { tbody.css("height", options.height); } $.ajax({ type: options.type, url: options.url, data: parms ? parms : options.ajaxParams, dataType: "JSON", success: function (data, textStatus, jqXHR) { // 加载完数据先清空 tbody.html(""); if (!data || data.length <= 0) { var _empty = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">没有记录</div></td></tr>' tbody.html(_empty); return; } var rootNode = target.getRootNodes(data); //console.log(rootNode); $.each(rootNode, function (i, item) { var tr = $('<tr></tr>'); tr.addClass('treegrid-' + (j + "_" + i)); tr.attr('load', 'true'); tr.attr('level', item.level); tr.addClass('unknow'); tr.addClass('tree_rootnode'); target.renderRow(tr, item); item.isShow = true; tbody.append(tr); target.getChildNodes(data, item, (j + "_" + i), tbody); }); target.append(tbody); // 初始化treegrid bug //target.treegrid({ // treeColumn: options.expandColumn ? options.expandColumn : (hasSelectItem ? 1 : 0),//如果有radio或checkbox默认第二列层级显示,当前是在用户未设置的提前下 // expanderExpandedClass: options.expanderExpandedClass, // expanderCollapsedClass: options.expanderCollapsedClass //}); //if (!options.expandAll) { // target.treegrid('collapseAll'); //} $(".treegrid-tbody").find("tr:not(.tree_rootnode)").hide(); target.repainExpends(); }, error: function (xhr, textStatus) { var _errorMsg = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">' + xhr.responseText + '</div></td></tr>' tbody.html(_errorMsg); } }); } /*** 初始化图标 ***/ target.repainExpends = function (tr, reset) { var trExpends; if (tr) { var str = tr.attr('class').split(" ")[0].split("-")[1]; var cls = "treegrid-parent-" + str; trExpends = target.find("tr." + cls); } else { trExpends = target.find("tr"); } /* * isleaf 是否有子数据 * load 是否已加载子数据 */ if (reset == "true") { $.each(trExpends, function (index, item) { if ($(item).attr('isLeaf') == 'true') { $(item).find("span:last-child").removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-right').addClass('glyphicon'); } }); } else { $.each(trExpends, function (index, item) { if ($(item).attr('isLeaf') == 'true' && $(item).attr('load') != 'true') { $(item).find("span:last-child").removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-right').addClass('glyphicon'); //收缩 } else if ($(item).attr('isLeaf') == 'true' && $(item).attr('load') == 'true') { $(item).find("span:last-child").addClass('glyphicon-chevron-down').removeClass('glyphicon-chevron-right').addClass('glyphicon'); //展开 } else { if ($(item).hasClass('tree_rootnode')) { $(item).find("span:last-child").removeClass('glyphicon-chevron-down').addClass('glyphicon-chevron-right').addClass('glyphicon'); //收缩 } else { $(item).find("span:last-child").removeClass('glyphicon-chevron-down').removeClass('glyphicon-chevron-right'); //删除图标 } } }); } } /****** 加载子节点数据 start ***************/ target.loadChilds = function (parentTR, parms) { debugger; var tbody = $(parentTR).parents(".treegrid-tbody"); parms = $.extend({}, parms, options.ajaxParams); $.ajax({ type: options.type, url: "handler/DeviceMaintainService.ashx?function=childtree", data: parms, dataType: "JSON", success: function (data, textStatus, jqXHR) { var _tr = target.find(".treegrid-" + parms.parentIndex); _tr.attr('load', 'true'); target.renderChildRows(data, { "mainId": parms.pid }, parms.parentIndex, _tr); parentTR.removeClass('unknow').addClass('know'); target.repainExpends(parentTR); }, error: function (xhr, textStatus) { var _errorMsg = '<tr><td colspan="' + options.columns.length + '"><div style="display: block;text-align: center;">' + xhr.responseText + '</div></td></tr>' tbody.html(_errorMsg); }, }); } /****** 加载子节点数据 end ***************/ /*自定义扩展方法*/ var customMethod = { collapseNode: function (parentTr) { var parentNum = parentTr.attr('class').split(" ")[0].split("-")[1]; var childCls = "treegrid-parent-" + parentNum; var child = $("tr." + childCls); if (child.length > 0) { child.hide(); for (var i = 0; i < child.length; i++) { if (child.eq(i).attr("isleaf") == "true") { child.eq(i).find("span.treegrid-expander").removeClass("glyphicon-chevron-down").addClass("glyphicon-chevron-right"); } this.collapseNode(child.eq(i)); } } }, expandNode: function (parentTr) { var parentNum = parentTr.attr('class').split(" ")[0].split("-")[1]; var childCls = "treegrid-parent-" + parentNum; var child = $("tr." + childCls); if (child.length > 0) { child.show(); for (var i = 0; i < child.length; i++) { if (child.eq(i).attr("isleaf") == "true") { child.eq(i).find("span.treegrid-expander").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-down"); } //this.expandNode(child.eq(i)); } } } } /*初始加载树数据*/ if (options.url) { target.load(); } else { // 通过data属性传递一个数据集合对组件进行初始化, } /*图标事件绑定*/ $(document).on('click', 'span.glyphicon-chevron-right', function (e) { //console.log("right"); if ($(this).parent().parent().attr('load') != 'true') { //console.log("loadchildren函数下节点图标绑定的事件触发了"); $(this).removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-down"); $(this).parent().parent().addClass("expand").removeClass("collaps"); target.loadChilds( $(this).parent().parent(), { "pid": $(this).parent().attr('mainid'), "parentIndex": $(this).parent().parent().attr('class').split(" ")[0].split("-")[1], "nowParentIndex": $(this).parent().parent().attr('class').split(" ")[0].split("-")[0] }); } else { var parentTr = $(this).parent().parent(); //var level = parentTr.attr("level"); //var parentNum = parentTr.attr('class').split(" ")[0].split("-")[1]; //var childCls = "treegrid-parent-" + parentNum; //var child = $("tr." + childCls); //if (level == "0" || $(this).parent().parent().hasClass("tree_rootnode")) { //根节点 // $(".treegrid-tbody").find("tr:not(.tree_rootnode)").show(); //} //else { // child.show(); //} customMethod.expandNode(parentTr); $(this).removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-down"); $(this).parent().parent().addClass("expand").removeClass("collaps"); //直属子级图标初始化统一为right target.repainExpends(parentTr, "true"); } e.stopPropagation(); }); $(document).on('click', 'span.glyphicon-chevron-down', function (e) { //console.log("down"); if ($(this).parent().parent().hasClass("expand")) { //获取选中行 var parentTr = $(this).parent().parent(); //var level = parentTr.attr("level"); //if (level == "0" || $(this).parent().parent().hasClass("tree_rootnode")) { // $(".treegrid-tbody").find("tr:not(.tree_rootnode)").hide(); //} //else { customMethod.collapseNode(parentTr); //} console.log(parentTr); } else { } $(this).removeClass("glyphicon-chevron-down").addClass("glyphicon-chevron-right"); $(this).parent().parent().addClass("collaps").removeClass("expand"); e.stopPropagation(); }); $(document).on('click', '.treegrid-tbody tr', function () { $(".treegrid-tbody tr").removeClass("checked-item"); var id = $(this).children(0).attr("mainid"); $(this).addClass("checked-item"); parent.$("#FullBodyContent_hdSelectedNodeId").val(id); $("#treeId").val(id); }) return target; }; // 组件方法封装 $.fn.myAjaxTreeTable.methods = { // 返回选中记录的id getSelections: function (target) { var _ipt = target.find("tbody").find("tr").find("input[name='select_item']:checked"); var chk_value = []; if (_ipt.attr("type") == "radio") { chk_value.push({ id: _ipt.val() }); } else { _ipt.each(function (_i, _item) { chk_value.push({ id: $(_item).val() }); }); } return chk_value; }, // 刷新记录 refresh: function (target, parms) { if (parms) { target.load(parms); } else { target.load(); } }, // 重置表格视图 resetHeight: function (target, height) { target.find("tbody").css("height", height + 'px'); } }; $.fn.myAjaxTreeTable.defaults = { id: 'id',// 选取记录返回的值 pid: 'pid',// 用于设置父子关系 rootidValue: null,//设置根节点id值----可指定根节点,默认为null,"",0,"0" data: [], // 构造table的数据集合,本地测试可以设置具体数据 type: "GET", // 请求数据的ajax类型 url: null, // 请求数据的ajax的url ajaxParams: {}, // 请求数据的ajax的data属性 expandColumn: null,// 在哪一列上面显示展开按钮 expandAll: false, // 是否全部展开 striped: false, // 是否各行渐变色 columns: [], toolbar: null,//顶部工具条 height: 0, expanderExpandedClass: 'glyphicon glyphicon-chevron-down',// 展开的按钮的图标 expanderCollapsedClass: 'glyphicon glyphicon-chevron-right'// 缩起的按钮的图标 }; })(jQuery);
效果图: