菜單管理實現

在這裏插入圖片描述

菜單列表(menu.html)

<!DOCTYPE html>
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
	<div class="wrapper wrapper-content ">
		<div class="col-sm-12">
			<div class="ibox">
				<div class="ibox-body">
					<div id="exampleToolbar" role="group" class="t-bar">
						<button shiro:hasPermission="sys:menu:add" type="button"
							class="btn btn-primary" title="在根節點下添加菜單" onclick="add('0')">
							<i class="fa fa-plus" aria-hidden="true"></i>添加
						</button>
						<button shiro:hasPermission="sys:menu:batchRemove" type="button"
							class="btn btn-danger" onclick="batchRemove()">
							<i class="fa fa-trash" aria-hidden="true"></i>刪除
						</button>
					</div>
					<table id="exampleTable" data-mobile-responsive="true">
					</table>
				</div>
			</div>
		</div>
		<!--shiro控制bootstraptable行內按鈕可見性 來自StudentBoot的創新方案 -->
		<div>
			<script type="text/javascript">
				var s_add_h = 'hidden';
				var s_edit_h = 'hidden';
				var s_remove_h = 'hidden';
			</script>
		</div>
		<div shiro:hasPermission="sys:menu:add">
			<script type="text/javascript">
				s_add_h = '';
			</script>
		</div>
		<div shiro:hasPermission="sys:menu:edit">
			<script type="text/javascript">
				s_edit_h = '';
			</script>
		</div>
		<div shiro:hasPermission="sys:menu:remove">
			<script type="text/javascript">
				var s_remove_h = '';
			</script>
		</div>
	</div>
	<div th:include="include::footer"></div>
	<script src="/app/sys/menu/menu.js"></script>
</body>

</html>

菜單列表(menu.js)

var prefix = "/sys/menu"
$(document).ready(function () {
    load();
});
var load = function () {
    $('#exampleTable')
        .bootstrapTable(
            {
                idField: 'menuId',
                code: 'menuId',
                method: "GET", // 請求數據的ajax類型
                url: prefix + '/list', // 請求數據的ajax的url
                queryParams: {sort:'order_num'}, // 請求數據的ajax的data屬性
                striped: true, // 是否各行漸變色
                //cache: false,
                toolbar : '#exampleToolbar',
                showColumns: true,                  //是否顯示所有的列(選擇顯示的列)
                showRefresh: true,                  //是否顯示刷新按鈕
                //clickToSelect: true,                //是否啓用點擊選中行
                columns: [
                    {
                        field: 'ck',
                        checkbox: true
                    },
                    {
                        title: '編號',
                        field: 'menuId',
                        visible: false,
                        align: 'center',
                        valign: 'center',
                    },
                    {
                        title: '名稱',
                        valign: 'center',
                        field: 'name',
                    },

                    {
                        title: '圖標',
                        field: 'icon',
                        align: 'center',
                        valign: 'center',
                        width : '5%',
                        formatter: function (value, row, index) {
                            return value == null ? ''
                                : '<i class="' + value
                                + ' fa-lg"></i>';
                        }
                    },
                    {
                        title: '類型',
                        field: 'type',
                        align: 'center',
                        valign: 'center',
                        formatter: function (value, row, index) {
                            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>';
                            }
                        }
                    },
                    {
                        title: '地址',
                        valign: 'center',
                        field: 'url'
                    },
                    {
                        title: '序號',
                        valign: 'center',
                        field: 'orderNum'
                    },
                    {
                        title: '權限標識',
                        valign: 'center',
                        field: 'perms'
                    },
                    {
                        title: '操作',
                        field: 'id',
                        align: 'center',
                        valign: 'center',
                        formatter: function (value, row, index) {
                            var e = '<a class="btn btn-primary btn-sm '
                                + s_edit_h
                                + '" href="#" mce_href="#" title="編輯" οnclick="edit(\''
                                + row.menuId
                                + '\')"><i class="fa fa-edit"></i></a> ';
                            var p = '<a class="btn btn-primary btn-sm '
                                + s_add_h
                                + '" href="#" mce_href="#" title="添加下級" οnclick="add(\''
                                + row.menuId
                                + '\')"><i class="fa fa-plus"></i></a> ';
                            var d = '<a class="btn btn-warning btn-sm '
                                + s_remove_h
                                + '" href="#" title="刪除"  mce_href="#" οnclick="remove(\''
                                + row.menuId
                                + '\')"><i class="fa fa-remove"></i></a> ';
                            return e + d + p;
                        }
                    }],
                treeShowField: 'name',
                parentIdField: 'parentId',
                onPostBody: function() {
                    $('#exampleTable').treegrid({
                        initialState: 'collapsed',//收縮
                        treeColumn: 1,//指明第幾列數據改爲樹形
                        expanderExpandedClass: 'glyphicon glyphicon-triangle-bottom',
                        expanderCollapsedClass: 'glyphicon glyphicon-triangle-right',
                        onChange: function() {
                            $('#exampleTable').bootstrapTable('resetWidth');
                        }
                    })
                }
            });
}

