You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 += '<span class="treeTable-empty"></span>';
}
if (isDir) {
// 如果是目录,添加两个图标:一个三角形和一个图层图标
iconHtml += '<i class="layui-icon layui-icon-triangle-d"></i> <i class="layui-icon layui-icon-layer"></i>';
} else {
// 如果是文件,添加一个文件图标
iconHtml += '<i class="layui-icon layui-icon-file"></i>';
}
// 添加两个空格作为间隔
iconHtml += '&nbsp;&nbsp;';
// 根据是否是目录设置类型为'dir'或'file'
var ttype = isDir ? 'dir' : 'file';
// 创建包含图标和名称的HTML字符串
var vg = '<span class="treeTable-icon open" lay-tid="' + mId + '" lay-tpid="' + mPid + '" lay-ttype="' + ttype + '">';
// 返回完整的HTML字符串
return vg + iconHtml + d[param.cols[0][param.treeColIndex].field] + '</span>'
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);
});