bootstrap table 父子表实现【无限级】菜单管理功能

实现效果

前端代码


<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" %>
<%@include file="/WEB-INF/include/tags.jsp" %>
<!DOCTYPE HTML>
<html>
<head> <!-- 引入jquery插件 -->
<script src="/jquery/jquery-2.1.1.min.js" type="text/javascript"></script>
<!-- 引入bootstrap插件 -->
<script src="/bootstrap/3.3.4/js/bootstrap.min.js" type="text/javascript"></script>
<link href="/bootstrap/3.3.4/css_default/bootstrap.min.css" type="text/css" rel="stylesheet"/>
<!-- 引入bootstrap-table 语言包 -->
<script src="/bootstrap/table/bootstrap-table-zh-CN.min.js"></script>
<!-- 引入bootstrap-table插件 -->
<script src="/bootstrap/table/bootstrap-table.min.js"></script>
<link href="/bootstrap/table/bootstrap-table.min.css" rel="stylesheet"> <style>
.child-table thead {
//隐藏子表的表头
/*display: none !important;*/
}
</style> </head>
<body class="gray-bg">
<div class="wrapper wrapper-content">
<p class="tit">菜单列表</p>
<div class="ibox">
<div class="ibox-content">
<table id="mytab" class="table table-hover"></table>
</div>
</div>
</div> <script type="text/javascript">
//菜单的根id
var mRootId = '0'; $(function () {
//初始化表格数据 传递menu的rootid
createTable(mRootId);
}) //详情递归使用初始化表格方法 pid 菜单的父级id tableObj 当前生成的table所绑定的对象
function createTable(pid, tableObj) { var isSearch = false; if (!tableObj) {
tableObj = "#mytab";
isSearch = true;
} //根据窗口调整表格高度
$(window).resize(function () {
$(tableObj).bootstrapTable('resetView', {
height: tableHeight()
})
}) $(tableObj).bootstrapTable({
url: "${ctx}/",//数据源 后台Controller的数据
dataField: "dataList",//服务端返回数据键值 就是说记录放的键值是rows,分页时使用总记录数的键值为total
// height: tableHeight(),//高度调整
search: isSearch,//是否搜索
pagination: false,//是否分页
contentType: "application/x-www-form-urlencoded",//请求数据内容格式 默认是 application/json 自己根据格式自行服务端处理
dataType: "json",//返回数据类型
method: "post",//请求方式
searchAlign: "left",//查询框对齐方式
queryParamsType: "limit",//查询参数组织方式
queryParams: function getParams(params) {
//params obj 其他参数 除了自身传递的参数外,可以由开发者自身设置传递
params.other = "otherInfo";
params.author = 'upuptop';
params.pid = pid
return params;
},
searchOnEnterKey: false,//回车搜索
showRefresh: isSearch,//刷新按钮
showColumns: false,//列选择按钮
buttonsAlign: "right",//按钮对齐方式
toolbarAlign: "right",//工具栏对齐方式
columns: [
{
title: "菜单名称",//标题
field: "name",//键名 与上方dataList里面存放的键值相对应 dataList['name':"菜单名称"]
sortable: true,//是否可排序
align: "center",//水平
order: "desc"//默认排序方式
},
{
title: "链接",
align: "center",//水平
field: "href",
sortable: true,
},
// {
// title: "权限",
// field: "permission",
// sortable: true,
// align: "center",//水平
// width: "20%",
// },
{
title: "排序值",
field: "sort",
align: "center",//水平
sortable: true,
},
{
title: "是否显示",
field: "isShow",
align: "center",//水平
sortable: true, },
{
title: "操作",
field: "operation",
align: "center",//水平
sortable: true,
}, ],
locale: "zh-CN", //中文支持
detailView: true, //是否显示详情折叠
detailFormatter: function (index, row, element) {
// 详情折叠 内容
// return '<p>这里显示详情</p>'
}, responseHandler: function (res) {
//请求返回数据成功会调用该方法/填充表格数据之前会调用这个方法 $.each(res.menuList, function (index, item) {
if (item.isShow == 1) {
item.isShow = "显示";
} else {
item.isShow = "隐藏";
} var tempHtml = '<a title="修改" "openDialog2(\'修改菜单\',\'${ctx}//form?id=' + item.id + '\',\'800px\',\'550px\',\'' + item.pid + '\')" style="color: #4a93ff">修改</a>';
tempHtml += '&nbsp;|&nbsp;';
tempHtml += '<a title="添加下一级菜单" "openDialog2(\'添加菜单\',\'${ctx}//form?pid=' + item.id + '\',\'800px\',\'550px\',\'' + item.pid + '\')" style="color: #4a93ff">添加下一级菜单</a>';
tempHtml += '&nbsp;|&nbsp;';
tempHtml += '<a title="删除" style="color: red" "delConfirmx(\'' + item.id + '\',\'' + item.pid + '\',\'' + item.name + '\')">删除</a>'; item.operation = tempHtml;
}) return res;
},
onClickRow: function (row, $element) {
//$element是当前tr的jquery对象
//单击row事件
}, onExpandRow: function (index, row, $detail) {
//点击左侧的加号 展开查看详情的时候调用 在这里做了递归调用自身再次构建一张表 这里的child-table-row.id是为了修改或者删除,刷新子表使用
createTable(row.id, $detail.html('<table class="child-table child-table-' + row.id + '" style=""></table>').find('table'));
},
onLoadSuccess: function (data) { },
detailFilter: function (index, row) {
//是否展开详情的过滤方法 可以通过逻辑进行设置是否可以展开查看详情
if (!row.childCount) {
return false;
} return true;
} });
} // 删除确认框
function delConfirmx(id, pid, name) {
top.layer.confirm('是否删除菜单【' + name + '】?', {
btn: ['确定', '取消'] //按钮 .bootstrapTable('refresh')
}, function (index) {
var tableObj;
if (pid != mRootId) {
tableObj = $(".child-table-" + pid);
} else {
tableObj = $("#mytab");
} $.get("${ctx}/deleteData?id=" + id, function (res) {
top.layer.msg("删除成功");
tableObj.bootstrapTable("refresh");
}) }, function (index) {
top.layer.close(index);
}); } //添加修改对话框
function openDialog2(title, url, width, height, pid) { console.log(pid);
console.log($(".child-table-" + pid)); if (navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)) {//如果是移动端,就使用自适应大小弹窗
width = 'auto';
height = 'auto';
} else {//如果是PC端,根据用户设置的width和height显示。 } top.layer.open({
type: 2,
area: [width, height],
title: title,
maxmin: true, //开启最大化最小化按钮
content: url,
// btn: ['确定', '关闭'],
// yes: function (index, layero) {
// },
end: function (index) { if (pid != mRootId) {
$(".child-table-" + pid).bootstrapTable('refresh');
} else {
$("#mytab").bootstrapTable('refresh');
// window.location.reload()
} }
}); } //设置表格的高度
function tableHeight() {
// return $(window).height() - 50; var height = $(window).height() - 120;
//当表格内容的高度小于外面容器的高度,容器的高度设置为内容的高度,相反时容器设置为窗口的高度-160
if ($(".fixed-table-body table").height() < $(".fixed-table-container").height()) {
$(".fixed-table-container").css({"padding-bottom": "0px", height: $(".fixed-table-body table").height() + 20});
// 是当内容少时,使用搜索功能高度保持不变
height = "auto";
} else {
height = $(window).height() - 160;
} return height;
}
</script>
</body>
</html>

