Layui 表格和树表格技巧

简单记录项目开发技巧,方便以后查看。

目标

效果一:表格

效果二:树表格
treetable-lay 简介

只实现全部展开和全部折叠

JSON工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.ray.common.utils;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;

/**
* @author Ray
* @date 2018/11/21 0021
* JSON 方法
*/
public class JsonUtils {

/**
* 格式化用户列表
*/
public JSONObject jsonObject(IPage userIPage) {

JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 0);
jsonObject.put("msg", "");
jsonObject.put("count", userIPage.getTotal());
jsonObject.put("data", userIPage.getRecords());

return jsonObject;
}
}

用于格式化数据(必须)

表格-实现

引入模块

1
2
layui.use('table', function () {
var table = layui.table;

完整页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>角色列表</title>
<link rel="stylesheet" th:href="@{/layuiadmin/layui/css/layui.css}" media="all">
<link rel="stylesheet" th:href="@{/css/ray-ui.css}">
</head>
<body>

<div style="padding: 20px;">
<div style="padding: 10px; background-color: #F2F2F2;">
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-row search">
<span>模糊搜索: </span>
<div class="layui-inline">
<input class="layui-input" id="keyword" autocomplete="off" placeholder="请输入角色名称">
</div>
<button class="layui-btn layui-btn-normal" data-type="reload">搜索</button>
</div>
<div class="layui-row">
<table id="table" lay-filter="test"></table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn layui-btn-sm" lay-event="add">新增</button>
</div>
</script>

<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
</script>

<script th:src="@{/js/ray-ui.js}"></script>
<script th:src="@{/layuiadmin/layui/layui.js}"></script>
<script th:inline="none">
layui.use('table', function () {
var table = layui.table;

table.render({
skin: 'line',
elem: '#table'
, url: '/sysRole/role/roleDate'
, title: '角色数据表'
, toolbar: '#toolbarDemo'
, page: true
, limits: [10,20,50]
, id: 'tableDate'
, cellMinWidth: 60
, cols: [[
{type: 'checkbox', fixed: 'left'}
, {field: 'roleId', title: '编号', sort: true}
, {field: 'roleName', title: '角色名称'}
, {field: 'description', title: '角色描述'}
, {field: 'available', title: '角色状态', align: 'center', sort: true, templet: '#availableTpl'}
, {field: 'roleSort', title: '角色顺序', sort: true}
, {field: 'createTime', title: '创建时间'}
, {field: 'updateTime', title: '更新时间'}
, {fixed: 'right', title: '操作', width: 120, align: 'center', toolbar: '#barDemo'}
]]
});

// 搜索功能
var $ = layui.$, active = {
reload: function () {
var keyword = $('#keyword');
table.reload('tableDate', {
page: {
curr: 1
}
, where: {
keyword: keyword.val()
}
});
}
};

// 点击搜索
$('.search .layui-btn').on('click', function () {
var type = $(this).data('type');
active[type] ? active[type].call(this) : '';
});

// 头工具
table.on('toolbar(test)', function (obj) {
switch (obj.event) {
case 'add':
addRole();
break;
}
});

// 新增角色信息
function addRole() {
layer.open({
skin: 'layui-layer-my',
area: ['45%', '80%'],
type: 2,
fix: false,
maxmin: true,
content: '/sysRole/role/add'
});
};

// 行内工具
table.on('tool(test)', function (obj) {
var data = obj.data;
if (obj.event == 'del') {
layer.confirm('真的删除么?',{
skin: 'layui-layer-my'
}, function (index) {
delRole(data.roleId);
layer.close(index);
});
} else if (obj.event == 'edit') {
editRole(data.roleId);
}
});

// 修改角色信息
function editRole(roleId) {
layer.open({
skin: 'layui-layer-my',
area: ['45%', '80%'],
type: 2,
fix: false,
maxmin: true,
content: '/sysRole/role/edit/' + roleId,
});
};

// 删除用户信息
function delRole(roleId) {
$.ajax({
url: "/sysRole/role/del/" + roleId,
type: "delete",
success: function (result) {
if (result.code == web_status.SUCCESS) {
layer.msg(result.msg, {
icon: 1,
time: 2000
}, function () {
location.reload();
});
} else {
layer.msg(result.msg, {
icon: 2
})
}
}
});
};
});
</script>

<script type="text/html" id="availableTpl">
{{# if(d.available == '0'){ }}
<span class="layui-badge layui-bg-green">正常</span>
{{# } else { }}
<span class="layui-badge layui-bg-orange">锁定</span>
{{# } }}
</script>
</body>
</html>

控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package com.ray.system.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ray.common.base.AjaxResult;
import com.ray.common.base.BaseController;
import com.ray.common.constant.UserConstants;
import com.ray.common.utils.JsonUtils;
import com.ray.system.entity.SysRole;
import com.ray.system.service.SysRoleService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
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.*;

/**
* <p>
* 角色表 前端控制器
* </p>
*
* @author Ray
* @since 2018-11-19
*/
@Api(value = "角色信息表")
@Controller
@RequestMapping("/sysRole/role")
public class SysRoleController extends BaseController {

private String prefix = "system/role";

@Autowired
private SysRoleService sysRoleService;

/**
* 角色列表视图
*/
@ApiOperation(value = "角色列表视图")
@GetMapping("/role")
public String role() {
return prefix + "/role";
}

/**
* 角色列表操作
*/
@ApiOperation(value = "角色列表操作")
@ApiImplicitParams({
@ApiImplicitParam(name = "roleName", value = "根据roleName模糊查询", paramType = "query"),
@ApiImplicitParam(name = "page", value = "分页", dataType = "Integer"),
@ApiImplicitParam(name = "limit", value = "每页显示的条数", dataType = "Integer")
})
@GetMapping("/roleDate")
@ResponseBody
public JSONObject roleDate(int page, int limit,
@RequestParam(value = "keyword", required = false) String roleName) {
JsonUtils jsonUtils = new JsonUtils();

/**
* 如果 userName 为空就执行全部搜索
*/
if (StrUtil.hasEmpty(roleName)) {
Page<SysRole> pages = new Page<>(page, limit);
IPage<SysRole> roleIPage = sysRoleService.page(pages, new QueryWrapper<SysRole>().orderByAsc("role_sort"));
return jsonUtils.jsonObject(roleIPage);
}

/**
* 如果 userName 不为空就执行模糊搜索
*/
Page<SysRole> pages = new Page<>(page, limit);
IPage<SysRole> roleIPage = sysRoleService.page(pages, new QueryWrapper<SysRole>().like("role_name", roleName).orderByAsc("role_sort"));
return jsonUtils.jsonObject(roleIPage);
}

/**
* 新增角色视图
*/
@ApiOperation(value = "新增角色视图")
@GetMapping("/add")
public String add() {
return prefix + "/add";
}

/**
* 新增角色操作
*/
// @RequiresPermissions("sysRole:add")
@ApiOperation(value = "新增角色操作")
@ApiImplicitParam(name = "sysRole", value = "角色对象")
@PostMapping("/add")
@ResponseBody
public AjaxResult addSave(@ModelAttribute SysRole sysRole) {

String roleName = sysRole.getRoleName();

// 验证角色名 唯一
if (ObjectUtil.isNotNull(sysRoleService.getOne(new QueryWrapper<SysRole>().eq("role_name", roleName)))) {
return error(UserConstants.ROLE_NAME_UNIQUE);
}

// 新增角色
boolean result = sysRoleService.save(sysRole);
if (result) {
return success("新增角色成功");
}
return error("新增角色失败");
}

/**
* 修改角色视图
*/
@ApiOperation(value = "修改角色视图")
@GetMapping("/edit/{roleId}")
public String edit(@PathVariable("roleId") Integer roleId, Model model) {
model.addAttribute("role", sysRoleService.getById(roleId));
return prefix + "/edit";
}

/**
* 修改角色操作
*/
// @RequiresPermissions("sysRole:edit")
@ApiOperation(value = "修改角色操作")
@PutMapping("/edit")
@ResponseBody
public AjaxResult editSave(@ModelAttribute SysRole sysRole) {
Integer roleId = sysRole.getRoleId();

if (ObjectUtil.isNotNull(roleId) && SysRole.isAdmin(roleId)) {
return error("不允许修改管理员角色");
}

// if (sysRoleService.updateById(sysRole)) {
if (sysRoleService.myUpdateById(sysRole)) {
return success("修改成功");
}
return error("修改失败");
}

/**
* 删除角色操作
*/
// @RequiresPermissions("sysRole:edit")
@ApiOperation(value = "删除角色操作")
@ApiImplicitParam(name = "roleId", value = "角色ID", required = true, paramType = "path", dataType = "Integer")
@DeleteMapping("/del/{roleId}")
@ResponseBody
public AjaxResult del(@PathVariable("roleId") Integer roleId) {

if (sysRoleService.removeById(roleId)) {
return success("删除成功");
}

return error("删除失败");
}
}

树表格-实现

引入模块

1
2
3
4
5
6
layui.config({
base: '/module/'
}).extend({
treetable: 'treetable-lay/treetable'
}).use(['treetable'], function () {
var treetable = layui.treetable;

完整页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>菜单列表</title>
<link rel="stylesheet" th:href="@{/layuiadmin/layui/css/layui.css}" media="all">
<link rel="stylesheet" th:href="@{/css/ray-ui.css}">
</head>
<body>

<div style="padding: 20px;">
<div style="padding: 10px; background-color: #F2F2F2;">
<div class="layui-row layui-col-space15">
<div class="layui-col-md12">
<div class="layui-card">
<div class="layui-card-body">
<div class="layui-row search">
<span>模糊搜索: </span>
<div class="layui-inline">
<input class="layui-input" id="keyword" autocomplete="off" placeholder="请输入角色名称">
</div>
<button class="layui-btn layui-btn-normal" data-type="reload">搜索</button>

<div class="layui-btn-group">
<button class="layui-btn" id="btn-expand">全部展开</button>
<button class="layui-btn" id="btn-fold">全部折叠</button>
</div>
</div>
<div class="layui-row">
<table id="auth-table" class="layui-table" lay-filter="auth-table"></table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<script type="text/html" id="toolbarDemo">
<div class="layui-btn-container">
<button class="layui-btn" lay-event="add">新增菜单</button>
<!--<div class="layui-btn-group">-->
<!--<button class="layui-btn" id="btn-expand">全部展开</button>-->
<!--<button class="layui-btn" id="btn-fold">全部折叠</button>-->
<!--</div>-->
</div>
</script>

<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
</script>

<script th:src="@{/js/ray-ui.js}"></script>
<script th:src="@{/webjars/jquery/jquery.min.js}"></script>
<script th:src="@{/layuiadmin/layui/layui.js}"></script>
<script th:inline="none">
layui.config({
base: '/module/'
}).extend({
treetable: 'treetable-lay/treetable'
}).use(['treetable'], function () {
var treetable = layui.treetable;

// 渲染表格
treetable.render({
skin: 'line',
toolbar: '#toolbarDemo',
treeColIndex: 1 // 树形图标显示在第几列
, treeSpid: 0 // 最上级的父级id
, treeIdName: 'menuId' // id字段的名称
, treePidName: 'parentId' // pid字段的名称
, treeDefaultClose: false // 是否默认折叠
, treeLinkage: false // 父级展开时是否自动展开所有子级
, elem: '#auth-table'
, url: '/sysMenu/menu/menuDate'
, cols: [[
{type: 'numbers', title: '序号', width: 80}
, {field: 'menuName', title: '菜单名称'}
, {field: 'orderNum', title: '排序'}
, {field: 'url', title: '请求地址'}
, {field: 'menuType', title: '菜单类型', align: 'center', templet: function (d) {
if (d.menuType == 'M') {
return '<span class="layui-badge">目录</span>';
}
if (d.menuType == 'C') {
return '<span class="layui-badge layui-bg-blue">菜单</span>';
} else {
return '<span class="layui-badge-rim">按钮</span>';
}
}}
, {field: 'visible', title: '可见', align: 'center', templet: function (d) {
if (d.visible == '0') {
return '<span class="layui-badge layui-bg-green">可见</span>'
} else {
return '<span class="layui-badge-rim">隐藏</span>'
}
}}
, {field: 'perms', title: '权限标识'}
, {fixed: 'right', title: '操作', width: 120, align: 'center', toolbar: '#barDemo'}
]]
});

$('#btn-expand').click(function () {
treetable.expandAll('#auth-table');
});

$('#btn-fold').click(function () {
treetable.foldAll('#auth-table');
});
});
</script>

</body>
</html>

控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.ray.system.controller;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ray.common.base.BaseController;
import com.ray.common.utils.JsonUtils;
import com.ray.system.entity.SysMenu;
import com.ray.system.service.SysMenuService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ResponseBody;

/**
* <p>
* 菜单权限表 前端控制器
* </p>
*
* @author Ray
* @since 2018-11-27
*/
@Api(value = "菜单信息表")
@Controller
@RequestMapping("/sysMenu/menu")
public class SysMenuController extends BaseController {

private String prefix = "system/menu";

@Autowired
private SysMenuService sysMenuService;

/**
* 菜单列表视图
*/
@ApiOperation(value = "菜单列表视图")
@GetMapping("/menu")
public String menu() {
return prefix + "/menu";
}

/**
* 菜单列表操作
*/
@ApiOperation(value = "菜单列表操作")
@GetMapping("/menuDate")
@ResponseBody
public JSONObject menuDate() {

JsonUtils jsonUtils = new JsonUtils();

Page<SysMenu> pages = new Page<>(1, 100);
IPage<SysMenu> menuIPage = sysMenuService.page(pages, null);
return jsonUtils.jsonObject(menuIPage);
}
}