Browse Source

初始化

sunlightcs 7 năm trước cách đây
mục cha
commit
561af4aa19

+ 10 - 4
src/main/java/io/renren/common/utils/Query.java

@@ -1,6 +1,7 @@
 package io.renren.common.utils;
 
 import io.renren.common.xss.SQLFilter;
+import org.apache.commons.lang.StringUtils;
 
 import java.util.LinkedHashMap;
 import java.util.Map;
@@ -30,10 +31,15 @@ public class Query extends LinkedHashMap<String, Object> {
         this.put("limit", limit);
 
         //防止SQL注入(因为sidx、order是通过拼接SQL实现排序的,会有SQL注入风险)
-        String sidx = params.get("sidx").toString();
-        String order = params.get("order").toString();
-        this.put("sidx", SQLFilter.sqlInject(sidx));
-        this.put("order", SQLFilter.sqlInject(order));
+        String sidx = (String)params.get("sidx");
+        String order = (String)params.get("order");
+        if(StringUtils.isNotBlank(sidx)){
+            this.put("sidx", SQLFilter.sqlInject(sidx));
+        }
+        if(StringUtils.isNotBlank(order)){
+            this.put("order", SQLFilter.sqlInject(order));
+        }
+
     }
 
 

+ 19 - 19
src/main/java/io/renren/modules/sys/controller/SysMenuController.java

@@ -4,8 +4,6 @@ import io.renren.common.annotation.SysLog;
 import io.renren.common.exception.RRException;
 import io.renren.common.utils.Constant;
 import io.renren.common.utils.Constant.MenuType;
-import io.renren.common.utils.PageUtils;
-import io.renren.common.utils.Query;
 import io.renren.common.utils.R;
 import io.renren.modules.sys.entity.SysMenuEntity;
 import io.renren.modules.sys.service.ShiroService;
@@ -13,11 +11,13 @@ import io.renren.modules.sys.service.SysMenuService;
 import org.apache.commons.lang.StringUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
 
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 /**
@@ -40,15 +40,10 @@ public class SysMenuController extends AbstractController {
 	 */
 	@RequestMapping("/list")
 	@RequiresPermissions("sys:menu:list")