上方代码需要修改的地方:

  • <head>标签中所有的引用需要修改。 推荐cdn:https://www.bootcdn.cn/
  • 数据源 需要修改为自身服务端的请求地址

服务端代码:

    @RequestMapping("/")
@ResponseBody
public Map<String, Object> menuData(String pid, String search, String order, Integer offset, Integer limit) { logger.info(" menuData() pid " + pid);
logger.info(" menuData() search " + search);
logger.info(" menuData() order " + order);
logger.info(" menuData() offset " + offset);
logger.info(" menuData() limit " + limit); Map<String, Object> resultMap = new HashMap<>(); List<Menu> menuList = menuService.selectAllMenuByPid(pid, null); resultMap.put("menuList", menuList); return resultMap;
}

参考地址:

官方示例程序:https://examples.bootstrap-table.com/#welcomes/sub-table.html

博客API翻译:https://blog.csdn.net/S_clifftop/article/details/77937356

博客API翻译:https://blog.csdn.net/rickiyeat/article/details/56483577

bootstrap table 父子表实现【无限级】菜单管理功能的更多相关文章

  1. 我的第一个python web开发框架(36)——后台菜单管理功能

    对于后台管理系统来说,要做好权限管理离不开菜单项和页面按钮控件功能的管理.由于程序没法智能的知道有什么菜单和控件,哪些人拥有哪些操作权限,所以首先要做的是菜单管理功能,将需要管理的菜单项和各个功能项添 ...

  2. Swoole 中使用 Table 内存表实现进程间共享数据

    背景 在多进程模式下进程之间的内存是相互隔离的,在一个工作进程中的全局变量和超全局变量,在另一个工作进程中是无法读取和操作的. 如果只有一个工作进程,则不存在进程隔离问题,可以使用全局变量和超全局变量 ...

  3. ABP+AdminLTE+Bootstrap Table权限管理系统第十节--AdminLTE模板菜单处理

    上节我们把布局页,也有的临时的菜单,但是菜单不是应该动态加载的么?,所以我们这节来写菜单.首先我们看一下AdminLTE源码里面的菜单以及结构. <aside class="main- ...

  4. Bootstrap table 实现树形表格,实现联动选中,联动取消

    公司最近有需求要做树形式table.因为是前后端不分离项目,且之前已经引入了bootstrap table插件,现把实现方式分享一下: <!DOCTYPE HTML> <html l ...

  5. Xianfeng轻量级Java中间件平台:菜单管理

    通过菜单管理,可以实现系统菜单的权限控制.用户个性化菜单功能等,当然很多系统支持在线开发,不用专门的开发工具编写代码,通过一些简单的设置就能开发出新的功能,有新功能增加到系统中,菜单管理功能也是必不可 ...

  6. JS组件系列——Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案

    前言:最近项目里面需要用到表格的冻结列功能,所谓“冻结列”,就是某些情况下表格的列比较多,需要固定前面的几列,后面的列滚动.遗憾的是,bootstrap table里自带的fixed column功能 ...

  7. 开源 java CMS - FreeCMS2.2 菜单管理

    项目地址:http://www.freeteam.cn/ 菜单管理 FreeCMS在设计时定位于面向二次开发友好,所以FreeCMS提供了菜单管理功能.二次开发者能够自由添加新的功能菜单到FreeCM ...

  8. django项目后台权限管理功能。

    对后台管理员进行分角色,分类别管理,每个管理员登录账号后只显示自己负责的权限范围. 创建后台管理数据库 models.py文件内 # 管理员表 class Superuser(models.Model ...

  9. ABP+AdminLTE+Bootstrap Table权限管理系统第十一节--bootstrap table之用户管理列表

    这张开始bootstrap table,引入项目有两种方法,一种是直接去官网下载 地址:http://bootstrap-table.wenzhixin.net.cn/ 另一种是Nuget引入. 然后 ...