function refresh() {
    $("#exampleTable").bootstrapTable("refresh");
}

function add(pId) {
    layer.open({
        type: 2,
        title: '增加菜單',
        maxmin: true,
        shadeClose: false, // 點擊遮罩關閉層
        area: ['800px', '520px'],
        content: prefix + '/add/' + pId // iframe的url
    });
}

function remove(id) {
    layer.confirm('確定要刪除選中的記錄?', {
        btn: ['確定', '取消']
    }, function () {
        $.ajax({
            url: prefix + "/remove",
            type: "post",
            data: {
                'id': id
            },
            success: function (data) {
                if (data.code == 0) {
                    layer.msg("刪除成功");
                    refresh();
                } else {
                    layer.msg(data.msg);
                }
            }
        });
    })
}

function edit(id) {
    layer.open({
        type: 2,
        title: '菜單修改',
        maxmin: true,
        shadeClose: false, // 點擊遮罩關閉層
        area: ['800px', '520px'],
        content: prefix + '/edit/' + id // iframe的url
    });
}

function batchRemove() {
    // var rows = $('#exampleTable').bootstrapTable('getSelections');

}

菜單添加(add.html)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<meta charset="utf-8">
<head th:include="include :: header"></head>
<body class="gray-bg">
	<div class="wrapper wrapper-content">
		<div class="row">
			<div class="col-sm-12">
				<div class="ibox float-e-margins">
					<div class="ibox-content">
						<form class="form-horizontal m-t" id="signupForm">
							<input id="parentId" name="parentId" type="hidden"
								th:value="${pId}">
							<div class="form-group">
								<label class="col-sm-3 control-label">上級菜單:</label>
								<div class="col-sm-8">
									<input id="" name="" class="form-control" type="text"
										th:value="${pName}" readonly>
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">菜單類型:</label>
								<div class="col-sm-8">
									<label class="radio-inline"> <input type="radio"
										name="type" value="0" /> 目錄
									</label> <label class="radio-inline"> <input type="radio"
										name="type" value="1" /> 菜單
									</label> <label class="radio-inline"> <input type="radio"
										name="type" value="2" /> 按鈕
									</label>
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">菜單名稱:</label>
								<div class="col-sm-8">
									<input id="name" name="name" class="form-control" type="text">
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">鏈接地址:</label>
								<div class="col-sm-8">
									<input id="url" name="url" class="form-control" type="text">
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">權限標識:</label>
								<div class="col-sm-8">
									<input id="perms" name="perms" class="form-control" type="text">
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">排序號:</label>
								<div class="col-sm-8">
									<input id="orderNum" name="orderNum" class="form-control"
										type="text">
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">圖標:</label>
								<div class="col-sm-6">
									<input id="icon" name="icon" class="form-control" type="text"
										placeholder="例如:fa fa-circle-o">
								</div>
								<input id="ico-btn" class="btn btn-warning" type="button" value="選擇圖標">
							</div>


							<div class="form-group">
								<div class="col-sm-8 col-sm-offset-3">
									<button type="submit" class="btn btn-primary">提交</button>
								</div>
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div th:include="include::footer"></div>
	<script src="/app/sys/menu/add.js"></script>
</body>

</html>

菜單添加(add.js)

var prefix = "/sys/menu"
$(function() {
	validateRule();
	//打開圖標列表
    $("#ico-btn").click(function(){
        layer.open({
            type: 2,
			title:'圖標列表',
            content: '/FontIcoList.html',
            area: ['480px', '90%'],
            success: function(layero, index){
                //var body = layer.getChildFrame('.ico-list', index);
                //console.log(layero, index);
            }
        });
    });
});
$.validator.setDefaults({
	submitHandler : function() {
		save();
	}
});
function save() {
	$.ajax({
		cache : true,
		type : "POST",
		url : prefix + "/save",
		data : $('#signupForm').serialize(),
		async : false,
		error : function(request) {
			layer.alert("Connection error");
		},
		success : function(data) {
			if (data.code == 0) {
				parent.layer.msg("保存成功");
				parent.refresh();
				var index = parent.layer.getFrameIndex(window.name); // 獲取窗口索引
				parent.layer.close(index);

			} else {
				layer.alert(data.msg)
			}
		}
	});
}

