miniMenu.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /**
  2. * date:2020/02/27
  3. * author:Mr.Chung
  4. * version:2.0
  5. * description:layuimini 菜单框架扩展
  6. */
  7. layui.define(["element", "laytpl", "jquery", "miniTab"], function (exports) {
  8. var element = layui.element,
  9. $ = layui.$,
  10. laytpl = layui.laytpl,
  11. layer = layui.layer;
  12. var navList = []
  13. var options = {
  14. iniUrl: url.menu, // 初始化接口
  15. clearUrl: "api/clear.json", // 缓存清理接口
  16. urlHashLocation: true, // 是否打开hash定位
  17. bgColorDefault: false, // 主题默认配置
  18. multiModule: false, // 是否开启多模块
  19. menuChildOpen: false, // 是否默认展开菜单
  20. loadingTime: 0, // 初始化加载时间
  21. pageAnim: true, // iframe窗口动画
  22. maxTabNum: 20, // 最大的tab打开数量
  23. };
  24. var miniMenu = {
  25. /**
  26. * 菜单初始化
  27. * @param options.menuList 菜单数据信息
  28. * @param options.multiModule 是否开启多模块
  29. * @param options.menuChildOpen 是否展开子菜单
  30. */
  31. render: function (options) {
  32. options.menuList = options.menuList || [];
  33. options.multiModule = options.multiModule || false;
  34. options.menuChildOpen = options.menuChildOpen || false;
  35. if (options.multiModule) {
  36. miniMenu.renderMultiModule(options.menuList, options.menuChildOpen);
  37. } else {
  38. miniMenu.renderSingleModule(options.menuList, options.menuChildOpen);
  39. }
  40. miniMenu.listen();
  41. miniMenu.bindFunction()
  42. },
  43. /**
  44. * 单模块
  45. * @param menuList 菜单数据
  46. * @param menuChildOpen 是否默认展开
  47. */
  48. renderSingleModule: function (menuList, menuChildOpen) {
  49. menuList = menuList || [];
  50. var leftMenuHtml = '',
  51. childOpenClass = '',
  52. leftMenuCheckDefault = 'layui-this';
  53. var me = this;
  54. if (menuChildOpen) childOpenClass = ' layui-nav-itemed';
  55. leftMenuHtml = this.renderLeftMenu(menuList, { childOpenClass: childOpenClass });
  56. $('.layui-layout-body').addClass('layuimini-single-module'); //单模块标识
  57. $('.layuimini-header-menu').remove();
  58. $('.layuimini-menu-left').html(leftMenuHtml);
  59. var selectLi = '<li class="layui-nav-item search-li"><i class="layui-icon layui-icon-search searchEvent"></i><i class="layui-icon layui-icon-search searchEvent-mini"></i><input value="" id="search" placeholder="请输入搜索内容"><div class="mc-hover-show"><input value="" placeholder="请输入搜索内容"></div> </li>'
  60. $('.layui-left-nav-tree').prepend(selectLi)
  61. element.init();
  62. },
  63. /*搜索导航栏绑定事件*/
  64. bindFunction: function () {
  65. var navData = JSON.parse(sessionStorage.getItem('menu')).menuInfo || []
  66. var selectList = []
  67. $('.layuimini-mini .searchEvent-mini').off('click').click(function () {
  68. $('.mc-hover-show').animate({ left: '60px' })
  69. $('.mc-hover-show input').focus()
  70. })
  71. $('.mc-hover-show input').blur(function () {
  72. $('.mc-hover-show').animate({ left: '-1000px' })
  73. })
  74. $('.mc-hover-show input').off('keydown').keydown(function (e) {
  75. selectList = []
  76. navList = []
  77. if (e.keyCode == 13) {
  78. var value = $(this).val()
  79. var navLsit = miniMenu.getNavList(navData)
  80. if (value) {
  81. for (var i = 0; i < navLsit.length; i++) {
  82. if (navLsit[i].title.indexOf(value) != -1) {
  83. selectList.push(navLsit[i])
  84. }
  85. }
  86. var htmlStr = '<dl class="layui-nav-child tips-dd">{innerHTML}</dl>'
  87. var innerHTML = ''
  88. for (var i = 0; i < selectList.length; i++) {
  89. innerHTML += '<dd><a href="javascript:;" class="layui-menu-tips" layuimini-href="' + selectList[i].href + '" target="_self"><iclass="layui-icon layui-icon-ok-circle"></i><span class="layui-left-nav">' + selectList[i].title + '</span></a></dd>'
  90. }
  91. var html = htmlStr.replace('{innerHTML}', innerHTML)
  92. window.openTips = layer.tips(html, $(this), {
  93. tips: [2, '#2f4056'],
  94. time: 300000,
  95. skin: "popup-tips",
  96. success: function (el) {
  97. $(el).css({ left: 60, top: 30 });
  98. element.render();
  99. $('.mc-hover-show').animate({ left: '-1000px' })
  100. }
  101. });
  102. miniMenu.listen();
  103. }
  104. }
  105. })
  106. $('#search').keydown(function (e) {
  107. selectList = []
  108. navList = []
  109. if (e.keyCode == 13) {
  110. var value = $('#search').val()
  111. var navLsit = miniMenu.getNavList(navData)
  112. if (value) {
  113. for (var i = 0; i < navLsit.length; i++) {
  114. if (navLsit[i].title.indexOf(value) != -1) {
  115. selectList.push(navLsit[i])
  116. }
  117. }
  118. miniMenu.render(Object.assign({ menuList: selectList }, miniMenu, options));
  119. } else {
  120. miniMenu.render(Object.assign({ menuList: JSON.parse(sessionStorage.getItem('menu')).menuInfo }, options))
  121. }
  122. }
  123. })
  124. $('.searchEvent').click(function () {
  125. selectList = []
  126. navList = []
  127. var value = $('#search').val()
  128. var navLsit = miniMenu.getNavList(navData)
  129. if (value) {
  130. for (var i = 0; i < navLsit.length; i++) {
  131. if (navLsit[i].title.indexOf(value) != -1) {
  132. selectList.push(navLsit[i])
  133. }
  134. }
  135. miniMenu.render(Object.assign({ menuList: selectList }, miniMenu, options));
  136. } else {
  137. miniMenu.render(Object.assign({ menuList: JSON.parse(sessionStorage.getItem('menu')).menuInfo }, options))
  138. }
  139. })
  140. },
  141. // 格式化导航栏数据
  142. getNavList: function (list) {
  143. for (var i = 0; i < list.length; i++) {
  144. if (list[i].href != '#') {
  145. navList.push({
  146. title: list[i].title,
  147. href: list[i].href,
  148. target: list[i].target
  149. })
  150. }
  151. if (list[i].child && list[i].child.length != 0) {
  152. miniMenu.getNavList(list[i].child)
  153. }
  154. }
  155. return navList
  156. },
  157. /**
  158. * 渲染一级菜单
  159. */
  160. compileMenu: function (menu, isSub) {
  161. 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 {{#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>';
  162. if (isSub) {
  163. menuHtml = '<dd class="menu-dd {{d.childOpenClass}} {{ d.className }}"> <a href="javascript:;" {{#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>'
  164. }
  165. return laytpl(menuHtml).render(menu);
  166. },
  167. compileMenuContainer: function (menu, isSub) {
  168. var wrapperHtml = '<ul class="layui-nav layui-nav-tree layui-left-nav-tree {{d.className}}" id="{{d.id}}">{{d.children}}</ul>';
  169. if (isSub) {
  170. wrapperHtml = '<dl class="layui-nav-child ">{{d.children}}</dl>';
  171. }
  172. if (!menu.children) {
  173. return "";
  174. }
  175. return laytpl(wrapperHtml).render(menu);
  176. },
  177. each: function (list, callback) {
  178. var _list = [];
  179. for (var i = 0, length = list.length; i < length; i++) {
  180. _list[i] = callback(i, list[i]);
  181. }
  182. return _list;
  183. },
  184. renderChildrenMenu: function (menuList, options) {
  185. var me = this;
  186. menuList = menuList || [];
  187. var html = this.each(menuList, function (idx, menu) {
  188. if (menu.child && menu.child.length) {
  189. menu.children = me.renderChildrenMenu(menu.child, { childOpenClass: options.childOpenClass || '' });
  190. }
  191. menu.className = "";
  192. menu.childOpenClass = options.childOpenClass || ''
  193. return me.compileMenu(menu, true)
  194. }).join("");
  195. return me.compileMenuContainer({ children: html }, true)
  196. },
  197. renderLeftMenu: function (leftMenus, options) {
  198. options = options || {};
  199. var me = this;
  200. var leftMenusHtml = me.each(leftMenus || [], function (idx, leftMenu) { // 左侧菜单遍历
  201. var children = me.renderChildrenMenu(leftMenu.child, { childOpenClass: options.childOpenClass });
  202. var leftMenuHtml = me.compileMenu({
  203. href: leftMenu.href,
  204. target: leftMenu.target,
  205. childOpenClass: options.childOpenClass,
  206. icon: leftMenu.icon,
  207. title: leftMenu.title,
  208. children: children,
  209. className: '',
  210. });
  211. return leftMenuHtml;
  212. }).join("");
  213. leftMenusHtml = me.compileMenuContainer({ id: options.parentMenuId, className: options.leftMenuCheckDefault, children: leftMenusHtml });
  214. return leftMenusHtml;
  215. },
  216. /**
  217. * 多模块
  218. * @param menuList 菜单数据
  219. * @param menuChildOpen 是否默认展开
  220. */
  221. renderMultiModule: function (menuList, menuChildOpen) {
  222. menuList = menuList || [];
  223. var me = this;
  224. var headerMenuHtml = '',
  225. headerMobileMenuHtml = '',
  226. leftMenuHtml = '',
  227. leftMenuCheckDefault = 'layui-this',
  228. childOpenClass = '',
  229. headerMenuCheckDefault = 'layui-this';
  230. if (menuChildOpen) childOpenClass = ' layui-nav-itemed';
  231. var headerMenuHtml = this.each(menuList, function (index, val) { //顶部菜单渲染
  232. var menu = 'multi_module_' + index;
  233. var id = menu + "HeaderId";
  234. var topMenuItemHtml = "";
  235. topMenuItemHtml = me.compileMenu({
  236. className: headerMenuCheckDefault,
  237. menu: menu,
  238. id: id,
  239. title: val.title,
  240. href: "",
  241. target: "",
  242. children: ""
  243. });
  244. leftMenuHtml += me.renderLeftMenu(val.child, {
  245. parentMenuId: menu,
  246. childOpenClass: childOpenClass,
  247. leftMenuCheckDefault: leftMenuCheckDefault
  248. });
  249. headerMobileMenuHtml += me.compileMenu({ id: id, menu: menu, id: id, icon: val.icon, title: val.title, }, true);
  250. headerMenuCheckDefault = "";
  251. leftMenuCheckDefault = "layui-hide";
  252. return topMenuItemHtml;
  253. }).join("");
  254. $('.layui-layout-body').addClass('layuimini-multi-module'); //多模块标识
  255. $('.layuimini-menu-header-pc').html(headerMenuHtml); //电脑
  256. $('.layuimini-menu-left').html(leftMenuHtml);
  257. $('.layuimini-menu-header-mobile').html(headerMobileMenuHtml); //手机
  258. element.init();
  259. },
  260. /**
  261. * 监听
  262. */
  263. listen: function () {
  264. /**
  265. * 菜单模块切换
  266. */
  267. $('body').on('click', '[data-menu]', function () {
  268. var loading = layer.load(0, { shade: false, time: 2 * 1000 });
  269. var menuId = $(this).attr('data-menu');
  270. // header
  271. $(".layuimini-header-menu .layui-nav-item.layui-this").removeClass('layui-this');
  272. $(this).addClass('layui-this');
  273. // left
  274. $(".layuimini-menu-left .layui-nav.layui-nav-tree.layui-this").addClass('layui-hide');
  275. $(".layuimini-menu-left .layui-nav.layui-nav-tree.layui-this.layui-hide").removeClass('layui-this');
  276. $("#" + menuId).removeClass('layui-hide');
  277. $("#" + menuId).addClass('layui-this');
  278. layer.close(loading);
  279. });
  280. /**
  281. * 菜单缩放
  282. */
  283. $('body').off('click').on('click', '.layuimini-site-mobile', function () {
  284. var loading = layer.load(0, { shade: false, time: 2 * 1000 });
  285. var isShow = $('.layuimini-tool [data-side-fold]').attr('data-side-fold');
  286. if (isShow == 1) { // 缩放
  287. $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0);
  288. $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent');
  289. $('.layui-layout-body').removeClass('layuimini-all');
  290. $('.layui-layout-body').addClass('layuimini-mini');
  291. } else { // 正常
  292. $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1);
  293. $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent');
  294. $('.layui-layout-body').removeClass('layuimini-mini');
  295. $('.layui-layout-body').addClass('layuimini-all');
  296. layer.close(window.openTips);
  297. }
  298. element.init();
  299. layer.close(loading);
  300. });
  301. /**
  302. * 菜单缩放
  303. */
  304. $('body').on('click', '[data-side-fold]', function () {
  305. var loading = layer.load(0, { shade: false, time: 2 * 1000 });
  306. var isShow = $('.layuimini-tool [data-side-fold]').attr('data-side-fold');
  307. if (isShow == 1) { // 缩放
  308. $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 0);
  309. $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-indent');
  310. $('.layui-layout-body').removeClass('layuimini-all');
  311. $('.layui-layout-body').addClass('layuimini-mini');
  312. // $(".menu-li").each(function (idx,el) {
  313. // $(el).addClass("hidden-sub-menu");
  314. // });
  315. } else { // 正常
  316. $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1);
  317. $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent');
  318. $('.layui-layout-body').removeClass('layuimini-mini');
  319. $('.layui-layout-body').addClass('layuimini-all');
  320. // $(".menu-li").each(function (idx,el) {
  321. // $(el).removeClass("hidden-sub-menu");
  322. // });
  323. layer.close(window.openTips);
  324. }
  325. element.init();
  326. layer.close(loading);
  327. miniMenu.bindFunction()
  328. });
  329. /**
  330. * 手机端点开模块
  331. */
  332. $('body').on('click', '.layuimini-header-menu.layuimini-mobile-show dd', function () {
  333. var loading = layer.load(0, { shade: false, time: 2 * 1000 });
  334. var check = $('.layuimini-tool [data-side-fold]').attr('data-side-fold');
  335. if (check === "1") {
  336. $('.layuimini-site-mobile').trigger("click");
  337. element.init();
  338. }
  339. layer.close(loading);
  340. });
  341. $('body').on('click', '.layuimini-make', function () {
  342. $('.layuimini-tool [data-side-fold]').attr('data-side-fold', 1);
  343. $('.layuimini-tool [data-side-fold]').attr('class', 'fa fa-outdent');
  344. $('.layui-layout-body').removeClass('layuimini-mini');
  345. $('.layui-layout-body').addClass('layuimini-all');
  346. layer.close(window.openTips);
  347. });
  348. // 菜单跳转
  349. $('body').on('click', '[layuimini-href]', function () {
  350. var loading = layer.load(0, { shade: false, time: 2 * 1000 });
  351. var tabId = $(this).attr('layuimini-href'),
  352. href = $(this).attr('layuimini-href'),
  353. title = $(this).text(),
  354. target = $(this).attr('target');
  355. var el = $("[layuimini-href='" + href + "']", ".layuimini-menu-left");
  356. layer.close(window.openTips);
  357. if (el.length) {
  358. $(el).closest(".layui-nav-tree").find(".layui-this").removeClass("layui-this");
  359. $(el).parent().addClass("layui-this");
  360. }
  361. if (target === '_blank') {
  362. layer.close(loading);
  363. window.open(href, "_blank");
  364. return false;
  365. }
  366. if (tabId === null || tabId === undefined) tabId = new Date().getTime();
  367. var checkTab = miniTab.check(tabId);
  368. if (!checkTab) {
  369. miniTab.create({
  370. tabId: tabId,
  371. href: href,
  372. title: title,
  373. isIframe: false,
  374. maxTabNum: options.maxTabNum,
  375. });
  376. }
  377. element.tabChange('layuiminiTab', tabId);
  378. layer.close(loading);
  379. });
  380. },
  381. };
  382. exports("miniMenu", miniMenu);
  383. });