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);
});