Files
YwxAppThink/public/static/backend/modules/index.js
T

231 lines
8.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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 = [
'<div class="layadmin-tabsbody-item layui-show">',
'<iframe src="' + options.url + '" frameborder="0" class="layadmin-iframe"></iframe>',
"</div>"
].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 = '<span style="' + options.highlight + '">' + displayTitle + "</span>";
}
element.tabAdd(TABS_CONTAINER_ID, {
title: "<span>" + titleHtml + "</span>",
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(支持任意层级)
* - 顶层用 <li>,嵌套层用 <dd>;有子项者为可展开目录,否则为可点击菜单。
* @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 += ' <a href="javascript:;" lay-tips="' + item.title + '" lay-direction="2">';
html += ' <i class="layui-icon ' + item.icon + '"></i>';
html += ' <cite>' + item.title + '</cite>';
html += ' </a>';
} else {
html += ' <a href="javascript:;">' + item.title + '</a>';
}
// 递归渲染子级,保证第 4 层及更深的菜单也能显示
html += ' <dl class="layui-nav-child">' + buildSideMenu(item.child, false) + '</dl>';
html += '</' + tag + '>';
} else {
html += '<' + tag + ' data-name="' + item.name + '"' + clsAttr + '>';
if (isTop) {
html += ' <a lay-href="' + item.route + '" lay-tips="' + item.title + '" lay-direction="2">';
html += ' <i class="layui-icon ' + item.icon + '"></i>';
html += ' <cite>' + item.title + '</cite>';
html += ' </a>';
} else {
html += ' <a lay-href="' + item.route + '">' + item.title + '</a>';
}
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",{});
});