function validateRule() {
	var icon = "<i class='fa fa-times-circle'></i> ";
	$("#signupForm").validate({
		rules : {
			name : {
				required : true
			},
			type : {
				required : true
			}
		},
		messages : {
			name : {
				required : icon + "請輸入菜單名"
			},
			type : {
				required : icon + "請選擇菜單類型"
			}
		}
	})
}

菜單編輯(edit.html)

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">

<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">


<title></title>
<meta name="keywords" content="">
<meta name="description" content="">
<link rel="shortcut icon" href="favicon.ico">
<link href="/bootstrap/bootstrap.css" rel="stylesheet">
<link href="/font-awesome/font-awesome.css" rel="stylesheet">
<link href="/animate/animate.css" rel="stylesheet">
<link href="/app/style.css" rel="stylesheet">
</head>
<body class="gray-bg">
	<div class="wrapper wrapper-content">
		<div class="row">
			<div class="col-sm-12">
				<div class="ibox float-e-margins">
					<div class="ibox-content">
						<form class="form-horizontal m-t" id="signupForm">
							<input id="parentId" name="parentId" type="hidden"
								th:value="${pId}" /> <input id="menuId" name="menuId"
								type="hidden" th:value="${menu.menuId}" />
							<div class="form-group">
								<label class="col-sm-3 control-label">上級菜單:</label>
								<div class="col-sm-8">
									<input id="" name="" class="form-control" type="text"
										th:value="${pName}" readonly>
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">菜單類型:</label>
								<div class="col-sm-8">
									<label class="radio-inline"> <input type="radio"
										th:field="*{menu.type}" name="type" value="0" /> 目錄
									</label> <label class="radio-inline"> <input type="radio"
										th:field="*{menu.type}" name="type" value="1" /> 菜單
									</label> <label class="radio-inline"> <input type="radio"
										th:field="*{menu.type}" name="type" value="2" /> 按鈕
									</label>
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">菜單名稱:</label>
								<div class="col-sm-8">
									<input id="name" name="name" class="form-control" type="text"
										th:value="${menu.name}" required>
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">鏈接地址:</label>
								<div class="col-sm-8">
									<input id="url" name="url" class="form-control" type="text"
										th:value="${menu.url}">
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">權限標識:</label>
								<div class="col-sm-8">
									<input id="perms" name="perms" class="form-control" type="text"
										th:value="${menu.perms}">
								</div>
							</div>
								<div class="form-group">
								<label class="col-sm-3 control-label">排序號:</label>
								<div class="col-sm-8">
									<input id="orderNum" name="orderNum" class="form-control"
										type="text" th:value="${menu.orderNum}">
								</div>
							</div>
							<div class="form-group">
								<label class="col-sm-3 control-label">圖標:</label>
								<div class="col-sm-5">
									<input id="icon" name="icon" class="form-control" type="text"
										placeholder="例如:fa fa-circle-o" th:value="${menu.icon}">
								</div>
								<input id="ico-btn" class="btn btn-warning" type="button" value="選擇圖標">
							</div>
							<div class="form-group">
								<div class="col-sm-8 col-sm-offset-3">
									<button type="submit" class="btn btn-info">提交</button>
								</div>
							</div>
						</form>
					</div>
				</div>
			</div>
		</div>
	</div>
	<div th:include="include::footer"></div>
	<script src="/app/sys/menu/edit.js"></script>
</body>

</html>

菜單編輯(edit.js)

var prefix = "/sys/menu"
$(function() {
	validateRule();

	//打開圖標列表
    $("#ico-btn").click(function(){
        layer.open({
            type: 2,
			title:'圖標列表',
            content: '/FontIcoList.html',
            area: ['480px', '90%'],
            success: function(layero, index){
                //var body = layer.getChildFrame('.ico-list', index);
                //console.log(layero, index);
            }
        });
    });

});
$.validator.setDefaults({
	submitHandler : function() {
		update();
	}
});
function update() {
	$.ajax({
		cache : true,
		type : "POST",
		url : prefix + "/update",
		data : $('#signupForm').serialize(),// 你的formid
		async : false,
		error : function(request) {
			layer.alert("Connection error");
		},
		success : function(data) {
			if (data.code == 0) {
				parent.layer.msg("保存成功");
				parent.refresh();
				var index = parent.layer.getFrameIndex(window.name); // 獲取窗口索引
				parent.layer.close(index);

			} else {
				layer.alert(data.msg)
			}

		}
	});

}
function validate() {
	var icon = "<i class='fa fa-times-circle'></i> ";
	$("#signupForm").validate({
		rules : {
			name : {
				required : true
			},
			type : {
				required : true
			}
		},
		messages : {
			name : {
				required : icon + "請輸入菜單名"
			},
			type : {
				required : icon + "請選擇菜單類型"
			}
		}
	})
}
function validateRule() {
	var icon = "<i class='fa fa-times-circle'></i> ";
	$("#signupForm").validate({
		rules : {
			name : {
				required : true
			},
			type : {
				required : true
			}
		},
		messages : {
			name : {
				required : icon + "請輸入菜單名"
			},
			type : {
				required : icon + "請選擇菜單類型"
			}
		}
	})
}