随机推荐

  1. 更改当前电源策略(使用SetActivePwrScheme API函数),自定义电源按钮动作(设置GLOBAL_POWER_POLICY)

    #include <windows.h> #include <Powrprof.h> #pragma comment(lib, "Powrprof.lib" ...

  2. Codility--- Distinct

    Task description Write a function class Solution { public int solution(int[] A); } that, given a zer ...

  3. Codility--- TapeEquilibrium

    Task description A non-empty zero-indexed array A consisting of N integers is given. Array A represe ...

  4. Android-小小设置永久解决程序因为未捕获异常而异常终止的问题

    (一) 前言各位亲爱的午饭童鞋,是不是经常因为自己的程序中出现未层捕获的异常导致程序异常终止而痛苦不已?嗯,是的.. 但是,大家不要怕,今天给大家分享一个东东可以解决大家这种困扰,吼吼! (二) Un ...

  5. Binary classification - 聊聊评价指标的那些事儿【回忆篇】

    在解决分类问题的时候,可以选择的评价指标简直不要太多.但基本可以分成两2大类,我们今分别来说道说道 基于一个概率阈值判断在该阈值下预测的准确率 衡量模型整体表现(在各个阈值下)的评价指标 在说指标之前 ...

  6. ABP开发框架前后端开发系列---(12)配置模块的管理

    一般来说,一个系统或多或少都会涉及到一些系统参数或者用户信息的配置,而ABP框架也提供了一套配置信息的管理模块,ABP框架的配置信息,必须提前定义好配置的各项内容,然后才能在系统中初始化或者通过接口查 ...

  7. Spark学习之路(八)—— Spark SQL 之 DataFrame和Dataset

    一.Spark SQL简介 Spark SQL是Spark中的一个子模块,主要用于操作结构化数据.它具有以下特点: 能够将SQL查询与Spark程序无缝混合,允许您使用SQL或DataFrame AP ...

  8. 如何为linux服务器配置DNS解析?

    本文建立在已经搭建好DNS服务器时,为linux机器配置DNS服务器的三种方式. IP地址是网络上标识站点的数字地址,为了方便记忆,采用域名来代替IP地址标识站点地址.DNS(域名解析)就是域名到IP ...

  9. 你需要知道的c# Timer 的垃圾回收机制。

    通常我们需要定时执行一段任务的时候,我们就需要定时器,这时我们就可以使用c# System.Threading空间中的 Timer定时器;他是个异步定时器,时间到时每次都是在线程池中分配一个线程去执行 ...

  10. Spring中AOP相关源码解析

    前言 在Spring中AOP是我们使用的非常频繁的一个特性.通过AOP我们可以补足一些面向对象编程中不足或难以实现的部分. AOP 前置理论 首先在学习源码之前我们需要了解关于AOP的相关概念如切点切 ...