Files
ulthon_admin/public/static/plugs/lay-module/layuimini/miniMenu.js
2026-10-10 13:19:03 +00:00

311 lines
14 KiB
PHP
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.

(function () {
var element = layui.element,
laytpl = layui.laytpl,
layer = layui.layer;
var miniMenu = {
// 菜单数据缓存(renderMultiModule 入口保存,收藏过滤与面板渲染复用;保存原 menuList 引用)
menuData: [],
/**
* 菜单初始化
* @param options.menuList 菜单数据信息
* @param options.menuChildOpen 是否展开子菜单
*/
render: function (options) {
options.menuList = options.menuList || [];
options.menuChildOpen = options.menuChildOpen || false;
if (!ua.checkMobile()) {
miniMenu.renderMultiModule(options.menuList, options.menuChildOpen);
} else {
miniMenu.renderSingleModule(options.menuList, options.menuChildOpen);
}
miniMenu.listen();
},
/**
* 单模块
* @param menuList 菜单数据
* @param menuChildOpen 是否默认展开
*/
renderSingleModule: function (menuList, menuChildOpen) {
menuList = menuList || [];
var leftMenuHtml = '',
childOpenClass = '',
leftMenuCheckDefault = 'layui-this';
var me = this;
if (menuChildOpen) childOpenClass = ' layui-nav-itemed';
leftMenuHtml = this.renderLeftMenu(menuList, { childOpenClass: childOpenClass });
$('.layui-layout-body').addClass('layuimini-single-module'); //单模块标识
$('.layuimini-menu-left').html(leftMenuHtml);
element.init();
},
/**
* 渲染一级菜单
*/
compileMenu: function (menu, isSub) {
var menuHtml = '<li {{#if( d.menu){ }} data-menu="{{-d.menu}}" {{#}}} class="layui-nav-item menu-li {{-d.childOpenClass}} {{-d.className}}" {{#if( d.id){ }} id="{{-d.id}}" {{#}}}> <a title="{{-d.title}}" {{#if( d.href){ }} layuimini-href="{{-d.href}}" {{#}}} {{#if( d.target){ }} target="{{-d.target}}" {{#}}} href="javascript:;">{{#if( d.icon){ }} <i class="{{-d.icon}}"></i> {{#}}} <span class="layui-left-nav">{{-d.title}}</span></a> {{# if(d.children){}} {{-d.children}} {{#}}} </li>';
if (isSub) {
menuHtml = '<dd class="menu-dd {{-d.childOpenClass}} {{- d.className }}"> <a href="javascript:;" title="{{-d.title}}" {{#if( d.menu){ }} data-menu="{{-d.menu}}" {{#}}} {{#if( d.id){ }} id="{{-d.id}}" {{#}}} {{#if(( !d.child || !d.child.length ) && d.href){ }} layuimini-href="{{-d.href}}" {{#}}} {{#if( d.target){ }} target="{{-d.target}}" {{#}}}> {{#if( d.icon){ }} <i class="{{-d.icon}}"></i> {{#}}} <span class="layui-left-nav"> {{-d.title}}</span></a> {{# if(d.children){}} {{-d.children}} {{#}}}</dd>';
}
return laytpl(menuHtml).render(menu);
},
compileMenuContainer: function (menu, isSub) {
var wrapperHtml = '<ul class="layui-nav layui-nav-tree layui-left-nav-tree {{-d.className}}" id="{{-d.id}}">{{-d.children}}</ul>';
if (isSub) {
wrapperHtml = '<dl class="layui-nav-child ">{{-d.children}}</dl>';
}
if (!menu.children) {
return "";
}
return laytpl(wrapperHtml).render(menu);
},
each: function (list, callback) {
var _list = [];
for (var i = 0, length = list.length; i < length; i++) {
_list[i] = callback(i, list[i]);
}
return _list;
},
renderChildrenMenu: function (menuList, options) {
var me = this;
menuList = menuList || [];
var html = this.each(menuList, function (idx, menu) {
if (menu.child && menu.child.length) {
menu.children = me.renderChildrenMenu(menu.child, { childOpenClass: options.childOpenClass || '' });
}
menu.className = "";
menu.childOpenClass = options.childOpenClass || '';
return me.compileMenu(menu, true);
}).join("");
return me.compileMenuContainer({ children: html }, true);
},
renderLeftMenu: function (leftMenus, options) {
options = options || {};
var me = this;
var leftMenusHtml = me.each(leftMenus || [], function (idx, leftMenu) { // 左侧菜单遍历
var children = me.renderChildrenMenu(leftMenu.child, { childOpenClass: options.childOpenClass });
var leftMenuHtml = me.compileMenu({
href: leftMenu.href,
target: leftMenu.target,
childOpenClass: options.childOpenClass,
icon: leftMenu.icon,
title: leftMenu.title,
children: children,
className: '',
});
return leftMenuHtml;
}).join("");
leftMenusHtml = me.compileMenuContainer({ id: options.parentMenuId, className: options.leftMenuCheckDefault, children: leftMenusHtml });
return leftMenusHtml;
},
/**
* 头部模块收藏存储适配层(以 title 为唯一标识,未来可整体替换为后端实现)
*/
getFavorites: function () {
var favorites = [];
try {
favorites = JSON.parse(localStorage.getItem('layuiminiHeaderModuleFavorites'));
} catch (e) {
favorites = [];
}
if (!Array.isArray(favorites)) {
return [];
}
// 与当前菜单 title 求交集,过滤已失效项,保持存储顺序
var valid = [];
miniMenu.each(miniMenu.menuData || [], function (index, menu) {
valid.push(menu.title);
});
var result = [];
miniMenu.each(favorites, function (index, title) {
if (valid.indexOf(title) !== -1) {
result.push(title);
}
});
return result;
},
/**
* 写回收藏列表
*/
setFavorites: function (list) {
localStorage.setItem('layuiminiHeaderModuleFavorites', JSON.stringify(list || []));
},
/**
* 是否已收藏
*/
isFavorite: function (title) {
return miniMenu.getFavorites().indexOf(title) !== -1;
},
/**
* 切换收藏状态,返回切换后的新状态(true=已收藏)
*/
toggleFavorite: function (title) {
var favorites = miniMenu.getFavorites();
var isAdd = favorites.indexOf(title) === -1;
if (isAdd) {
favorites.push(title);
} else {
favorites.splice(favorites.indexOf(title), 1);
}
miniMenu.setFavorites(favorites);
return isAdd;
},
/**
* 头部模块排序:收藏组在前(组内保持菜单原序),未收藏组回填在后(保持菜单原序)
* 返回新数组、不修改入参;multi_module_N 下标仍按原 menuList 索引分配,仅排序显示顺序
* 注:收藏以 title 为唯一标识,顶级模块重名视为同一收藏(同时置顶/同时取消)——
* 框架菜单管理实际不产生重名顶级模块,此为已文档化假设而非保证
*/
sortModules: function (menuList) {
var favorites = miniMenu.getFavorites();
var sorted = [];
var backfill = [];
miniMenu.each(menuList || [], function (index, menu) {
if (favorites.indexOf(menu.title) !== -1) {
sorted.push(menu);
} else {
backfill.push(menu);
}
});
return sorted.concat(backfill);
},
/**
* 多模块
* @param menuList 菜单数据
* @param menuChildOpen 是否默认展开
*/
renderMultiModule: function (menuList, menuChildOpen) {
menuList = menuList || [];
var me = this;
miniMenu.menuData = menuList; //入口保存,注意为原数组引用
var sortedMenuList = this.sortModules(menuList); //头部显示顺序:收藏置顶+原序回填,仅排序不改下标映射
var firstMenu = 'multi_module_' + menuList.indexOf(sortedMenuList[0]); //排序后首模块,首屏一致性锚点
var headerMenuHtml = '',
leftMenuHtml = '',
childOpenClass = '',
headerMenuCheckDefault = 'layui-this';
if (menuChildOpen) childOpenClass = ' layui-nav-itemed';
var headerMenuHtml = this.each(sortedMenuList, function (index, val) { //顶部菜单渲染(按排序后顺序编译,data-menu 仍按原 menuList 下标映射)
var menu = 'multi_module_' + menuList.indexOf(val);
var id = menu + "HeaderId";
var topMenuItemHtml = "";
topMenuItemHtml = me.compileMenu({
className: headerMenuCheckDefault,
menu: menu,
id: id,
title: val.title,
href: "",
target: "",
children: ""
});
headerMenuCheckDefault = "";
return topMenuItemHtml;
}).join("");
leftMenuHtml = this.each(menuList, function (index, val) { //左侧菜单累积与 ul#multi_module_N 分配保持原 menuList 顺序(收藏只影响头部与面板显示顺序)
var menu = 'multi_module_' + index;
var leftMenuCheckDefault = (menu === firstMenu) ? 'layui-this' : 'layui-hide'; //默认可见 ul=排序后首模块,与头部激活项首屏一致
return me.renderLeftMenu(val.child, {
parentMenuId: menu,
childOpenClass: childOpenClass,
leftMenuCheckDefault: leftMenuCheckDefault
});
}).join("");
$('.layui-layout-body').addClass('layuimini-multi-module'); //多模块标识
$('.layuimini-menu-header-pc').html(headerMenuHtml); //电脑
$('.layuimini-menu-left').html(leftMenuHtml);
element.init();
},
/**
* 监听
*/
listen: function () {
/**
* 菜单模块切换
*/
$('body').on('click', '[data-menu]', function () {
var loading = layer.load(0, { shade: false, time: 2 * 1000 });
var menuId = $(this).attr('data-menu');
// header
$(".layuimini-header-menu .layui-nav-item.layui-this").removeClass('layui-this');
$(this).addClass('layui-this');
// left
$(".layuimini-menu-left .layui-nav.layui-nav-tree.layui-this").addClass('layui-hide');
$(".layuimini-menu-left .layui-nav.layui-nav-tree.layui-this.layui-hide").removeClass('layui-this');
$("#" + menuId).removeClass('layui-hide');
$("#" + menuId).addClass('layui-this');
layer.close(loading);
});
/**
* 菜单缩放
*/
$('body').on('click', '.layuimini-site-mobile', function () {
var loading = layer.load(0, { shade: false, time: 2 * 1000 });
var isShow = $('.layuimini-tool [data-side-fold]').attr('data-side-fold');
if (isShow == 1) { // 缩放
$('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0);
$('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent');
$('.layui-layout-body').removeClass('layuimini-all');
$('.layui-layout-body').addClass('layuimini-mini');
} else { // 正常
$('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1);
$('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent');
$('.layui-layout-body').removeClass('layuimini-mini');
$('.layui-layout-body').addClass('layuimini-all');
layer.close(window.openTips);
}
element.init();
layer.close(loading);
});
/**
* 菜单缩放
*/
$('body').on('click', '[data-side-fold]', function () {
var loading = layer.load(0, { shade: false, time: 2 * 1000 });
var isShow = $('.layuimini-tool [data-side-fold]').attr('data-side-fold');
if (isShow == 1) { // 缩放
$('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0);
$('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent');
$('.layui-layout-body').removeClass('layuimini-all');
$('.layui-layout-body').addClass('layuimini-mini');
// $(".menu-li").each(function (idx,el) {
// $(el).addClass("hidden-sub-menu");
// });
} else { // 正常
$('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1);
$('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent');
$('.layui-layout-body').removeClass('layuimini-mini');
$('.layui-layout-body').addClass('layuimini-all');
// $(".menu-li").each(function (idx,el) {
// $(el).removeClass("hidden-sub-menu");
// });
layer.close(window.openTips);
}
element.init();
layer.close(loading);
});
},
};
window.miniMenu = miniMenu;
})();