/**
* Layui Admin Index Module - Theme v2.7.1
* 功能:处理后台管理系统的标签页(Tabs)逻辑,包括打开新标签、切换标签、URL路由监听等。
*/
layui.define(["ywxapp", "http", "route"], function (exports) {
// 获取 Layui 核心模块引用
var $ = layui.$;
var element = layui.element;
var ywxapp = layui.ywxapp;
var http = layui.http;
var route = layui.route;
var setter = layui.setter;
var view = layui.view;
var util = layui.util;
// 状态与配置常量
var tabsPageState = ywxapp.tabsPage; // 当前标签页状态
var TABS_CONTAINER_ID = "layadmin-layout-tabs"; // 标签容器ID
/**
* 核心函数:打开或切换标签页
* @param {Object} options - 配置对象
* @param {String} options.url - 页面URL
* @param {String} options.title - 页面标题
* @param {Boolean} options.escape - 是否转义标题(默认true)
* @param {String} options.highlight - 标题高亮样式
*/
function openOrSwitchTab(options) {
// 合并默认配置
options = $.extend({
url: "",
escape: true
}, options);
var isTabExists = false;
var tabHeaders = $("#LAY_app_tabsheader > li");
// 提取用于匹配的唯一标识(去除协议头和查询参数)
var matchKey = options.url.replace(/(^http(s*):)|(\?[\s\S]*$)/g, "");
// 1. 检查标签是否已存在
tabHeaders.each(function (index) {
if ($(this).attr("lay-id") === options.url) {
isTabExists = true;
tabsPageState.index = index; // 更新当前激活标签索引
}
});
// 设置默认标题
if (!options.title) {
options.title = (tabsPageState.index === 0) ? "" : "\u65b0\u6807\u7b7e\u9875"; // "新标签页"
}
/**
* 执行标签切换动作
*/
function performTabChange() {
element.tabChange(TABS_CONTAINER_ID, options.url);
ywxapp.tabsBodyChange(tabsPageState.index, {
url: options.url,
title: options.title
});
}
// 2. 根据配置决定是新增标签还是刷新现有iframe
if (setter.pageTabs) {
// 如果开启了多标签模式
if (!isTabExists) {
// 延迟添加DOM,确保渲染顺序
setTimeout(function () {
var iframeHtml = [
'
',
'',
"
"
].join("");
$("#LAY_app_body").append(iframeHtml);
performTabChange();
}, 10);
// 添加标签头
var displayTitle = options.title;
if (options.escape) {
displayTitle = util.escape(displayTitle);
}
// 处理标题高亮
var titleHtml = displayTitle;
if (options.highlight) {
titleHtml = '' + displayTitle + "";
}
element.tabAdd(TABS_CONTAINER_ID, {
title: "" + titleHtml + "",
id: options.url,
attr: matchKey
});
// 更新索引为新添加的标签
tabsPageState.index = tabHeaders.length;
} else {
// 标签已存在,直接切换
performTabChange();
}
} else {
// 如果未开启多标签模式,直接在当前iframe中跳转
var currentIframe = ywxapp.tabsBody(ywxapp.tabsPage.index).find(".layadmin-iframe")[0];
if (currentIframe && currentIframe.contentWindow) {
currentIframe.contentWindow.location.href = options.url;
}
// 即使不新增标签,也可能需要更新内部状态
performTabChange();
}
}
/**
* 构建侧边菜单的HTML结构
* @param {Array} data
* @returns
*/
/**
* 递归构建侧边菜单 HTML(支持任意层级)
* - 顶层用 ,嵌套层用 ;有子项者为可展开目录,否则为可点击菜单。
* @param {Array} data 当前层级菜单数组
* @param {Boolean} isTop 是否为顶层(默认 true)
* @returns {String}
*/
function buildSideMenu(data, isTop) {
isTop = isTop !== false;
var html = '';
$.each(data || [], function (i, item) {
var hasChild = item.child && item.child.length > 0;
var tag = isTop ? 'li' : 'dd';
var cls = isTop ? 'layui-nav-item' : '';
if (item.spread) {
cls += (cls ? ' ' : '') + 'layui-nav-itemed';
}
var clsAttr = cls ? ' class="' + cls + '"' : '';
if (hasChild) {
html += '<' + tag + ' data-name="' + item.name + '"' + clsAttr + '>';
if (isTop) {
html += ' ';
html += ' ';
html += ' ' + item.title + '';
html += ' ';
} else {
html += ' ' + item.title + '';
}
// 递归渲染子级,保证第 4 层及更深的菜单也能显示
html += ' ' + buildSideMenu(item.child, false) + '
';
html += '' + tag + '>';
} else {
html += '<' + tag + ' data-name="' + item.name + '"' + clsAttr + '>';
if (isTop) {
html += ' ';
html += ' ';
html += ' ' + item.title + '';
html += ' ';
} else {
html += ' ' + item.title + '';
}
html += '' + tag + '>';
}
});
return html;
}
const menuApi = route.route('menu');
http.get(menuApi).then(function (res) {
if (res.code === 0) {
var html = buildSideMenu(res.data);
$('#LAY-system-side-menu').html(html);
} else {
layer.msg('菜单加载失败: ' + res.msg, { icon: 2 });
}
element.init(); // 重新渲染导航
}).catch(function (error) {
layer.msg('菜单加载失败: ' + error, { icon: 2 });
element.init();
});
/**
* 初始化路由监听与自动渲染
*/
(function initRouter() {
// 自动渲染视图
view().autoRender();
// 监听 Hash 变化
var hashObj = layui.url().hash;
var recordConfig = setter.record || {};
var path = hashObj.href.replace(/^\//, ""); // 去除开头的斜杠
// 尝试从本地存储获取标题
var storedData = layui.data(setter.tableName).record || {};
var savedTitle = storedData[path] || "";
// 如果配置了记录功能且路径有效
if (recordConfig.url && path) {
var cleanPath = $.trim(path);
// 安全检查:如果是外部链接且不属于当前域名,则通过 openOrSwitchTab 处理
// 注意:原代码逻辑中,正则测试失败(即不是外部链接)或者属于当前域名时,可能不走这个分支,
// 但原代码结构是:如果满足条件则调用 n (即 openOrSwitchTab)。
// 原逻辑:/^(\w*:)*\/\/.+/.test(i) && -1 === i.indexOf(location.hostname)
// 意思是:如果是绝对路径且域名不同,则作为新标签打开。
if (/^(\w*:)*\/\/.+/.test(cleanPath) && cleanPath.indexOf(location.hostname) === -1) {
openOrSwitchTab({
url: cleanPath,
title: savedTitle
});
}
}
// 延迟显示主体内容,避免闪烁
setTimeout(function () { $("#" + setter.container).css("visibility", "visible"); }, 3000);
})();
// 导出模块接口http://127.0.0.1/%7B__CTRL__%7D/menu”。
var exportsData = {
openTabsPage: openOrSwitchTab
};
// 扩展 ywxapp 模块的功能
$.extend(ywxapp, exportsData);
// 完成模块定义
exports("index",{});
});