-	public R list(@RequestParam Map<String, Object> params){
-		//查询列表数据
-		Query query = new Query(params);
-		List<SysMenuEntity> menuList = sysMenuService.queryList(query);
-		int total = sysMenuService.queryTotal(query);
-		
-		PageUtils pageUtil = new PageUtils(menuList, total, query.getLimit(), query.getPage());
-		
-		return R.ok().put("page", pageUtil);
+	public List<SysMenuEntity> list(){
+		List<SysMenuEntity> menuList = sysMenuService.queryList(new HashMap<String, Object>());
+
+		return menuList;
 	}
 	
 	/**
@@ -136,13 +131,18 @@ public class SysMenuController extends AbstractController {
 	@SysLog("删除菜单")
 	@RequestMapping("/delete")
 	@RequiresPermissions("sys:menu:delete")
-	public R delete(@RequestBody Long[] menuIds){
-		for(Long menuId : menuIds){
-			if(menuId.longValue() <= 30){
-				return R.error("系统菜单,不能删除");
-			}
+	public R delete(long menuId){
+		if(menuId <= 30){
+			return R.error("系统菜单,不能删除");
+		}
+
+		//判断是否有子菜单或按钮
+		List<SysMenuEntity> menuList = sysMenuService.queryListParentId(menuId);
+		if(menuList.size() > 0){
+			return R.error("请先删除子菜单或按钮");
 		}
-		sysMenuService.deleteBatch(menuIds);
+
+		sysMenuService.deleteBatch(new Long[]{menuId});
 		
 		return R.ok();
 	}

+ 6 - 0
src/main/java/io/renren/modules/sys/service/SysMenuService.java

@@ -21,6 +21,12 @@ public interface SysMenuService {
 	 * @param menuIdList  用户菜单ID
 	 */
 	List<SysMenuEntity> queryListParentId(Long parentId, List<Long> menuIdList);
+
+	/**
+	 * 根据父菜单,查询子菜单
+	 * @param parentId 父菜单ID
+	 */
+	List<SysMenuEntity> queryListParentId(Long parentId);
 	
 	/**
 	 * 获取不包含按钮的菜单列表

+ 6 - 1
src/main/java/io/renren/modules/sys/service/impl/SysMenuServiceImpl.java

@@ -24,7 +24,7 @@ public class SysMenuServiceImpl implements SysMenuService {
 	
 	@Override
 	public List<SysMenuEntity> queryListParentId(Long parentId, List<Long> menuIdList) {
-		List<SysMenuEntity> menuList = sysMenuDao.queryListParentId(parentId);
+		List<SysMenuEntity> menuList = queryListParentId(parentId);
 		if(menuIdList == null){
 			return menuList;
 		}
@@ -39,6 +39,11 @@ public class SysMenuServiceImpl implements SysMenuService {
 	}
 
 	@Override
+	public List<SysMenuEntity> queryListParentId(Long parentId) {
+		return sysMenuDao.queryListParentId(parentId);
+	}
+
+	@Override
 	public List<SysMenuEntity> queryNotButtonList() {
 		return sysMenuDao.queryNotButtonList();
 	}

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 1 - 0
src/main/resources/static/css/bootstrap-table.min.css


+ 175 - 172
src/main/resources/static/js/modules/sys/menu.js

@@ -1,183 +1,186 @@
-$(function () {
-    $("#jqGrid").jqGrid({
-        url: baseURL + 'sys/menu/list',
-        datatype: "json",
-        colModel: [			
-			{ label: '菜单ID', name: 'menuId', index: "menu_id", width: 40, key: true },
-			{ label: '菜单名称', name: 'name', width: 60 },
-			{ label: '上级菜单', name: 'parentName', sortable: false, width: 60 },
-			{ label: '菜单图标', name: 'icon', sortable: false, width: 50, formatter: function(value, options, row){
-				return value == null ? '' : '<i class="'+value+' fa-lg"></i>';
-			}},
-			{ label: '菜单URL', name: 'url', width: 100 },
-			{ label: '授权标识', name: 'perms', width: 100 },
-			{ label: '类型', name: 'type', width: 50, formatter: function(value, options, row){
-				if(value === 0){
-					return '<span class="label label-primary">目录</span>';
-				}
-				if(value === 1){
-					return '<span class="label label-success">菜单</span>';
-				}
-				if(value === 2){
-					return '<span class="label label-warning">按钮</span>';
-				}
-			}},
-			{ label: '排序号', name: 'orderNum', index: "order_num", width: 50}
-        ],
-		viewrecords: true,
-        height: 385,
-        rowNum: 10,
-		rowList : [10,30,50],
-        rownumbers: true, 
-        rownumWidth: 25, 
-        autowidth:true,
-        multiselect: true,
-        pager: "#jqGridPager",
-        jsonReader : {
-            root: "page.list",
-            page: "page.currPage",
-            total: "page.totalPage",
-            records: "page.totalCount"
-        },
-        prmNames : {
-            page:"page", 
-            rows:"limit", 
-            order: "order"
+var setting = {
+    data: {
+        simpleData: {
+            enable: true,
+            idKey: "menuId",
+            pIdKey: "parentId",
+            rootPId: -1
         },
-        gridComplete:function(){
-        	//隐藏grid底部滚动条
-        	$("#jqGrid").closest(".ui-jqgrid-bdiv").css({ "overflow-x" : "hidden" }); 
+        key: {
+            url:"nourl"
         }
-    });
-});
-
-var setting = {
-	data: {
-		simpleData: {
-			enable: true,
-			idKey: "menuId",
-			pIdKey: "parentId",
-			rootPId: -1
-		},
-		key: {
-			url:"nourl"
-		}
-	}
+    }
 };
 var ztree;
 
 var vm = new Vue({
-	el:'#rrapp',
-	data:{
-		showList: true,
-		title: null,
-		menu:{
-			parentName:null,
-			parentId:0,
-			type:1,
-			orderNum:0
-		}
-	},
-	methods: {
-		getMenu: function(menuId){
-			//加载菜单树
-			$.get(baseURL + "sys/menu/select", function(r){
-				ztree = $.fn.zTree.init($("#menuTree"), setting, r.menuList);
-				var node = ztree.getNodeByParam("menuId", vm.menu.parentId);
-				ztree.selectNode(node);
-				
-				vm.menu.parentName = node.name;
-			})
-		},
-		add: function(){
-			vm.showList = false;
-			vm.title = "新增";
-			vm.menu = {parentName:null,parentId:0,type:1,orderNum:0};
-			vm.getMenu();
-		},
-		update: function () {
-			var menuId = getSelectedRow();
-			if(menuId == null){
-				return ;
-			}
-			
-			$.get(baseURL + "sys/menu/info/"+menuId, function(r){
-				vm.showList = false;
+    el:'#rrapp',
+    data:{
+        showList: true,
+        title: null,
+        menu:{
+            parentName:null,
+            parentId:0,
+            type:1,
+            orderNum:0
+        }
+    },
+    methods: {
+        getMenu: function(menuId){
+            //加载菜单树
+            $.get(baseURL + "sys/menu/select", function(r){
+                ztree = $.fn.zTree.init($("#menuTree"), setting, r.menuList);
+                var node = ztree.getNodeByParam("menuId", vm.menu.parentId);
+                ztree.selectNode(node);
+
+                vm.menu.parentName = node.name;
+            })
+        },
+        add: function(){
+            vm.showList = false;
+            vm.title = "新增";
+            vm.menu = {parentName:null,parentId:0,type:1,orderNum:0};
+            vm.getMenu();
+        },
+        update: function () {
+            var menuId = getMenuId();
+            if(menuId == null){
+                return ;
+            }
+
+            $.get(baseURL + "sys/menu/info/"+menuId, function(r){
+                vm.showList = false;
                 vm.title = "修改";
                 vm.menu = r.menu;
-                
+
                 vm.getMenu();
             });
-		},
-		del: function () {
-			var menuIds = getSelectedRows();
-			if(menuIds == null){
-				return ;
-			}
-			
-			confirm('确定要删除选中的记录?', function(){
-				$.ajax({
-					type: "POST",
-				    url: baseURL + "sys/menu/delete",
-                    contentType: "application/json",
-				    data: JSON.stringify(menuIds),
-				    success: function(r){
-				    	if(r.code === 0){
-							alert('操作成功', function(){
-								vm.reload();
-							});
-						}else{
-							alert(r.msg);
-						}
-					}
-				});
-			});
-		},
-		saveOrUpdate: function (event) {
-			var url = vm.menu.menuId == null ? "sys/menu/save" : "sys/menu/update";
-			$.ajax({
-				type: "POST",
-			    url: baseURL + url,
+        },
+        del: function () {
+            var menuId = getMenuId();
+            if(menuId == null){
+                return ;
+            }
+
+            confirm('确定要删除选中的记录?', function(){
+                $.ajax({
+                    type: "POST",
+                    url: baseURL + "sys/menu/delete",
+                    data: "menuId=" + menuId,
+                    success: function(r){
+                        if(r.code === 0){
+                            alert('操作成功', function(){
+                                vm.reload();
+                            });
+                        }else{
+                            alert(r.msg);
+                        }
+                    }
+                });
+            });
+        },
+        saveOrUpdate: function (event) {
+            var url = vm.menu.menuId == null ? "sys/menu/save" : "sys/menu/update";
+            $.ajax({
+                type: "POST",
+                url: baseURL + url,
                 contentType: "application/json",
-			    data: JSON.stringify(vm.menu),
-			    success: function(r){
-			    	if(r.code === 0){
-						alert('操作成功', function(){
-							vm.reload();
-						});
-					}else{
-						alert(r.msg);
-					}
-				}
-			});
-		},
-		menuTree: function(){
-			layer.open({
-				type: 1,
-				offset: '50px',
-				skin: 'layui-layer-molv',
-				title: "选择菜单",
-				area: ['300px', '450px'],
-				shade: 0,
-				shadeClose: false,
-				content: jQuery("#menuLayer"),
-				btn: ['确定', '取消'],
-				btn1: function (index) {
-					var node = ztree.getSelectedNodes();
-					//选择上级菜单
-					vm.menu.parentId = node[0].menuId;
-					vm.menu.parentName = node[0].name;
-					
-					layer.close(index);
-	            }
-			});
-		},
-		reload: function () {
-			vm.showList = true;
-			var page = $("#jqGrid").jqGrid('getGridParam','page');
-			$("#jqGrid").jqGrid('setGridParam',{ 
-                page:page
-            }).trigger("reloadGrid");
-		}
-	}
-});
+                data: JSON.stringify(vm.menu),
+                success: function(r){
+                    if(r.code === 0){
+                        alert('操作成功', function(){
+                            vm.reload();
+                        });
+                    }else{
+                        alert(r.msg);
+                    }
+                }
+            });
+        },
+        menuTree: function(){
+            layer.open({
+                type: 1,
+                offset: '50px',
+                skin: 'layui-layer-molv',
+                title: "选择菜单",
+                area: ['300px', '450px'],
+                shade: 0,
+                shadeClose: false,
+                content: jQuery("#menuLayer"),
+                btn: ['确定', '取消'],
+                btn1: function (index) {
+                    var node = ztree.getSelectedNodes();
+                    //选择上级菜单
+                    vm.menu.parentId = node[0].menuId;
+                    vm.menu.parentName = node[0].name;
+
+                    layer.close(index);
+                }
+            });
+        },
+        reload: function () {
+            vm.showList = true;
+            Menu.table.refresh();
+        }
+    }
+});
+
+
+var Menu = {
+    id: "menuTable",
+    table: null,
+    layerIndex: -1
+};
+
+/**
+ * 初始化表格的列
+ */
+Menu.initColumn = function () {
+    var columns = [
+        {field: 'selectItem', radio: true},
+        {title: '菜单ID', field: 'menuId', visible: false, align: 'center', valign: 'middle', width: '80px'},
+        {title: '菜单名称', field: 'name', align: 'center', valign: 'middle', sortable: true, width: '180px'},
+        {title: '上级菜单', field: 'parentName', align: 'center', valign: 'middle', sortable: true, width: '100px'},
+        {title: '图标', field: 'icon', align: 'center', valign: 'middle', sortable: true, width: '80px', formatter: function(item, index){
+            return item.icon == null ? '' : '<i class="'+item.icon+' fa-lg"></i>';
+        }},
+        {title: '类型', field: 'type', align: 'center', valign: 'middle', sortable: true, width: '100px', formatter: function(item, index){
+            if(item.type === 0){
+                return '<span class="label label-primary">目录</span>';
+            }
+            if(item.type === 1){
+                return '<span class="label label-success">菜单</span>';
+            }
+            if(item.type === 2){
+                return '<span class="label label-warning">按钮</span>';
+            }
+        }},
+        {title: '排序号', field: 'orderNum', align: 'center', valign: 'middle', sortable: true, width: '100px'},
+        {title: '菜单URL', field: 'url', align: 'center', valign: 'middle', sortable: true, width: '160px'},
+        {title: '授权标识', field: 'perms', align: 'center', valign: 'middle', sortable: true}]
+    return columns;
+};
+
+
+function getMenuId () {
+    var selected = $('#menuTable').bootstrapTreeTable('getSelections');
+    if (selected.length == 0) {
+        alert("请选择一条记录");
+        return false;
+    } else {
+        return selected[0].id;
+    }
+}
+
+
+$(function () {
+    var colunms = Menu.initColumn();
+    var table = new TreeTable(Menu.id, baseURL + "sys/menu/list", colunms);
+    table.setExpandColumn(2);
+    table.setIdField("menuId");
+    table.setCodeField("menuId");
+    table.setParentCodeField("parentId");
+    table.setExpandAll(false);
+    table.init();
+    Menu.table = table;
+});

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 8 - 0
src/main/resources/static/libs/bootstrap-table.min.js


+ 4 - 1
src/main/resources/static/plugins/treegrid/jquery.treegrid.css

@@ -10,5 +10,8 @@
 .treegrid-table thead, .treegrid-table tbody tr {display:table;width:100%;table-layout:fixed;}
 .treegrid-thead th{line-height:40px;border: 0 !important;background:#fff !important;border-radius: 4px;border-left:1px solid #e7eaec !important;border-bottom:2px solid #e7eaec !important;text-align: center;}
 .treegrid-thead tr :first-child{border-left:0 !important}
-.treegrid-tbody td{border: 0 !important;border-left:1px solid #e7eaec !important;border-bottom:1px solid #e7eaec !important;}
+.treegrid-tbody td{border: 0 !important;border-left:1px solid #e7eaec !important;border-bottom:1px solid #e7eaec !important;overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;}
 .treegrid-tbody tr :first-child{border-left:0 !important}
+

+ 243 - 238
src/main/resources/static/plugins/treegrid/jquery.treegrid.extension.js

@@ -1,249 +1,254 @@
 (function($) {
-	"use strict";
+    "use strict";
 
-	$.fn.bootstrapTreeTable = function(options, param) {
-		// 如果是调用方法
-		if (typeof options == 'string') {
-			return $.fn.bootstrapTreeTable.methods[options](this, param);
-		}
+    $.fn.bootstrapTreeTable = function(options, param) {
+        // 如果是调用方法
+        if (typeof options == 'string') {
+            return $.fn.bootstrapTreeTable.methods[options](this, param);
+        }
 
-		// 如果是初始化组件
-		options = $.extend({}, $.fn.bootstrapTreeTable.defaults, options || {});
-		// 是否有radio或checkbox
-		var hasSelectItem = false;
-		var target = $(this);
-		// 在外层包装一下div,样式用的bootstrap-table的
-		var _main_div = $("<div class='fixed-table-container'></div>");
-		target.before(_main_div);
-		_main_div.append(target);
-		target.addClass("table table-hover treegrid-table table-bordered");
-		if (options.striped) {
-			target.addClass('table-striped');
-		}
-		// 工具条在外层包装一下div,样式用的bootstrap-table的
-		if(options.toolbar){
-			var _tool_div = $("<div class='fixed-table-toolbar'></div>");
-			var _tool_left_div = $("<div class='bs-bars pull-left'></div>");
-			_tool_left_div.append($(options.toolbar));
-			_tool_div.append(_tool_left_div);
-			_main_div.before(_tool_div);
-		}
-		// 得到根节点
-		target.getRootNodes = function(data) {
-			// 指定Root节点值
-			var _root = options.rootCodeValue?options.rootCodeValue:null
-			var result = [];
-			$.each(data, function(index, item) {
-				// 这里兼容几种常见Root节点写法
-				// 默认的几种判断
-				var _defaultRootFlag = item[options.parentCode] == '0'
-					|| item[options.parentCode] == 0
-					|| item[options.parentCode] == null
-					|| item[options.parentCode] == '';
-				if (!item[options.parentCode] || (_root?(item[options.parentCode] == options.rootCodeValue):_defaultRootFlag)){
-					result.push(item);
-				}
-				// 添加一个默认属性,用来判断当前节点有没有被显示
-				item.isShow = false;
-			});
-			return result;
-		};
-		var j = 0;
-		// 递归获取子节点并且设置子节点
-		target.getChildNodes = function(data, parentNode, parentIndex, tbody) {
-			$.each(data, function(i, item) {
-				if (item[options.parentCode] == parentNode[options.code]) {
-					var tr = $('<tr></tr>');
-					var nowParentIndex = (parentIndex + (j++) + 1);
-					tr.addClass('treegrid-' + nowParentIndex);
-					tr.addClass('treegrid-parent-' + parentIndex);
-					target.renderRow(tr,item);
-					item.isShow = true;
-					tbody.append(tr);
-					target.getChildNodes(data, item, nowParentIndex, tbody)
+        // 如果是初始化组件
+        options = $.extend({}, $.fn.bootstrapTreeTable.defaults, options || {});
+        // 是否有radio或checkbox
+        var hasSelectItem = false;
+        var target = $(this);
+        // 在外层包装一下div,样式用的bootstrap-table的
+        var _main_div = $("<div class='fixed-table-container'></div>");
+        target.before(_main_div);
+        _main_div.append(target);
+        target.addClass("table table-hover treegrid-table table-bordered");
+        if (options.striped) {
+            target.addClass('table-striped');
+        }
+        // 工具条在外层包装一下div,样式用的bootstrap-table的
+        if(options.toolbar){
+            var _tool_div = $("<div class='fixed-table-toolbar'></div>");
+            var _tool_left_div = $("<div class='bs-bars pull-left'></div>");
+            _tool_left_div.append($(options.toolbar));
+            _tool_div.append(_tool_left_div);
+            _main_div.before(_tool_div);
+        }
+        // 得到根节点
+        target.getRootNodes = function(data) {
+            // 指定Root节点值
+            var _root = options.rootCodeValue?options.rootCodeValue:null
+            var result = [];
+            $.each(data, function(index, item) {
+                // 这里兼容几种常见Root节点写法
+                // 默认的几种判断
+                var _defaultRootFlag = item[options.parentCode] == '0'
+                    || item[options.parentCode] == 0
+                    || item[options.parentCode] == null
+                    || item[options.parentCode] == '';
+                if (!item[options.parentCode] || (_root?(item[options.parentCode] == options.rootCodeValue):_defaultRootFlag)){
+                    result.push(item);
+                }
+                // 添加一个默认属性,用来判断当前节点有没有被显示
+                item.isShow = false;
+            });
+            return result;
+        };
+        var j = 0;
+        // 递归获取子节点并且设置子节点
+        target.getChildNodes = function(data, parentNode, parentIndex, tbody) {
+            $.each(data, function(i, item) {
+                if (item[options.parentCode] == parentNode[options.code]) {
+                    var tr = $('<tr></tr>');
+                    var nowParentIndex = (parentIndex + (j++) + 1);
+                    tr.addClass('treegrid-' + nowParentIndex);
+                    tr.addClass('treegrid-parent-' + parentIndex);
+                    target.renderRow(tr,item);
+                    item.isShow = true;
+                    tbody.append(tr);
+                    target.getChildNodes(data, item, nowParentIndex, tbody)
 
-				}
-			});
-		};
-		// 绘制行
-		target.renderRow = function(tr,item){
-			$.each(options.columns, function(index, column) {
-				// 判断有没有选择列
-				if(index==0&&column.field=='selectItem'){
-					hasSelectItem = true;
-					var td = $('<td style="text-align:center;width:36px"></td>');
-					if(column.radio){
-						var _ipt = $('<input name="select_item" type="radio" value="'+item[options.id]+'"></input>');
-						td.append(_ipt);
-					} 
-					if(column.checkbox){
-						var _ipt = $('<input name="select_item" type="checkbox" value="'+item[options.id]+'"></input>');
-						td.append(_ipt);
-					} 
-					tr.append(td);
-				}else{
-					var td = $('<td style="'+((column.width)?('width:'+column.width):'')+'"></td>');
-					td.text(item[column.field]);
-					tr.append(td);
-				}
-			});
-		}
-		// 加载数据
-		target.load = function(parms){
-			// 加载数据前先清空
-			target.html("");
-			// 构造表头
-			var thr = $('<tr></tr>');
-			$.each(options.columns, function(i, item) {
-				var th = null;
-				// 判断有没有选择列
-				if(i==0&&item.field=='selectItem'){
-					hasSelectItem = true;
-					th = $('<th style="width:36px"></th>');
-				}else{
-					th = $('<th style="padding:10px;'+((item.width)?('width:'+item.width):'')+'"></th>');
-				}
-				th.text(item.title);
-				thr.append(th);
-			});
-			var thead = $('<thead class="treegrid-thead"></thead>');
-			thead.append(thr);
-			target.append(thead);
-			// 构造表体
-			var tbody = $('<tbody class="treegrid-tbody"></tbody>');
-			target.append(tbody);
-			// 添加加载loading
-			var _loading = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">正在努力地加载数据中,请稍候……</div></td></tr>'
-			tbody.html(_loading);
-			// 默认高度
-			if(options.height){
-				tbody.css("height",options.height);
-			}
-			$.ajax({
-				type : options.type,
-				url : options.url,
-				data : parms?parms:options.ajaxParams,
-				dataType : "JSON",
-				success : function(data, textStatus, jqXHR) {
-					// 加载完数据先清空
-					tbody.html("");
-					if(!data||data.length<=0){
-						var _empty = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">没有找到匹配的记录</div></td></tr>'
-						tbody.html(_empty);
-						return;
-					}
-					var rootNode = target.getRootNodes(data);
-					$.each(rootNode, function(i, item) {
-						var tr = $('<tr></tr>');
-						tr.addClass('treegrid-' + (j + "_" + i));
-						target.renderRow(tr,item);
-						item.isShow = true;
-						tbody.append(tr);
-						target.getChildNodes(data, item, (j + "_" + i), tbody);
-					});
-					// 下边的操作主要是为了查询时让一些没有根节点的节点显示
-					$.each(data, function(i, item) {
-						if(!item.isShow){
-							var tr = $('<tr></tr>');
-							tr.addClass('treegrid-' + (j + "_" + i));
-							target.renderRow(tr,item);
-							tbody.append(tr);
-						}
-					});
-					target.append(tbody);
-					// 初始化treegrid
-					target.treegrid({
-						treeColumn: options.expandColumn?options.expandColumn:(hasSelectItem?1:0),//如果有radio或checkbox默认第二列层级显示,当前是在用户未设置的提前下
-						expanderExpandedClass : options.expanderExpandedClass,
-						expanderCollapsedClass : options.expanderCollapsedClass
-					});
-					if (!options.expandAll) {
-						target.treegrid('collapseAll');
-					}
-					//动态设置表头宽度
-					thead.css("width", tbody.children(":first").css("width"));
-					// 行点击选中事件
-					target.find("tbody").find("tr").click(function(){
-						if(hasSelectItem){
-							var _ipt = $(this).find("input[name='select_item']");
-							if(_ipt.attr("type")=="radio"){
-								_ipt.prop('checked',true);
-								target.find("tbody").find("tr").removeClass("treegrid-selected");
-								$(this).addClass("treegrid-selected");
-							}else{
-								if(_ipt.prop('checked')){
-									_ipt.prop('checked',false);
-									$(this).removeClass("treegrid-selected");
-								}else{
-									_ipt.prop('checked',true);
-									$(this).addClass("treegrid-selected");
-								}
-							}
-						}
-					});
-				},
-			    error:function(xhr,textStatus){
-					var _errorMsg = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">'+xhr.responseText+'</div></td></tr>'
-					tbody.html(_errorMsg);
-					debugger;
-			    },
-			});
-		}
-		if (options.url) {
-			target.load();
-		} else {
-			// 也可以通过defaults里面的data属性通过传递一个数据集合进来对组件进行初始化....有兴趣可以自己实现,思路和上述类似
-		}
-		
-		return target;
-	};
+                }
+            });
+        };
+        // 绘制行
+        target.renderRow = function(tr,item){
+            $.each(options.columns, function(index, column) {
+                // 判断有没有选择列
+                if(index==0&&column.field=='selectItem'){
+                    hasSelectItem = true;
+                    var td = $('<td style="text-align:center;width:36px"></td>');
+                    if(column.radio){
+                        var _ipt = $('<input name="select_item" type="radio" value="'+item[options.id]+'"></input>');
+                        td.append(_ipt);
+                    }
+                    if(column.checkbox){
+                        var _ipt = $('<input name="select_item" type="checkbox" value="'+item[options.id]+'"></input>');
+                        td.append(_ipt);
+                    }
+                    tr.append(td);
+                }else{
+                    var td = $('<td style="'+((column.width)?('width:'+column.width):'')+'"></td>');
+                    // 增加formatter渲染
+                    if (column.formatter) {
+                        td.html(column.formatter.call(this, item, index));
+                    } else {
+                        td.text(item[column.field]);
+                    }
+                    tr.append(td);
+                }
+            });
+        }
+        // 加载数据
+        target.load = function(parms){
+            // 加载数据前先清空
+            target.html("");
+            // 构造表头
+            var thr = $('<tr></tr>');
+            $.each(options.columns, function(i, item) {
+                var th = null;
+                // 判断有没有选择列
+                if(i==0&&item.field=='selectItem'){
+                    hasSelectItem = true;
+                    th = $('<th style="width:36px"></th>');
+                }else{
+                    th = $('<th style="padding:10px;'+((item.width)?('width:'+item.width):'')+'"></th>');
+                }
+                th.text(item.title);
+                thr.append(th);
+            });
+            var thead = $('<thead class="treegrid-thead"></thead>');
+            thead.append(thr);
+            target.append(thead);
+            // 构造表体
+            var tbody = $('<tbody class="treegrid-tbody"></tbody>');
+            target.append(tbody);
+            // 添加加载loading
+            var _loading = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">正在努力地加载数据中,请稍候……</div></td></tr>'
+            tbody.html(_loading);
+            // 默认高度
+            if(options.height){
+                tbody.css("height",options.height);
+            }
+            $.ajax({
+                type : options.type,
+                url : options.url,
+                data : parms?parms:options.ajaxParams,
+                dataType : "JSON",
+                success : function(data, textStatus, jqXHR) {
+                    // 加载完数据先清空
+                    tbody.html("");
+                    if(!data||data.length<=0){
+                        var _empty = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">没有记录</div></td></tr>'
+                        tbody.html(_empty);
+                        return;
+                    }
+                    var rootNode = target.getRootNodes(data);
+                    $.each(rootNode, function(i, item) {
+                        var tr = $('<tr></tr>');
+                        tr.addClass('treegrid-' + (j + "_" + i));
+                        target.renderRow(tr,item);
+                        item.isShow = true;
+                        tbody.append(tr);
+                        target.getChildNodes(data, item, (j + "_" + i), tbody);
+                    });
+                    // 下边的操作主要是为了查询时让一些没有根节点的节点显示
+                    $.each(data, function(i, item) {
+                        if(!item.isShow){
+                            var tr = $('<tr></tr>');
+                            tr.addClass('treegrid-' + (j + "_" + i));
+                            target.renderRow(tr,item);
+                            tbody.append(tr);
+                        }
+                    });
+                    target.append(tbody);
+                    // 初始化treegrid
+                    target.treegrid({
+                        treeColumn: options.expandColumn?options.expandColumn:(hasSelectItem?1:0),//如果有radio或checkbox默认第二列层级显示,当前是在用户未设置的提前下
+                        expanderExpandedClass : options.expanderExpandedClass,
+                        expanderCollapsedClass : options.expanderCollapsedClass
+                    });
+                    if (!options.expandAll) {
+                        target.treegrid('collapseAll');
+                    }
+                    //动态设置表头宽度
+                    //thead.css("width", tbody.children(":first").css("width"));
+                    // 行点击选中事件
+                    target.find("tbody").find("tr").click(function(){
+                        if(hasSelectItem){
+                            var _ipt = $(this).find("input[name='select_item']");
+                            if(_ipt.attr("type")=="radio"){
+                                _ipt.prop('checked',true);
+                                target.find("tbody").find("tr").removeClass("treegrid-selected");
+                                $(this).addClass("treegrid-selected");
+                            }else{
+                                if(_ipt.prop('checked')){
+                                    _ipt.prop('checked',false);
+                                    $(this).removeClass("treegrid-selected");
+                                }else{
+                                    _ipt.prop('checked',true);
+                                    $(this).addClass("treegrid-selected");
+                                }
+                            }
+                        }
+                    });
+                },
+                error:function(xhr,textStatus){
+                    var _errorMsg = '<tr><td colspan="'+options.columns.length+'"><div style="display: block;text-align: center;">'+xhr.responseText+'</div></td></tr>'
+                    tbody.html(_errorMsg);
+                    debugger;
+                },
+            });
+        }
+        if (options.url) {
+            target.load();
+        } else {
+            // 也可以通过defaults里面的data属性通过传递一个数据集合进来对组件进行初始化....有兴趣可以自己实现,思路和上述类似
+        }
 
-	// 组件方法封装........
-	$.fn.bootstrapTreeTable.methods = {
-		// 返回选中记录的id(返回的id由配置中的id属性指定)
-		// 为了兼容bootstrap-table的写法,统一返回数组,这里只返回了指定的id
-		getSelections : function(target, data) {
-			// 所有被选中的记录input
-			var _ipt = target.find("tbody").find("tr").find("input[name='select_item']:checked");
-			var chk_value =[]; 
-			// 如果是radio
-			if(_ipt.attr("type")=="radio"){
-				chk_value.push({id:_ipt.val()}); 
-			}else{
-				_ipt.each(function(_i,_item){ 
-					chk_value.push({id:$(_item).val()}); 
-				}); 
-			}
-			return chk_value;
-		},
-		// 刷新记录
-		refresh : function(target, parms) {
-			if(parms){
-				target.load(parms);
-			}else{
+        return target;
+    };
+
+    // 组件方法封装........
+    $.fn.bootstrapTreeTable.methods = {
+        // 返回选中记录的id(返回的id由配置中的id属性指定)
+        // 为了兼容bootstrap-table的写法,统一返回数组,这里只返回了指定的id
+        getSelections : function(target, data) {
+            // 所有被选中的记录input
+            var _ipt = target.find("tbody").find("tr").find("input[name='select_item']:checked");
+            var chk_value =[];
+            // 如果是radio
+            if(_ipt.attr("type")=="radio"){
+                chk_value.push({id:_ipt.val()});
+            }else{
+                _ipt.each(function(_i,_item){
+                    chk_value.push({id:$(_item).val()});
+                });
+            }
+            return chk_value;
+        },
+        // 刷新记录
+        refresh : function(target, parms) {
+            if(parms){
+                target.load(parms);
+            }else{
                 target.load();
-			}
-		},
-	// 组件的其他方法也可以进行类似封装........
-	};
+            }
+        },
+        // 组件的其他方法也可以进行类似封装........
+    };
 
-	$.fn.bootstrapTreeTable.defaults = {
-		id : 'id',// 选取记录返回的值
-		code : 'code',// 用于设置父子关系
-		parentCode : 'parentId',// 用于设置父子关系
-		rootCodeValue: null,//设置根节点code值----可指定根节点,默认为null,"",0,"0"
-		data : [], // 构造table的数据集合
-		type : "GET", // 请求数据的ajax类型
-		url : null, // 请求数据的ajax的url
-		ajaxParams : {}, // 请求数据的ajax的data属性
-		expandColumn : null,// 在哪一列上面显示展开按钮
-		expandAll : true, // 是否全部展开
-		striped : false, // 是否各行渐变色
-		columns : [],
+    $.fn.bootstrapTreeTable.defaults = {
+        id : 'menuId',// 选取记录返回的值
+        code : 'menuId',// 用于设置父子关系
+        parentCode : 'parentId',// 用于设置父子关系
+        rootCodeValue: null,//设置根节点code值----可指定根节点,默认为null,"",0,"0"
+        data : [], // 构造table的数据集合
+        type : "GET", // 请求数据的ajax类型
+        url : null, // 请求数据的ajax的url
+        ajaxParams : {}, // 请求数据的ajax的data属性
+        expandColumn : null,// 在哪一列上面显示展开按钮
+        expandAll : true, // 是否全部展开
+        striped : false, // 是否各行渐变色
+        columns : [],
         toolbar: null,//顶部工具条
         height: 0,
-		expanderExpandedClass : 'glyphicon glyphicon-chevron-down',// 展开的按钮的图标
-		expanderCollapsedClass : 'glyphicon glyphicon-chevron-right'// 缩起的按钮的图标
+        expanderExpandedClass : 'glyphicon glyphicon-chevron-down',// 展开的按钮的图标
+        expanderCollapsedClass : 'glyphicon glyphicon-chevron-right'// 缩起的按钮的图标
 
-	};
+    };
 })(jQuery);

+ 136 - 0
src/main/resources/static/plugins/treegrid/tree.table.js

@@ -0,0 +1,136 @@
+/**
+ * 初始化 Tree Table 的封装
+ *
+ * @author cyf
+ */
+(function () {
+    var TreeTable = function (tableId, url, columns) {
+        this.btInstance = null;					//jquery和bootstrapTreeTable绑定的对象
+        this.bstableId = tableId;
+        this.url = url;
+        this.method = "GET";
+        this.columns = columns;
+        this.data = {};// ajax的参数
+        this.expandColumn = null;// 展开显示的列 
+        this.id = 'menuId';// 选取记录返回的值
+        this.code = 'menuId';// 用于设置父子关系
+        this.parentCode = 'parentId';// 用于设置父子关系
+        this.expandAll = false;// 是否默认全部展开
+        this.toolbarId = tableId + "Toolbar";
+        this.height = 430;
+    };
+
+    TreeTable.prototype = {
+        /**
+         * 初始化bootstrap table
+         */
+        init: function () {
+            var tableId = this.bstableId;
+            this.btInstance =
+                $('#'+tableId).bootstrapTreeTable({
+                    id: this.id,// 选取记录返回的值
+                    code: this.code,// 用于设置父子关系
+                    parentCode: this.parentCode,// 用于设置父子关系
+                    rootCodeValue: this.rootCodeValue,//设置根节点code值----可指定根节点,默认为null,"",0,"0"
+                    type: this.method, //请求数据的ajax类型
+                    url: this.url,   //请求数据的ajax的url
+                    ajaxParams: this.data, //请求数据的ajax的data属性
+                    expandColumn: this.expandColumn,//在哪一列上面显示展开按钮,从0开始
+                    striped: true,   //是否各行渐变色
+                    expandAll: this.expandAll,  //是否全部展开
+                    columns: this.columns,		//列数组
+                    toolbar: "#" + this.toolbarId,//顶部工具条
+                    height: this.height,
+                });
+            return this;
+        },
+
+        /**
+         * 设置在哪一列上面显示展开按钮,从0开始
+         */
+        setExpandColumn: function (expandColumn) {
+            this.expandColumn = expandColumn;
+        },
+        /**
+         * 设置记录返回的id值
+         */
+        setIdField: function (id) {
+            this.id = id;
+        },
+        /**
+         * 设置记录分级的字段
+         */
+        setCodeField: function (code) {
+            this.code = code;
+        },
+        /**
+         * 设置记录分级的父级字段
+         */
+        setParentCodeField: function (parentCode) {
+            this.parentCode = parentCode;
+        },
+        /**
+         * 设置根节点code值----可指定根节点,默认为null,"",0,"0"
+         */
+        setRootCodeValue: function (rootCodeValue) {
+            this.rootCodeValue = rootCodeValue;
+        },
+        /**
+         * 设置是否默认全部展开
+         */
+        setExpandAll: function (expandAll) {
+        	this.expandAll = expandAll;
+        },
+        /**
+         * 设置表格高度
+         */
+        setHeight: function (height) {
+        	this.height = height;
+        },
+        /**
+         * 设置ajax post请求时候附带的参数
+         */
+        set: function (key, value) {
+            if (typeof key == "object") {
+                for (var i in key) {
+                    if (typeof i == "function")
+                        continue;
+                    this.data[i] = key[i];
+                }
+            } else {
+                this.data[key] = (typeof value == "undefined") ? $("#" + key).val() : value;
+            }
+            return this;
+        },
+
+        /**
+         * 设置ajax get请求时候附带的参数
+         */
+        setData: function (data) {
+            this.data = data;
+            return this;
+        },
+
+        /**
+         * 清空ajax post请求参数
+         */
+        clear: function () {
+            this.data = {};
+            return this;
+        },
+
+        /**
+         * 刷新表格
+         */
+        refresh: function (parms) {
+            if (typeof parms != "undefined") {
+                this.btInstance.bootstrapTreeTable('refresh', parms.query);// 为了兼容bootstrap-table的写法
+            } else {
+                this.btInstance.bootstrapTreeTable('refresh');
+            }
+        }
+    };
+
+    window.TreeTable = TreeTable;
+
+}());

+ 63 - 49
src/main/resources/views/modules/sys/menu.html

@@ -1,23 +1,31 @@
 <!DOCTYPE html>
 <html>
 <head>
-<title>菜单管理</title>
-<meta charset="UTF-8">
-<meta http-equiv="X-UA-Compatible" content="IE=edge">
-<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
-<link rel="stylesheet" href="../../css/bootstrap.min.css">
-<link rel="stylesheet" href="../../css/font-awesome.min.css">
-<link rel="stylesheet" href="../../plugins/jqgrid/ui.jqgrid-bootstrap.css">
-<link rel="stylesheet" href="../../plugins/ztree/css/metroStyle/metroStyle.css">
-<link rel="stylesheet" href="../../css/main.css">
-<script src="../../libs/jquery.min.js"></script>
-<script src="../../plugins/layer/layer.js"></script>
-<script src="../../libs/bootstrap.min.js"></script>
-<script src="../../libs/vue.min.js"></script>
-<script src="../../plugins/jqgrid/grid.locale-cn.js"></script>
-<script src="../../plugins/jqgrid/jquery.jqGrid.min.js"></script>
-<script src="../../plugins/ztree/jquery.ztree.all.min.js"></script>
-<script src="../../js/common.js"></script>
+	<title>菜单管理</title>
+	<meta charset="UTF-8">
+	<meta http-equiv="X-UA-Compatible" content="IE=edge">
+	<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
+	<link rel="stylesheet" href="../../css/bootstrap.min.css">
+	<link rel="stylesheet" href="../../css/font-awesome.min.css">
+	<link rel="stylesheet" href="../../plugins/jqgrid/ui.jqgrid-bootstrap.css">
+	<link rel="stylesheet" href="../../plugins/ztree/css/metroStyle/metroStyle.css">
+	<link rel="stylesheet" href="../../css/bootstrap-table.min.css">
+	<link rel="stylesheet" href="../../css/main.css">
+	<link rel="stylesheet" href="../../plugins/treegrid/jquery.treegrid.css">
+
+	<script src="../../libs/jquery.min.js"></script>
+	<script src="../../plugins/layer/layer.js"></script>
+	<script src="../../libs/bootstrap.min.js"></script>
+	<script src="../../libs/vue.min.js"></script>
+	<script src="../../libs/bootstrap-table.min.js"></script>
+	<script src="../../plugins/treegrid/jquery.treegrid.min.js"></script>
+	<script src="../../plugins/treegrid/jquery.treegrid.bootstrap3.js"></script>
+	<script src="../../plugins/treegrid/jquery.treegrid.extension.js"></script>
+	<script src="../../plugins/treegrid/tree.table.js"></script>
+	<script src="../../plugins/jqgrid/grid.locale-cn.js"></script>
+	<script src="../../plugins/jqgrid/jquery.jqGrid.min.js"></script>
+	<script src="../../plugins/ztree/jquery.ztree.all.min.js"></script>
+	<script src="../../js/common.js"></script>
 </head>
 <body>
 <div id="rrapp" v-cloak>
@@ -27,64 +35,69 @@
 			<a v-if="hasPermission('sys:menu:update')" class="btn btn-primary" @click="update"><i class="fa fa-pencil-square-o"></i>&nbsp;修改</a>
 			<a v-if="hasPermission('sys:menu:delete')" class="btn btn-primary" @click="del"><i class="fa fa-trash-o"></i>&nbsp;删除</a>
 		</div>
-	    <table id="jqGrid"></table>
-	    <div id="jqGridPager"></div>
+		<table id="menuTable" data-mobile-responsive="true" data-click-to-select="true">
+			<thead>
+			<tr>
+				<th data-field="selectItem" data-checkbox="true"></th>
+			</tr>
+			</thead>
+		</table>
 	</div>
-	
+
 	<div v-show="!showList" class="panel panel-default">
 		<div class="panel-heading">{{title}}</div>
 		<form class="form-horizontal">
 			<div class="form-group">
-				<div class="col-sm-2 control-label">类型</div> 
+				<div class="col-sm-2 control-label">类型</div>
 				<label class="radio-inline">
-				  <input type="radio" name="type" value="0" v-model="menu.type"/> 目录
+					<input type="radio" name="type" value="0" v-model="menu.type"/> 目录
 				</label>
 				<label class="radio-inline">
-				  <input type="radio" name="type" value="1" v-model="menu.type"/> 菜单
+					<input type="radio" name="type" value="1" v-model="menu.type"/> 菜单
 				</label>
 				<label class="radio-inline">
-				  <input type="radio" name="type" value="2" v-model="menu.type"/> 按钮
+					<input type="radio" name="type" value="2" v-model="menu.type"/> 按钮
 				</label>
 			</div>
 			<div class="form-group">
-			   	<div class="col-sm-2 control-label">菜单名称</div>
-			   	<div class="col-sm-10">
-			      <input type="text" class="form-control" v-model="menu.name" placeholder="菜单名称或按钮名称"/>
-			    </div>
+				<div class="col-sm-2 control-label">菜单名称</div>
+				<div class="col-sm-10">
+					<input type="text" class="form-control" v-model="menu.name" placeholder="菜单名称或按钮名称"/>
+				</div>
 			</div>
 			<div class="form-group">
 				<div class="col-sm-2 control-label">上级菜单</div>
-			   	<div class="col-sm-10">
-			       <input type="text" class="form-control" style="cursor:pointer;" v-model="menu.parentName" @click="menuTree" readonly="readonly" placeholder="一级菜单"/>
-			    </div>
+				<div class="col-sm-10">
+					<input type="text" class="form-control" style="cursor:pointer;" v-model="menu.parentName" @click="menuTree" readonly="readonly" placeholder="一级菜单"/>
+				</div>
 			</div>
 			<div v-if="menu.type == 1" class="form-group">
-			   	<div class="col-sm-2 control-label">菜单URL</div>
-			   	<div class="col-sm-10">
-			      <input type="text" class="form-control" v-model="menu.url" placeholder="菜单URL"/>
-			    </div>
+				<div class="col-sm-2 control-label">菜单URL</div>
+				<div class="col-sm-10">
+					<input type="text" class="form-control" v-model="menu.url" placeholder="菜单URL"/>
+				</div>
 			</div>
 			<div v-if="menu.type == 1 || menu.type == 2" class="form-group">
-			   	<div class="col-sm-2 control-label">授权标识</div>
-			   	<div class="col-sm-10">
-			      <input type="text" class="form-control" v-model="menu.perms" placeholder="多个用逗号分隔,如:user:list,user:create"/>
-			    </div>
+				<div class="col-sm-2 control-label">授权标识</div>
+				<div class="col-sm-10">
+					<input type="text" class="form-control" v-model="menu.perms" placeholder="多个用逗号分隔,如:user:list,user:create"/>
+				</div>
 			</div>
 			<div v-if="menu.type != 2" class="form-group">
-			   	<div class="col-sm-2 control-label">排序号</div>
-			   	<div class="col-sm-10">
-			      <input type="number" class="form-control" v-model="menu.orderNum" placeholder="排序号"/>
-			    </div>
+				<div class="col-sm-2 control-label">排序号</div>
+				<div class="col-sm-10">
+					<input type="number" class="form-control" v-model="menu.orderNum" placeholder="排序号"/>
+				</div>
 			</div>
 			<div v-if="menu.type != 2" class="form-group">
-			   	<div class="col-sm-2 control-label">图标</div>
-			   	<div class="col-sm-10">
-			      <input type="text" class="form-control" v-model="menu.icon" placeholder="菜单图标"/>
-			      <code style="margin-top:4px;display: block;">获取图标:http://fontawesome.io/icons/</code>
-			    </div>
+				<div class="col-sm-2 control-label">图标</div>
+				<div class="col-sm-10">
+					<input type="text" class="form-control" v-model="menu.icon" placeholder="菜单图标"/>
+					<code style="margin-top:4px;display: block;">获取图标:http://fontawesome.io/icons/</code>
+				</div>
 			</div>
 			<div class="form-group">
-				<div class="col-sm-2 control-label"></div> 
+				<div class="col-sm-2 control-label"></div>
 				<input type="button" class="btn btn-primary" @click="saveOrUpdate" value="确定"/>
 				&nbsp;&nbsp;<input type="button" class="btn btn-warning" @click="reload" value="返回"/>
 			</div>
@@ -97,6 +110,7 @@
 	<ul id="menuTree" class="ztree"></ul>
 </div>
 
+
 <script src="../../js/modules/sys/menu.js"></script>
 </body>
 </html>