菜單管理接口(Java)

package com.yangzc.studentboot.system.controller;

import com.yangzc.studentboot.common.config.Constant;
import com.yangzc.studentboot.common.controller.BaseController;
import com.yangzc.studentboot.common.domain.Tree;
import com.yangzc.studentboot.common.utils.R;
import com.yangzc.studentboot.system.domain.MenuDO;
import com.yangzc.studentboot.system.service.MenuService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * @author yangzc [email protected]
 */
@RequestMapping("/sys/menu")
@Controller
public class MenuController extends BaseController {
	String prefix = "/menu";
	@Autowired
	MenuService menuService;

	@RequiresPermissions("sys:menu:menu")
	@GetMapping()
	String menu(Model model) {
		return prefix+"/menu";
	}

	@RequiresPermissions("sys:menu:menu")
	@RequestMapping("/list")
	@ResponseBody
	List<MenuDO> list(@RequestParam Map<String, Object> params) {
		List<MenuDO> menus = menuService.list(params);
		return menus;
	}

	@RequiresPermissions("sys:menu:add")
	@GetMapping("/add/{pId}")
	String add(Model model, @PathVariable("pId") Long pId) {
		model.addAttribute("pId", pId);
		if (pId == 0) {
			model.addAttribute("pName", "根目錄");
		} else {
			model.addAttribute("pName", menuService.get(pId).getName());
		}
		return prefix + "/add";
	}

	@RequiresPermissions("sys:menu:edit")
	@GetMapping("/edit/{id}")
	String edit(Model model, @PathVariable("id") Long id) {
		MenuDO mdo = menuService.get(id);
		Long pId = mdo.getParentId();
		model.addAttribute("pId", pId);
		if (pId == 0) {
			model.addAttribute("pName", "根目錄");
		} else {
			model.addAttribute("pName", menuService.get(pId).getName());
		}
		model.addAttribute("menu", mdo);
		return prefix+"/edit";
	}

	@RequiresPermissions("sys:menu:add")
	@PostMapping("/save")
	@ResponseBody
	R save(MenuDO menu) {
		if (Constant.DEMO_ACCOUNT.equals(getUsername())) {
			return R.error(1, "演示系統不允許修改,完整體驗請部署程序");
		}
		if (menuService.save(menu) > 0) {
			return R.ok();
		} else {
			return R.error(1, "保存失敗");
		}
	}

	@RequiresPermissions("sys:menu:edit")
	@PostMapping("/update")
	@ResponseBody
	R update(MenuDO menu) {
		if (Constant.DEMO_ACCOUNT.equals(getUsername())) {
			return R.error(1, "演示系統不允許修改,完整體驗請部署程序");
		}
		if (menuService.update(menu) > 0) {
			return R.ok();
		} else {
			return R.error(1, "更新失敗");
		}
	}

	@RequiresPermissions("sys:menu:remove")
	@PostMapping("/remove")
	@ResponseBody
	R remove(Long id) {
		if (Constant.DEMO_ACCOUNT.equals(getUsername())) {
			return R.error(1, "演示系統不允許修改,完整體驗請部署程序");
		}
		if (menuService.remove(id) > 0) {
			return R.ok();
		} else {
			return R.error(1, "刪除失敗");
		}
	}

	@GetMapping("/tree")
	@ResponseBody
	Tree<MenuDO> tree() {
		Tree<MenuDO>  tree = menuService.getTree();
		return tree;
	}

	@GetMapping("/tree/{roleId}")
	@ResponseBody
	Tree<MenuDO> tree(@PathVariable("roleId") Long roleId) {
		Tree<MenuDO> tree = menuService.getTree(roleId);
		return tree;
	}
}

github項目地址

https://github.com/yangzc23/studentboot

參考資料

[01] 彈層組件文檔 - layui.layer
[02] bootstrap-table-examples
[03] 簡單知識點實例之四:BootstrapTable新型樹表格
[04] RuoYi開發文檔
[05] RuoYi: 基於SpringBoot的權限管理系統 易讀易懂、界面簡潔美觀

微信掃一掃關注公衆號
image.png
點擊鏈接加入羣聊

https://jq.qq.com/?_wv=1027&k=5eVEhfN
軟件測試學習交流QQ羣號:511619105

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章