文章目錄
菜單列表(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的權限管理系統 易讀易懂、界面簡潔美觀
微信掃一掃關注公衆號
點擊鏈接加入羣聊
https://jq.qq.com/?_wv=1027&k=5eVEhfN
軟件測試學習交流QQ羣號:511619105