layui.define(['layer', 'table'], function (exports) { // 获取jQuery对象 var $ = layui.jquery; // 获取layer模块 var layer = layui.layer; // 获取table模块 var table = layui.table; var treetable = { // 渲染树形表格 render: function (param) { // 检查参数是否合法 if (!treetable.checkParam(param)) { return; // 如果参数不合法,直接返回 } // 获取数据 if (param.data) { // 如果参数中包含数据,则直接初始化树形表格 treetable.init(param, param.data); } else { // 如果参数中没有数据,则通过AJAX请求获取数据 $.getJSON(param.url, param.where, function (res) { // 使用获取到的数据初始化树形表格 treetable.init(param, res.data); }); } }, // 渲染表格 init: function (param, data) { // 初始化一个空数组,用于存储处理后的数据 var mData = []; // 获取回调函数done var doneCallback = param.done; // 将传入的数据赋值给tNodes变量 var tNodes = data; // 遍历tNodes数组中的每一个元素 for (var i = 0; i < tNodes.length; i++) { // 当前遍历到的元素 var tt = tNodes[i]; // 如果当前元素没有id字段 if (!tt.id) { // 如果参数中没有treeIdName字段 if (!param.treeIdName) { // 弹出提示信息,告知treeIdName不能为空 layer.msg('参数treeIdName不能为空', {icon: 5}); // 终止函数执行 return; } // 使用treeIdName对应的值作为id tt.id = tt[param.treeIdName]; } // 检查tt对象是否具有pid属性 if (!tt.pid) { // 如果param对象没有treePidName属性,则提示错误信息并返回 if (!param.treePidName) { layer.msg('参数treePidName不能为空', {icon: 5}); return; } // 将tt对象的pid属性设置为tt对象中对应treePidName属性的值 tt.pid = tt[param.treePidName]; } } // 对数据进行排序 var sort = function (s_pid, data) { // 遍历数据数组 for (var i = 0; i < data.length; i++) { // 如果当前元素的父ID等于目标父ID if (data[i].pid == s_pid) { // 获取mData数组的长度 var len = mData.length; // 如果mData数组不为空且最后一个元素的ID等于目标父ID if (len > 0 && mData[len - 1].id == s_pid) { // 将最后一个元素的isParent属性设置为true mData[len - 1].isParent = true; } // 将当前元素添加到mData数组中 mData.push(data[i]); // 递归调用sort函数,处理当前元素的子元素 sort(data[i].id, data); } } }; } }; // 调用sort函数,对树形结构进行排序 // 参数param.treeSpid表示树的根节点ID // tNodes是包含所有节点信息的数组 sort(param.treeSpid, tNodes); // 重写参数 // 将param对象的url属性设置为undefined param.url = undefined; // 将param对象的data属性设置为mData param.data = mData; // 设置param对象的page属性,包含count和limit两个子属性 param.page = { // count属性表示数据的总数量,等于data数组的长度 count: param.data.length, // limit属性表示每页显示的数据量,等于data数组的长度 limit: param.data.length }; param.cols[0][param.treeColIndex].templet = function (d) { // 获取当前节点的ID var mId = d.id; // 获取当前节点的父节点ID var mPid = d.pid; // 判断当前节点是否为目录(是否有子节点) var isDir = d.isParent; // 计算当前节点前面需要填充的空白数量 var emptyNum = treetable.getEmptyNum(mPid, mData); // 初始化图标HTML字符串 var iconHtml = ''; // 根据空白数量生成相应数量的空白图标 for (var i = 0; i < emptyNum; i++) { iconHtml += ''; } if (isDir) { // 如果是目录,添加两个图标:一个三角形和一个图层图标 iconHtml += ' '; } else { // 如果是文件,添加一个文件图标 iconHtml += ''; } // 添加两个空格作为间隔 iconHtml += '  '; // 根据是否是目录设置类型为'dir'或'file' var ttype = isDir ? 'dir' : 'file'; // 创建包含图标和名称的HTML字符串 var vg = ''; // 返回完整的HTML字符串 return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '' param.done = function (res, curr, count) { // 在当前元素之后插入一个带有'class'为'treeTable'的元素 $(param.elem).next().addClass('treeTable'); // 隐藏'treeTable'中的分页控件 $('.treeTable .layui-table-page').css('display', 'none'); // 设置'treeTable'元素的'treeLinkage'属性 $(param.elem).next().attr('treeLinkage', param.treeLinkage); // 注释掉的代码:绑定点击事件,用于切换行显示状态 /*$('.treeTable .treeTable-icon').click(function () { treetable.toggleRows($(this), param.treeLinkage); });*/ // 如果设置了默认关闭树形结构,则折叠所有节点 if (param.treeDefaultClose) { treetable.foldAll(param.elem); } // 如果存在回调函数,则执行回调函数 if (doneCallback) { doneCallback(res, curr, count); } }; // 渲染表格 table.render(param); }, // 计算缩进的数量 getEmptyNum: function (pid, data) { // 初始化缩进数量为0 var num = 0; // 如果pid不存在,直接返回缩进数量0 if (!pid) { return num; } var tPid; // 遍历数据数组 for (var i = 0; i < data.length; i++) { // 如果当前元素的id与pid匹配 if (pid == data[i].id) { // 增加缩进数量 num += 1; // 更新tPid为当前元素的父id tPid = data[i].pid; // 跳出循环 break; } } return num + treetable.getEmptyNum(tPid, data); }, // 展开/折叠行 toggleRows: function ($dom, linkage) { // 获取当前行的树类型 var type = $dom.attr('lay-ttype'); // 如果当前行是文件类型,则直接返回 if ('file' == type) { return; } // 获取当前行的ID var mId = $dom.attr('lay-tid'); // 判断当前行是否已经展开 var isOpen = $dom.hasClass('open'); // 如果已经展开,则移除展开类,否则添加展开类 if (isOpen) { $dom.removeClass('open'); } else { $dom.addClass('open'); } // 遍历当前行所在的tbody中的所有行 $dom.closest('tbody').find('tr').each(function () { // 获取当前行的图标元素 var $ti = $(this).find('.treeTable-icon'); // 获取当前行的父ID和类型 var pid = $ti.attr('lay-tpid'); var ttype = $ti.attr('lay-ttype'); // 判断当前行的图标是否已经展开 var tOpen = $ti.hasClass('open'); // 如果当前行的父ID与目标ID相同 if (mId == pid) { // 如果目标行已经展开,则隐藏当前行 if (isOpen) { $(this).hide(); // 如果当前行是目录且已经展开,则触发点击事件 if ('dir' == ttype && tOpen == isOpen) { $ti.trigger('click'); } } else { // 如果目标行未展开,则显示当前行 $(this).show(); // 如果需要联动展开且当前行是目录且已经展开,则触发点击事件 if (linkage && 'dir' == ttype && tOpen == isOpen) { $ti.trigger('click'); } } } }); }, // 检查参数 checkParam: function (param) { // 检查参数param的treeSpid属性是否为空或未定义,如果是则弹出提示信息并返回false if (!param.treeSpid && param.treeSpid != 0) { layer.msg('参数treeSpid不能为空', {icon: 5}); return false; } // 检查参数param的treeColIndex属性是否为空或未定义,如果是则弹出提示信息并返回false if (!param.treeColIndex && param.treeColIndex != 0) { layer.msg('参数treeColIndex不能为空', {icon: 5}); return false; } // 如果所有检查都通过,则返回true return true; } }, // 展开所有 expandAll: function (dom) { // 获取传入的DOM元素,并找到其下一个具有'.treeTable'类的元素 $(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () { // 在当前行中找到具有'.treeTable-icon'类的元素 var $ti = $(this).find('.treeTable-icon'); // 获取该元素的'lay-ttype'属性值 var ttype = $ti.attr('lay-ttype'); // 检查该元素是否具有'open'类 var tOpen = $ti.hasClass('open'); // 如果'lay-ttype'属性值为'dir'且没有'open'类,则触发点击事件 if ('dir' == ttype && !tOpen) { $ti.trigger('click'); } }); }, // 折叠所有 foldAll: function (dom) { // 获取传入的DOM元素,并找到其下一个具有'.treeTable'类的元素 $(dom).next('.treeTable').find('.layui-table-body tbody tr').each(function () { // 在当前行中找到具有'.treeTable-icon'类的元素 var $ti = $(this).find('.treeTable-icon'); // 获取该元素的'lay-ttype'属性值 var ttype = $ti.attr('lay-ttype'); // 检查该元素是否具有'open'类 var tOpen = $ti.hasClass('open'); // 如果'lay-ttype'属性值为'dir'且该元素具有'open'类 if ('dir' == ttype && tOpen) { // 触发该元素的点击事件 $ti.trigger('click'); } }); } }; // 加载并链接外部CSS文件,用于树形表格的样式 layui.link(layui.cache.base + 'treetable-lay/treetable.css'); // 给图标列绑定事件 $('body').on('click', '.treeTable .treeTable-icon', function () { // 获取当前点击的图标所在的树表元素的 treeLinkage 属性值 var treeLinkage = $(this).parents('.treeTable').attr('treeLinkage'); // 如果 treeLinkage 属性值为 'true',则调用 treetable.toggleRows 方法并传入 true 参数 if ('true' == treeLinkage) { treetable.toggleRows($(this), true); } else { // 否则调用 treetable.toggleRows 方法并传入 false 参数 treetable.toggleRows($(this), false); } }); }); // 导出名为 'treetable' 的模块,并将其赋值为 treetable 函数或对象 exports('treetable', treetable); });