kkk 2 years ago
parent
commit
33805321a0

+ 836 - 0
src/main/webapp/skin/default/layuiadmin/lib/admin.js

@@ -0,0 +1,836 @@
+/**
+
+ @Name:layuiAdmin iframe版核心模块
+ @Author:贤心
+ @Site:http://www.layui.com/admin/
+ @License:LPPL
+    
+ */
+ 
+layui.define('view', function(exports){
+  var $ = layui.jquery
+  ,laytpl = layui.laytpl
+  ,element = layui.element
+  ,setter = layui.setter
+  ,view = layui.view
+  ,device = layui.device()
+  
+  ,$win = $(window), $body = $('body')
+  ,container = $('#'+ setter.container)
+  
+  ,SHOW = 'layui-show', HIDE = 'layui-hide', THIS = 'layui-this', DISABLED = 'layui-disabled', TEMP = 'template'
+  ,APP_BODY = '#LAY_app_body', APP_FLEXIBLE = 'LAY_app_flexible'
+  ,FILTER_TAB_TBAS = 'layadmin-layout-tabs'
+  ,APP_SPREAD_SM = 'layadmin-side-spread-sm', TABS_BODY = 'layadmin-tabsbody-item'
+  ,ICON_SHRINK = 'layui-icon-shrink-right', ICON_SPREAD = 'layui-icon-spread-left'
+  ,SIDE_SHRINK = 'layadmin-side-shrink', SIDE_MENU = 'LAY-system-side-menu'
+
+  //通用方法
+  ,admin = {
+    v: '1.2.1 std'
+    
+    //数据的异步请求
+    ,req: view.req
+    
+    //清除本地 token,并跳转到登入页
+    ,exit: view.exit
+    
+    //xss 转义
+    ,escape: function(html){
+      return String(html || '').replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&')
+      .replace(/</g, '&lt;').replace(/>/g, '&gt;')
+      .replace(/'/g, '&#39;').replace(/"/g, '&quot;');
+    }
+    
+    //事件监听
+    ,on: function(events, callback){
+      return layui.onevent.call(this, setter.MOD_NAME, events, callback);
+    }
+    
+    //发送验证码
+    ,sendAuthCode: function(options){
+      options = $.extend({
+        seconds: 60
+        ,elemPhone: '#LAY_phone'
+        ,elemVercode: '#LAY_vercode'
+      }, options);
+
+      var seconds = options.seconds
+      ,btn = $(options.elem)
+      ,token = null
+      ,timer, countDown = function(loop){
+        seconds--;
+        if(seconds < 0){
+          btn.removeClass(DISABLED).html('获取验证码');
+          seconds = options.seconds;
+          clearInterval(timer);
+        } else {
+          btn.addClass(DISABLED).html(seconds + '秒后重获');
+        }
+
+        if(!loop){
+          timer = setInterval(function(){
+            countDown(true);
+          }, 1000);
+        }
+      };
+      
+      options.elemPhone = $(options.elemPhone);
+      options.elemVercode = $(options.elemVercode);
+
+      btn.on('click', function(){
+        var elemPhone = options.elemPhone
+        ,value = elemPhone.val();
+
+        if(seconds !== options.seconds || $(this).hasClass(DISABLED)) return;
+
+        if(!/^1\d{10}$/.test(value)){
+          elemPhone.focus();
+          return layer.msg('请输入正确的手机号')
+        };
+        
+        if(typeof options.ajax === 'object'){
+          var success = options.ajax.success;
+          delete options.ajax.success;
+        }
+        
+        admin.req($.extend(true, {
+          url: '/auth/code'
+          ,type: 'get'
+          ,data: {
+            phone: value
+          }
+          ,success: function(res){
+            layer.msg('验证码已发送至你的手机,请注意查收', {
+              icon: 1
+              ,shade: 0
+            });
+            options.elemVercode.focus();
+            countDown();
+            success && success(res);
+          }
+        }, options.ajax));
+      });
+    }
+    
+    //屏幕类型
+    ,screen: function(){
+      var width = $win.width()
+      if(width > 1200){
+        return 3; //大屏幕
+      } else if(width > 992){
+        return 2; //中屏幕
+      } else if(width > 768){
+        return 1; //小屏幕
+      } else {
+        return 0; //超小屏幕
+      }
+    }
+    
+    //侧边伸缩
+    ,sideFlexible: function(status){
+      var app = container
+      ,iconElem =  $('#'+ APP_FLEXIBLE)
+      ,screen = admin.screen();
+
+      //设置状态,PC:默认展开、移动:默认收缩
+      if(status === 'spread'){
+        //切换到展开状态的 icon,箭头:←
+        iconElem.removeClass(ICON_SPREAD).addClass(ICON_SHRINK);
+        
+        //移动:从左到右位移;PC:清除多余选择器恢复默认
+        if(screen < 2){
+          app.addClass(APP_SPREAD_SM);
+        } else {
+          app.removeClass(APP_SPREAD_SM);
+        }
+        
+        app.removeClass(SIDE_SHRINK)
+      } else {
+        //切换到搜索状态的 icon,箭头:→
+        iconElem.removeClass(ICON_SHRINK).addClass(ICON_SPREAD);
+        
+        //移动:清除多余选择器恢复默认;PC:从右往左收缩
+        if(screen < 2){
+          app.removeClass(SIDE_SHRINK);
+        } else {
+          app.addClass(SIDE_SHRINK);
+        }
+        
+        app.removeClass(APP_SPREAD_SM)
+      }
+      
+      layui.event.call(this, setter.MOD_NAME, 'side({*})', {
+        status: status
+      });
+    }
+    
+    //弹出面板
+    ,popup: view.popup
+    
+    //右侧面板
+    ,popupRight: function(options){
+      //layer.close(admin.popup.index);
+      return admin.popup.index = layer.open($.extend({
+        type: 1
+        ,id: 'LAY_adminPopupR'
+        ,anim: -1
+        ,title: false
+        ,closeBtn: false
+        ,offset: 'r'
+        ,shade: 0.1
+        ,shadeClose: true
+        ,skin: 'layui-anim layui-anim-rl layui-layer-adminRight'
+        ,area: '300px'
+      }, options));
+    }
+    
+    //主题设置
+    ,theme: function(options){
+      var theme = setter.theme
+      ,local = layui.data(setter.tableName)
+      ,id = 'LAY_layadmin_theme'
+      ,style = document.createElement('style')
+      ,styleText = laytpl([
+        //主题色
+        '.layui-side-menu,'
+        ,'.layadmin-pagetabs .layui-tab-title li:after,'
+        ,'.layadmin-pagetabs .layui-tab-title li.layui-this:after,'
+        ,'.layui-layer-admin .layui-layer-title,'
+        ,'.layadmin-side-shrink .layui-side-menu .layui-nav>.layui-nav-item>.layui-nav-child'
+        ,'{background-color:{{d.color.main}} !important;}'
+ 
+        //选中色
+        ,'.layui-nav-tree .layui-this,'
+        ,'.layui-nav-tree .layui-this>a,'
+        ,'.layui-nav-tree .layui-nav-child dd.layui-this,'
+        ,'.layui-nav-tree .layui-nav-child dd.layui-this a'
+        ,'{background-color:{{d.color.selected}} !important;}'
+        
+        //logo
+        ,'.layui-layout-admin .layui-logo{background-color:{{d.color.logo || d.color.main}} !important;}'
+        
+        //头部色
+        ,'{{# if(d.color.header){ }}'
+          ,'.layui-layout-admin .layui-header{background-color:{{ d.color.header }};}'
+          ,'.layui-layout-admin .layui-header a,'
+          ,'.layui-layout-admin .layui-header a cite{color: #f8f8f8;}'
+          ,'.layui-layout-admin .layui-header a:hover{color: #fff;}'
+          ,'.layui-layout-admin .layui-header .layui-nav .layui-nav-more{border-top-color: #fbfbfb;}'
+          ,'.layui-layout-admin .layui-header .layui-nav .layui-nav-mored{border-color: transparent; border-bottom-color: #fbfbfb;}'
+          ,'.layui-layout-admin .layui-header .layui-nav .layui-this:after, .layui-layout-admin .layui-header .layui-nav-bar{background-color: #fff; background-color: rgba(255,255,255,.5);}'
+          ,'.layadmin-pagetabs .layui-tab-title li:after{display: none;}'
+        ,'{{# } }}'
+      ].join('')).render(options = $.extend({}, local.theme, options))
+      ,styleElem = document.getElementById(id);
+      
+      //添加主题样式
+      if('styleSheet' in style){
+        style.setAttribute('type', 'text/css');
+        style.styleSheet.cssText = styleText;
+      } else {
+        style.innerHTML = styleText;
+      }
+      style.id = id;
+      
+      styleElem && $body[0].removeChild(styleElem);
+      $body[0].appendChild(style);
+      $body.attr('layadmin-themealias', options.color.alias);
+      
+      //本地存储记录
+      local.theme = local.theme || {};
+      layui.each(options, function(key, value){
+        local.theme[key] = value;
+      });
+      layui.data(setter.tableName, {
+        key: 'theme'
+        ,value: local.theme
+      }); 
+    }
+    
+    //初始化主题
+    ,initTheme: function(index){
+      var theme = setter.theme;
+      index = index || 0;
+      if(theme.color[index]){
+        theme.color[index].index = index;
+        admin.theme({
+          color: theme.color[index]
+        });
+      }
+    }
+    
+    //记录最近一次点击的页面标签数据
+    ,tabsPage: {}
+    
+    //获取页面标签主体元素
+    ,tabsBody: function(index){
+      return $(APP_BODY).find('.'+ TABS_BODY).eq(index || 0);
+    }
+    
+    //切换页面标签主体
+    ,tabsBodyChange: function(index, options){
+      options = options || {};
+      
+      admin.tabsBody(index).addClass(SHOW).siblings().removeClass(SHOW);
+      events.rollPage('auto', index);
+      
+      //执行 {setter.MOD_NAME}.tabsPage 下的事件
+      layui.event.call(this, setter.MOD_NAME, 'tabsPage({*})', {
+        url: options.url
+        ,text: options.text
+      });
+    }
+    
+    //resize事件管理
+    ,resize: function(fn){
+      var router = layui.router()
+      ,key = router.path.join('-');
+      
+      if(admin.resizeFn[key]){
+        $win.off('resize', admin.resizeFn[key]);
+        delete admin.resizeFn[key];
+      }
+      
+      if(fn === 'off') return; //如果是清除 resize 事件,则终止往下执行
+      
+      fn(), admin.resizeFn[key] = fn;
+      $win.on('resize', admin.resizeFn[key]);
+    }
+    ,resizeFn: {}
+    ,runResize: function(){
+      var router = layui.router()
+      ,key = router.path.join('-');
+      admin.resizeFn[key] && admin.resizeFn[key]();
+    }
+    ,delResize: function(){
+      this.resize('off');
+    }
+    
+    //关闭当前 pageTabs
+    ,closeThisTabs: function(){
+      if(!admin.tabsPage.index) return;
+      $(TABS_HEADER).eq(admin.tabsPage.index).find('.layui-tab-close').trigger('click');
+    }
+    
+    //全屏
+    ,fullScreen: function(){
+      var ele = document.documentElement
+      ,reqFullScreen = ele.requestFullScreen || ele.webkitRequestFullScreen 
+      || ele.mozRequestFullScreen || ele.msRequestFullscreen;      
+      if(typeof reqFullScreen !== 'undefined' && reqFullScreen) {
+        reqFullScreen.call(ele);
+      };
+    }
+    
+    //退出全屏
+    ,exitScreen: function(){
+      var ele = document.documentElement
+      if (document.exitFullscreen) {  
+        document.exitFullscreen();  
+      } else if (document.mozCancelFullScreen) {  
+        document.mozCancelFullScreen();  
+      } else if (document.webkitCancelFullScreen) {  
+        document.webkitCancelFullScreen();  
+      } else if (document.msExitFullscreen) {  
+        document.msExitFullscreen();  
+      }
+    }
+    
+    //……
+  };
+  
+  //事件
+  var events = admin.events = {
+    //伸缩
+    flexible: function(othis){
+      var iconElem = othis.find('#'+ APP_FLEXIBLE)
+      ,isSpread = iconElem.hasClass(ICON_SPREAD);
+      admin.sideFlexible(isSpread ? 'spread' : null);
+    }
+    
+    //刷新
+    ,refresh: function(){
+      var ELEM_IFRAME = '.layadmin-iframe'
+      ,length = $('.'+ TABS_BODY).length;
+      
+      if(admin.tabsPage.index >= length){
+        admin.tabsPage.index = length - 1;
+      }
+      
+      var iframe = admin.tabsBody(admin.tabsPage.index).find(ELEM_IFRAME);
+      iframe[0].contentWindow.location.reload(true);
+    }
+
+    //输入框搜索
+    ,serach: function(othis){
+      othis.off('keypress').on('keypress',function(e){
+        if(!this.value.replace(/\s/g, '')) return;
+        //回车跳转
+        if(e.keyCode === 13){
+          var href = othis.attr('lay-action')
+          ,text = othis.attr('lay-text') || '搜索';
+          
+          href = href + this.value;
+          text = text + ' <span style="color: #FF5722;">'+ admin.escape(this.value) +'</span>';
+          
+          //打开标签页
+          layui.index.openTabsPage(href, text);
+          
+          //如果搜索关键词已经打开,则刷新页面即可
+          events.serach.keys || (events.serach.keys = {});
+          events.serach.keys[admin.tabsPage.index] = this.value;
+          if(this.value === events.serach.keys[admin.tabsPage.index]){
+            events.refresh(othis);
+          }
+          
+          //清空输入框
+          this.value = '';
+        }       
+      });
+    }
+    
+    //点击消息
+    ,message: function(othis){
+      othis.find('.layui-badge-dot').remove();
+    }
+    
+    //弹出主题面板
+    ,theme: function(){
+      admin.popupRight({
+        id: 'LAY_adminPopupTheme'
+        ,success: function(){
+          view(this.id).render('system/theme')
+        }
+      });
+    }
+    
+    //便签
+    ,note: function(othis){
+      var mobile = admin.screen() < 2
+      ,note = layui.data(setter.tableName).note;
+      
+      events.note.index = admin.popup({
+        title: '便签'
+        ,shade: 0
+        ,offset: [
+          '41px'
+          ,(mobile ? null : (othis.offset().left - 250) + 'px')
+        ]
+        ,anim: -1
+        ,id: 'LAY_adminNote'
+        ,skin: 'layadmin-note layui-anim layui-anim-upbit'
+        ,content: '<textarea placeholder="内容"></textarea>'
+        ,resize: false
+        ,success: function(layero, index){
+          var textarea = layero.find('textarea')
+          ,value = note === undefined ? '便签中的内容会存储在本地,这样即便你关掉了浏览器,在下次打开时,依然会读取到上一次的记录。是个非常小巧实用的本地备忘录' : note;
+          
+          textarea.val(value).focus().on('keyup', function(){
+            layui.data(setter.tableName, {
+              key: 'note'
+              ,value: this.value
+            });
+          });
+        }
+      })
+    }
+
+    //全屏
+    ,fullscreen: function(othis){
+      var SCREEN_FULL = 'layui-icon-screen-full'
+      ,SCREEN_REST = 'layui-icon-screen-restore'
+      ,iconElem = othis.children("i");
+      
+      if(iconElem.hasClass(SCREEN_FULL)){
+        admin.fullScreen();
+        iconElem.addClass(SCREEN_REST).removeClass(SCREEN_FULL);
+      } else {
+        admin.exitScreen();
+        iconElem.addClass(SCREEN_FULL).removeClass(SCREEN_REST);
+      }
+    }
+
+    //弹出关于面板
+    ,about: function(){
+      admin.popupRight({
+        id: 'LAY_adminPopupAbout'
+        ,success: function(){
+          view(this.id).render('system/about');
+        }
+      });
+    }
+    
+    //弹出更多面板
+    ,more: function(){
+      admin.popupRight({
+        id: 'LAY_adminPopupMore'
+        ,success: function(){
+          view(this.id).render('system/more');
+        }
+      });
+    }
+    
+    //返回上一页
+    ,back: function(){
+      history.back();
+    }
+    
+    //主题设置
+    ,setTheme: function(othis){
+      var index = othis.data('index')
+      ,nextIndex = othis.siblings('.layui-this').data('index');
+      
+      if(othis.hasClass(THIS)) return;
+      
+      othis.addClass(THIS).siblings('.layui-this').removeClass(THIS);
+      admin.initTheme(index);
+    }
+    
+    //左右滚动页面标签
+    ,rollPage: function(type, index){
+      var tabsHeader = $('#LAY_app_tabsheader')
+      ,liItem = tabsHeader.children('li')
+      ,scrollWidth = tabsHeader.prop('scrollWidth')
+      ,outerWidth = tabsHeader.outerWidth()
+      ,tabsLeft = parseFloat(tabsHeader.css('left'));
+      
+      //右左往右
+      if(type === 'left'){
+        if(!tabsLeft && tabsLeft <=0) return;
+        
+        //当前的left减去可视宽度,用于与上一轮的页标比较
+        var  prefLeft = -tabsLeft - outerWidth; 
+
+        liItem.each(function(index, item){
+          var li = $(item)
+          ,left = li.position().left;
+          
+          if(left >= prefLeft){
+            tabsHeader.css('left', -left);
+            return false;
+          }
+        });
+      } else if(type === 'auto'){ //自动滚动
+        (function(){
+          var thisLi = liItem.eq(index), thisLeft;
+          
+          if(!thisLi[0]) return;
+          thisLeft = thisLi.position().left;
+          
+          //当目标标签在可视区域左侧时
+          if(thisLeft < -tabsLeft){
+            return tabsHeader.css('left', -thisLeft);
+          }
+          
+          //当目标标签在可视区域右侧时
+          if(thisLeft + thisLi.outerWidth() >= outerWidth - tabsLeft){
+            var subLeft = thisLeft + thisLi.outerWidth() - (outerWidth - tabsLeft);
+            liItem.each(function(i, item){
+              var li = $(item)
+              ,left = li.position().left;
+              
+              //从当前可视区域的最左第二个节点遍历,如果减去最左节点的差 > 目标在右侧不可见的宽度,则将该节点放置可视区域最左
+              if(left + tabsLeft > 0){
+                if(left - tabsLeft > subLeft){
+                  tabsHeader.css('left', -left);
+                  return false;
+                }
+              }
+            });
+          }
+        }());
+      } else {
+        //默认向左滚动
+        liItem.each(function(i, item){
+          var li = $(item)
+          ,left = li.position().left;
+
+          if(left + li.outerWidth() >= outerWidth - tabsLeft){
+            tabsHeader.css('left', -left);
+            return false;
+          }
+        });
+      }      
+    }
+    
+    //向右滚动页面标签
+    ,leftPage: function(){
+      events.rollPage('left');
+    }
+    
+    //向左滚动页面标签
+    ,rightPage: function(){
+      events.rollPage();
+    }
+    
+    //关闭当前标签页
+    ,closeThisTabs: function(){
+      var topAdmin = parent === self ? admin : parent.layui.admin;
+      topAdmin.closeThisTabs();
+    }
+    
+    //关闭其它标签页
+    ,closeOtherTabs: function(type){
+      var TABS_REMOVE = 'LAY-system-pagetabs-remove';
+      if(type === 'all'){
+        $(TABS_HEADER+ ':gt(0)').remove();
+        $(APP_BODY).find('.'+ TABS_BODY+ ':gt(0)').remove();
+
+        $(TABS_HEADER).eq(0).trigger('click');
+      } else {
+        $(TABS_HEADER).each(function(index, item){
+          if(index && index != admin.tabsPage.index){
+            $(item).addClass(TABS_REMOVE);
+            admin.tabsBody(index).addClass(TABS_REMOVE);
+          }
+        });
+        $('.'+ TABS_REMOVE).remove();
+      }
+    }
+    
+    //关闭全部标签页
+    ,closeAllTabs: function(){
+      events.closeOtherTabs('all');
+      //location.hash = '';
+    }
+    
+    //遮罩
+    ,shade: function(){
+      admin.sideFlexible();
+    }
+    
+    //呼出IM 示例
+    // ,im: function(){
+    //   admin.popup({
+    //     id: 'LAY-popup-layim-demo' //定义唯一ID,防止重复弹出
+    //     ,shade: 0
+    //     ,area: ['800px', '300px']
+    //     ,title: '面板外的操作示例'
+    //     ,offset: 'lb'
+    //     ,success: function(){
+    //       //将 views 目录下的某视图文件内容渲染给该面板
+    //       layui.view(this.id).render('layim/demo').then(function(){
+    //         layui.use('im');
+    //       });
+    //     }
+    //   })
+    // }
+  };
+  
+  //初始
+  !function(){
+    //主题初始化,本地主题记录优先,其次为 initColorIndex
+    var local = layui.data(setter.tableName);
+    if(local.theme){
+      admin.theme(local.theme);
+    } else if(setter.theme){
+      admin.initTheme(setter.theme.initColorIndex);
+    }
+    
+    //常规版默认开启多标签页
+    if(!('pageTabs' in layui.setter)) layui.setter.pageTabs = true;
+    
+    //不开启页面标签时
+    if(!setter.pageTabs){
+      $('#LAY_app_tabs').addClass(HIDE);
+      container.addClass('layadmin-tabspage-none');
+    }
+
+    //低版本IE提示
+    if(device.ie && device.ie < 10){
+      view.error('IE'+ device.ie + '下访问可能不佳,推荐使用:Chrome / Firefox / Edge 等高级浏览器', {
+        offset: 'auto'
+        ,id: 'LAY_errorIE'
+      });
+    }
+    
+  }();
+  
+  //admin.prevRouter = {}; //上一个路由
+  
+  //监听 tab 组件切换,同步 index
+  element.on('tab('+ FILTER_TAB_TBAS +')', function(data){
+    admin.tabsPage.index = data.index;
+  });
+  
+  //监听选项卡切换,改变菜单状态
+  admin.on('tabsPage(setMenustatus)', function(router){
+    var pathURL = router.url, getData = function(item){
+      return {
+        list: item.children('.layui-nav-child')
+        ,a: item.children('*[lay-href]')
+      }
+    }
+    ,sideMenu = $('#'+ SIDE_MENU)
+    ,SIDE_NAV_ITEMD = 'layui-nav-itemed'
+    
+    //捕获对应菜单
+    ,matchMenu = function(list){
+      list.each(function(index1, item1){
+        var othis1 = $(item1)
+        ,data1 = getData(othis1)
+        ,listChildren1 = data1.list.children('dd')
+        ,matched1 = pathURL === data1.a.attr('lay-href');
+        
+        listChildren1.each(function(index2, item2){
+          var othis2 = $(item2)
+          ,data2 = getData(othis2)
+          ,listChildren2 = data2.list.children('dd')
+          ,matched2 = pathURL === data2.a.attr('lay-href');
+          
+          listChildren2.each(function(index3, item3){
+            var othis3 = $(item3)
+            ,data3 = getData(othis3)
+            ,matched3 = pathURL === data3.a.attr('lay-href');
+            
+            if(matched3){
+              var selected = data3.list[0] ? SIDE_NAV_ITEMD : THIS;
+              othis3.addClass(selected).siblings().removeClass(selected); //标记选择器
+              return false;
+            }
+            
+          });
+
+          if(matched2){
+            var selected = data2.list[0] ? SIDE_NAV_ITEMD : THIS;
+            othis2.addClass(selected).siblings().removeClass(selected); //标记选择器
+            return false
+          }
+          
+        });
+        
+        if(matched1){
+          var selected = data1.list[0] ? SIDE_NAV_ITEMD : THIS;
+          othis1.addClass(selected).siblings().removeClass(selected); //标记选择器
+          return false;
+        }
+        
+      });
+    }
+    
+    //重置状态
+    sideMenu.find('.'+ THIS).removeClass(THIS);
+    
+    //移动端点击菜单时自动收缩
+    if(admin.screen() < 2) admin.sideFlexible();
+    
+    //开始捕获
+    matchMenu(sideMenu.children('li'));
+  });
+  
+  //监听侧边导航点击事件
+  element.on('nav(layadmin-system-side-menu)', function(elem){
+    if(elem.siblings('.layui-nav-child')[0] && container.hasClass(SIDE_SHRINK)){
+      admin.sideFlexible('spread');
+      layer.close(elem.data('index'));
+    };
+    admin.tabsPage.type = 'nav';
+  });
+  
+  //监听选项卡的更多操作
+  element.on('nav(layadmin-pagetabs-nav)', function(elem){
+    var dd = elem.parent();
+    dd.removeClass(THIS);
+    dd.parent().removeClass(SHOW);
+  });
+  
+  //同步路由
+  var setThisRouter = function(othis){
+    var layid = othis.attr('lay-id')
+    ,attr = othis.attr('lay-attr')
+    ,index = othis.index();
+    
+    admin.tabsBodyChange(index, {
+      url: attr
+    });
+    //location.hash = layid === setter.entry ? '/' : attr;
+  }
+  ,TABS_HEADER = '#LAY_app_tabsheader>li';
+  
+  //标签页标题点击
+  $body.on('click', TABS_HEADER, function(){
+    var othis = $(this)
+    ,index = othis.index();
+    
+    admin.tabsPage.type = 'tab';
+    admin.tabsPage.index = index;
+
+    setThisRouter(othis);
+  });
+  
+  //监听 tabspage 删除
+  element.on('tabDelete('+ FILTER_TAB_TBAS +')', function(obj){
+    var othis = $(TABS_HEADER+ '.layui-this');
+    
+    obj.index && admin.tabsBody(obj.index).remove();
+    setThisRouter(othis);
+    
+    //移除resize事件
+    admin.delResize();
+  });
+  
+  //页面跳转
+  $body.on('click', '*[lay-href]', function(){
+    var othis = $(this)
+    ,href = othis.attr('lay-href')
+    ,text = othis.attr('lay-text')
+    ,router = layui.router();
+    
+    admin.tabsPage.elem = othis;
+    //admin.prevRouter[router.path[0]] = router.href; //记录上一次各菜单的路由信息
+
+    //执行跳转
+    var topLayui = parent === self ? layui : top.layui;
+    topLayui.index.openTabsPage(href, text || othis.text());
+  });
+  
+  //点击事件
+  $body.on('click', '*[layadmin-event]', function(){
+    var othis = $(this)
+    ,attrEvent = othis.attr('layadmin-event');
+    events[attrEvent] && events[attrEvent].call(this, othis);
+  });
+  
+  //tips
+  $body.on('mouseenter', '*[lay-tips]', function(){
+    var othis = $(this);
+    
+    if(othis.parent().hasClass('layui-nav-item') && !container.hasClass(SIDE_SHRINK)) return;
+    
+    var tips = othis.attr('lay-tips')
+    ,offset = othis.attr('lay-offset') 
+    ,direction = othis.attr('lay-direction')
+    ,index = layer.tips(tips, this, {
+      tips: direction || 1
+      ,time: -1
+      ,success: function(layero, index){
+        if(offset){
+          layero.css('margin-left', offset + 'px');
+        }
+      }
+    });
+    othis.data('index', index);
+  }).on('mouseleave', '*[lay-tips]', function(){
+    layer.close($(this).data('index'));
+  });
+  
+  //窗口resize事件
+  var resizeSystem = layui.data.resizeSystem = function(){
+    //layer.close(events.note.index);
+    layer.closeAll('tips');
+    
+    if(!resizeSystem.lock){
+      setTimeout(function(){
+        admin.sideFlexible(admin.screen() < 2 ? '' : 'spread');
+        delete resizeSystem.lock;
+      }, 100);
+    }
+    
+    resizeSystem.lock = true;
+  }
+  $win.on('resize', layui.data.resizeSystem);
+  
+  //接口输出
+  exports('admin', admin);
+});

+ 267 - 0
src/main/webapp/skin/default/layuiadmin/lib/extend/echartsTheme.js

@@ -0,0 +1,267 @@
+/**
+
+ @Name:echarts 主题
+ @Author:贤心
+ @Site:http://www.layui.com/admin/
+ @License:GPL-2
+    
+ */
+
+
+layui.define(function(exports) {
+  exports('echartsTheme', {
+    // 默认色板
+    color: [
+      '#009688','#1E9FFF','#5FB878','#FFB980','#D87A80',
+      '#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa',
+      '#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050',
+      '#59678c','#c9ab00','#7eb00a','#6f5553','#c14089'
+    ],
+
+    // 图表标题
+    title: {
+      textStyle: {
+        fontWeight: 'normal',
+        color: '#666'      // 主标题文字颜色
+      }
+    },
+    
+    // 值域
+    dataRange: {
+      itemWidth: 15,
+      color: ['#009688','#e0ffff']
+    },
+
+    // 工具箱
+    toolbox: {
+      color : ['#1e90ff', '#1e90ff', '#1e90ff', '#1e90ff'],
+      effectiveColor : '#ff4500'
+    },
+
+    // 提示框
+    tooltip: {
+      backgroundColor: 'rgba(50,50,50,0.5)',   // 提示背景颜色,默认为透明度为0.7的黑色
+      axisPointer : {      // 坐标轴指示器,坐标轴触发有效
+        type : 'line',     // 默认为直线,可选为:'line' | 'shadow'
+        lineStyle : {      // 直线指示器样式设置
+          color: '#009688'
+        },
+        crossStyle: {
+          color: '#008acd'
+        },
+        shadowStyle : {           // 阴影指示器样式设置
+          color: 'rgba(200,200,200,0.2)'
+        }
+      }
+    },
+
+    // 区域缩放控制器
+    dataZoom: {
+      dataBackgroundColor: '#efefff',      // 数据背景颜色
+      fillerColor: 'rgba(182,162,222,0.2)',   // 填充颜色
+      handleColor: '#008acd'  // 手柄颜色
+    },
+
+    // 网格
+    grid: {
+      borderColor: '#eee'
+    },
+
+    // 类目轴 - X轴
+    categoryAxis: {
+      axisLine: {      // 坐标轴线
+        lineStyle: {     // 属性lineStyle控制线条样式
+          color: '#009688'
+        }
+      },
+      axisTick: { //小标记
+        show: false
+      },
+      splitLine: {       // 分隔线
+        lineStyle: {     // 属性lineStyle(详见lineStyle)控制线条样式
+          color: ['#eee']
+        }
+      }
+    },
+
+    // 数值型坐标轴默认参数 - Y轴
+    valueAxis: {
+      axisLine: {      // 坐标轴线
+        lineStyle: {     // 属性lineStyle控制线条样式
+          color: '#009688'
+        }
+      },
+      splitArea : {
+        show : true,
+        areaStyle : {
+          color: ['rgba(250,250,250,0.1)','rgba(200,200,200,0.1)']
+        }
+      },
+      splitLine: {       // 分隔线
+        lineStyle: {     // 属性lineStyle(详见lineStyle)控制线条样式
+          color: ['#eee']
+        }
+      }
+    },
+
+    polar : {
+      axisLine: {      // 坐标轴线
+        lineStyle: {     // 属性lineStyle控制线条样式
+          color: '#ddd'
+        }
+      },
+      splitArea : {
+        show : true,
+        areaStyle : {
+          color: ['rgba(250,250,250,0.2)','rgba(200,200,200,0.2)']
+        }
+      },
+      splitLine : {
+        lineStyle : {
+          color : '#ddd'
+        }
+      }
+    },
+
+    timeline : {
+      lineStyle : {
+        color : '#009688'
+      },
+      controlStyle : {
+        normal : { color : '#009688'},
+        emphasis : { color : '#009688'}
+      },
+      symbol : 'emptyCircle',
+      symbolSize : 3
+    },
+
+    // 柱形图默认参数
+    bar: {
+      itemStyle: {
+        normal: {
+          barBorderRadius: 2
+        },
+        emphasis: {
+          barBorderRadius: 2
+        }
+      }
+    },
+
+    // 折线图默认参数
+    line: {
+      smooth : true,
+      symbol: 'emptyCircle',  // 拐点图形类型
+      symbolSize: 3       // 拐点图形大小
+    },
+    
+    // K线图默认参数
+    k: {
+      itemStyle: {
+        normal: {
+          color: '#d87a80',     // 阳线填充颜色
+          color0: '#2ec7c9',    // 阴线填充颜色
+          lineStyle: {
+            color: '#d87a80',   // 阳线边框颜色
+            color0: '#2ec7c9'   // 阴线边框颜色
+          }
+        }
+      }
+    },
+    
+    // 散点图默认参数
+    scatter: {
+      symbol: 'circle',  // 图形类型
+      symbolSize: 4    // 图形大小,半宽(半径)参数,当图形为方向或菱形则总宽度为symbolSize * 2
+    },
+
+    // 雷达图默认参数
+    radar : {
+      symbol: 'emptyCircle',  // 图形类型
+      symbolSize:3
+      //symbol: null,     // 拐点图形类型
+      //symbolRotate : null,  // 图形旋转控制
+    },
+
+    map: {
+      itemStyle: {
+        normal: {
+          areaStyle: {
+            color: '#ddd'
+          },
+          label: {
+            textStyle: {
+              color: '#d87a80'
+            }
+          }
+        },
+        emphasis: {         // 也是选中样式
+          areaStyle: {
+            color: '#fe994e'
+          }
+        }
+      }
+    },
+    
+    force : {
+      itemStyle: {
+        normal: {
+          linkStyle : {
+            color : '#1e90ff'
+          }
+        }
+      }
+    },
+
+    chord : {
+      itemStyle : {
+        normal : {
+          borderWidth: 1,
+          borderColor: 'rgba(128, 128, 128, 0.5)',
+          chordStyle : {
+            lineStyle : {
+              color : 'rgba(128, 128, 128, 0.5)'
+            }
+          }
+        },
+        emphasis : {
+          borderWidth: 1,
+          borderColor: 'rgba(128, 128, 128, 0.5)',
+          chordStyle : {
+            lineStyle : {
+              color : 'rgba(128, 128, 128, 0.5)'
+            }
+          }
+        }
+      }
+    },
+
+    gauge : {
+      axisLine: {      // 坐标轴线
+        lineStyle: {     // 属性lineStyle控制线条样式
+          color: [[0.2, '#2ec7c9'],[0.8, '#5ab1ef'],[1, '#d87a80']], 
+          width: 10
+        }
+      },
+      axisTick: {      // 坐标轴小标记
+        splitNumber: 10,   // 每份split细分多少段
+        length :15,    // 属性length控制线长
+        lineStyle: {     // 属性lineStyle控制线条样式
+          color: 'auto'
+        }
+      },
+      splitLine: {       // 分隔线
+        length :22,     // 属性length控制线长
+        lineStyle: {     // 属性lineStyle(详见lineStyle)控制线条样式
+          color: 'auto'
+        }
+      },
+      pointer : {
+        width : 5
+      }
+    },
+    
+    textStyle: {
+      fontFamily: '微软雅黑, Arial, Verdana, sans-serif'
+    }
+  });
+});

+ 116 - 0
src/main/webapp/skin/default/layuiadmin/lib/index.js

@@ -0,0 +1,116 @@
+/**
+
+ @Name:layuiAdmin iframe版主入口
+ @Author:贤心
+ @Site:http://www.layui.com/admin/
+ @License:LPPL
+    
+ */
+layui.extend({
+  setter: 'config' //配置模块
+  ,admin: 'lib/admin' //核心模块
+  ,view: 'lib/view' //视图渲染模块
+}).define(['setter', 'admin'], function(exports){
+  var setter = layui.setter
+  ,element = layui.element
+  ,admin = layui.admin
+  ,tabsPage = admin.tabsPage
+  ,view = layui.view
+  //打开标签页
+  ,openTabsPage = function(url, text){
+      if (hasUserAuth(url)){
+          //遍历页签选项卡
+          var matchTo
+              ,tabs = $('#LAY_app_tabsheader>li')
+              ,path = url.replace(/(^http(s*):)|(\?[\s\S]*$)/g, '');
+
+          tabs.each(function(index){
+              var li = $(this)
+                  ,layid = li.attr('lay-id');
+
+              if(layid === url){
+                  matchTo = true;
+                  tabsPage.index = index;
+              }
+          });
+
+          text = text || '新标签页';
+
+          if(setter.pageTabs){
+              //如果未在选项卡中匹配到,则追加选项卡
+              if(!matchTo){
+                  $(APP_BODY).append([
+                      '<div class="layadmin-tabsbody-item layui-show">'
+                      ,'<iframe src="'+ url +'" frameborder="0" class="layadmin-iframe"></iframe>'
+                      ,'</div>'
+                  ].join(''));
+                  tabsPage.index = tabs.length;
+                  element.tabAdd(FILTER_TAB_TBAS, {
+                      title: '<span>'+ text +'</span>'
+                      ,id: url
+                      ,attr: path
+                  });
+              }else{
+                  var iframe = admin.tabsBody(admin.tabsPage.index).find('.layadmin-iframe');
+                  iframe[0].contentWindow.location.href = url;
+              }
+          } else {
+              var iframe = admin.tabsBody(admin.tabsPage.index).find('.layadmin-iframe');
+              iframe[0].contentWindow.location.href = url;
+          }
+
+          //定位当前tabs
+          element.tabChange(FILTER_TAB_TBAS, url);
+          admin.tabsBodyChange(tabsPage.index, {
+              url: url
+              ,text: text
+          });
+      }
+  }
+  
+  ,APP_BODY = '#LAY_app_body', FILTER_TAB_TBAS = 'layadmin-layout-tabs'
+  ,$ = layui.$, $win = $(window);
+  
+  //初始
+  if(admin.screen() < 2) admin.sideFlexible();
+  
+  //将模块根路径设置为 controller 目录
+  layui.config({
+    base: setter.base + 'modules/'
+  });
+  
+  //扩展 lib 目录下的其它模块
+  layui.each(setter.extend, function(index, item){
+    var mods = {};
+    mods[item] = '{/}' + setter.base + 'lib/extend/' + item;
+    layui.extend(mods);
+  });
+  
+  view().autoRender();
+  
+  //加载公共模块
+  layui.use('common');
+
+  //对外输出
+  exports('index', {
+    openTabsPage: openTabsPage
+  });
+
+
+    function hasUserAuth(url) {
+       var flag =true;
+        /*$.ajax("/menu/hasAuth",{
+            async:false,
+            data:{token:JSON.parse(sessionStorage.loginData).token,url:url},
+            success:function (data) {
+                console.log(data);
+                if (data.code==4){
+                    layer.msg('抱歉,您无权限操作!若需开通此权限,请联系超级管理员', { icon: 1 });
+                }else {
+                    flag= true;
+                }
+            }
+        });*/
+        return flag;
+   }
+});

+ 359 - 0
src/main/webapp/skin/default/layuiadmin/lib/view.js

@@ -0,0 +1,359 @@
+/**
+
+ @Name:layuiAdmin 视图模块
+ @Author:贤心
+ @Site:http://www.layui.com/admin/
+ @License:LPPL
+    
+ */
+ 
+layui.define(['laytpl', 'layer'], function(exports){
+  var $ = layui.jquery
+  ,laytpl = layui.laytpl
+  ,layer = layui.layer
+  ,setter = layui.setter
+  ,device = layui.device()
+  ,hint = layui.hint()
+  
+  //对外接口
+  ,view = function(id){
+    return new Class(id);
+  }
+  
+  ,SHOW = 'layui-show', LAY_BODY = 'LAY_app_body'
+  
+  //构造器
+  ,Class = function(id){
+    this.id = id;
+    this.container = $('#'+(id || LAY_BODY));
+  };
+  
+  //加载中
+  view.loading = function(elem){
+    elem.append(
+      this.elemLoad = $('<i class="layui-anim layui-anim-rotate layui-anim-loop layui-icon layui-icon-loading layadmin-loading"></i>')
+    );
+  };
+    
+  //移除加载
+  view.removeLoad = function(){
+    this.elemLoad && this.elemLoad.remove();
+  };
+  
+  //清除 token,并跳转到登入页
+  view.exit = function(callback){
+    //清空本地记录的 token
+    layui.data(setter.tableName, {
+      key: setter.request.tokenName
+      ,remove: true
+    });
+    
+    //跳转到登入页
+    //location.hash = '/user/login'; 
+    callback && callback();
+  };
+  
+  //Ajax请求
+  view.req = function(options){
+    var that = this
+    ,success = options.success
+    ,error = options.error
+    ,request = setter.request
+    ,response = setter.response
+    ,debug = function(){
+      return setter.debug 
+        ? '<br><cite>URL:</cite>' + options.url
+      : '';
+    };
+    
+    options.data = options.data || {};
+    options.headers = options.headers || {};
+    
+    if(request.tokenName){
+      var sendData = typeof options.data === 'string' 
+        ? JSON.parse(options.data) 
+      : options.data;
+
+      //自动给参数传入默认 token
+      options.data[request.tokenName] = request.tokenName in sendData
+        ?  options.data[request.tokenName]
+      : (layui.data(setter.tableName)[request.tokenName] || '');
+      
+      //自动给 Request Headers 传入 token
+      options.headers[request.tokenName] = request.tokenName in options.headers 
+        ?  options.headers[request.tokenName]
+      : (layui.data(setter.tableName)[request.tokenName] || '');
+    }
+    
+    delete options.success;
+    delete options.error;
+
+    return $.ajax($.extend({
+      type: 'get'
+      ,dataType: 'json'
+      ,success: function(res){
+        var statusCode = response.statusCode;
+        
+        //只有 response 的 code 一切正常才执行 done
+        if(res[response.statusName] == statusCode.ok) {
+          typeof options.done === 'function' && options.done(res); 
+        } 
+        
+        //登录状态失效,清除本地 access_token,并强制跳转到登入页
+        else if(res[response.statusName] == statusCode.logout){
+          view.exit();
+        }
+        
+        //其它异常
+        else {
+          var error = [
+            '<cite>Error:</cite> ' + (res[response.msgName] || '返回状态码异常')
+            ,debug()
+          ].join('');
+          view.error(error);
+        }
+        
+        //只要 http 状态码正常,无论 response 的 code 是否正常都执行 success
+        typeof success === 'function' && success(res);
+      }
+      ,error: function(e, code){
+        var error = [
+          '请求异常,请重试<br><cite>错误信息:</cite>'+ code 
+          ,debug()
+        ].join('');
+        view.error(error);
+        
+        typeof error === 'function' && error(res);
+      }
+    }, options));
+  };
+  
+  //弹窗
+  view.popup = function(options){
+    var success = options.success
+    ,skin = options.skin;
+    
+    delete options.success;
+    delete options.skin;
+    
+    return layer.open($.extend({
+      type: 1
+      ,title: '提示'
+      ,content: ''
+      ,id: 'LAY-system-view-popup'
+      ,skin: 'layui-layer-admin' + (skin ? ' ' + skin : '')
+      ,shadeClose: true
+      ,closeBtn: false
+      ,success: function(layero, index){
+        var elemClose = $('<i class="layui-icon" close>&#x1006;</i>');
+        layero.append(elemClose);
+        elemClose.on('click', function(){
+          layer.close(index);
+        });
+        typeof success === 'function' && success.apply(this, arguments);
+      }
+    }, options))
+  };
+  
+  //异常提示
+  view.error = function(content, options){
+    return view.popup($.extend({
+      content: content
+      ,maxWidth: 300
+      //,shade: 0.01
+      ,offset: 't'
+      ,anim: 6
+      ,id: 'LAY_adminError'
+    }, options))
+  };
+  
+  
+  //请求模板文件渲染
+  Class.prototype.render = function(views, params){
+    var that = this, router = layui.router();
+    views = setter.views + views + setter.engine;
+    
+    $('#'+ LAY_BODY).children('.layadmin-loading').remove();
+    view.loading(that.container); //loading
+    
+    //请求模板
+    $.ajax({
+      url: views
+      ,type: 'get'
+      ,dataType: 'html'
+      ,data: {
+        v: layui.cache.version
+      }
+      ,success: function(html){
+        html = '<div>' + html + '</div>';
+        
+        var elemTitle = $(html).find('title')
+        ,title = elemTitle.text() || (html.match(/\<title\>([\s\S]*)\<\/title>/)||[])[1];
+        
+        var res = {
+          title: title
+          ,body: html
+        };
+        
+        elemTitle.remove();
+        that.params = params || {}; //获取参数
+        
+        if(that.then){
+          that.then(res);
+          delete that.then; 
+        }
+
+        that.parse(html);
+        view.removeLoad();
+        
+        if(that.done){
+          that.done(res);
+          delete that.done; 
+        }
+        
+      }
+      ,error: function(e){
+        view.removeLoad();
+        
+        if(that.render.isError){
+          return view.error('请求视图文件异常,状态:'+ e.status);
+        };
+        
+        if(e.status === 404){
+          that.render('template/tips/404');
+        } else {
+          that.render('template/tips/error');
+        }
+        
+        that.render.isError = true;
+      }
+    });
+    return that;
+  };
+  
+  //解析模板
+  Class.prototype.parse = function(html, refresh, callback){
+    var that = this
+    ,isScriptTpl = typeof html === 'object' //是否模板元素
+    ,elem = isScriptTpl ? html : $(html)
+    ,elemTemp = isScriptTpl ? html : elem.find('*[template]')
+    ,fn = function(options){
+      var tpl = laytpl(options.dataElem.html())
+      ,res = $.extend({
+        params: router.params
+      }, options.res);
+      
+      options.dataElem.after(tpl.render(res));
+      typeof callback === 'function' && callback();
+      
+      try {
+        options.done && new Function('d', options.done)(res);
+      } catch(e){
+        console.error(options.dataElem[0], '\n存在错误回调脚本\n\n', e)
+      }
+    }
+    ,router = layui.router();
+    
+    elem.find('title').remove();
+    that.container[refresh ? 'after' : 'html'](elem.children());
+    
+    router.params = that.params || {};
+    
+    //遍历模板区块
+    for(var i = elemTemp.length; i > 0; i--){
+      (function(){
+        var dataElem = elemTemp.eq(i - 1)
+        ,layDone = dataElem.attr('lay-done') || dataElem.attr('lay-then') //获取回调
+        ,url = laytpl(dataElem.attr('lay-url')|| '').render(router) //接口 url
+        ,data = laytpl(dataElem.attr('lay-data')|| '').render(router) //接口参数
+        ,headers = laytpl(dataElem.attr('lay-headers')|| '').render(router); //接口请求的头信息
+        
+        try {
+          data = new Function('return '+ data + ';')();
+        } catch(e) {
+          hint.error('lay-data: ' + e.message);
+          data = {};
+        };
+        
+        try {
+          headers = new Function('return '+ headers + ';')();
+        } catch(e) {
+          hint.error('lay-headers: ' + e.message);
+          headers = headers || {}
+        };
+        
+        if(url){
+          view.req({
+            type: dataElem.attr('lay-type') || 'get'
+            ,url: url
+            ,data: data
+            ,dataType: 'json'
+            ,headers: headers
+            ,success: function(res){
+              fn({
+                dataElem: dataElem
+                ,res: res
+                ,done: layDone
+              });
+            }
+          });
+        } else {
+          fn({
+            dataElem: dataElem
+            ,done: layDone
+          });
+        }
+      }());
+    }
+    
+    return that;
+  };
+  
+  //自动渲染数据模板
+  Class.prototype.autoRender = function(id, callback){
+    var that = this;
+    $(id || 'body').find('*[template]').each(function(index, item){
+      var othis = $(this);
+      that.container = othis;
+      that.parse(othis, 'refresh');
+    });
+  };
+  
+  //直接渲染字符
+  Class.prototype.send = function(views, data){
+    var tpl = laytpl(views || this.container.html()).render(data || {});
+    this.container.html(tpl);
+    return this;
+  };
+  
+  //局部刷新模板
+  Class.prototype.refresh = function(callback){
+    var that = this
+    ,next = that.container.next()
+    ,templateid = next.attr('lay-templateid');
+    
+    if(that.id != templateid) return that;
+    
+    that.parse(that.container, 'refresh', function(){
+      that.container.siblings('[lay-templateid="'+ that.id +'"]:last').remove();
+      typeof callback === 'function' && callback();
+    });
+    
+    return that;
+  };
+  
+  //视图请求成功后的回调
+  Class.prototype.then = function(callback){
+    this.then = callback;
+    return this;
+  };
+  
+  //视图渲染完毕后的回调
+  Class.prototype.done = function(callback){
+    this.done = callback;
+    return this;
+  };
+  
+  //对外接口
+  exports('view', view);
+});