【知识积累】Thymeleaf + layui

本文源码:https://github.com/dg1222/spring-boot(有什么问题可以提issue给我,一起学习,共同进步。)

本文参考资料(layui2.0官方文档):https://www.layui.com/doc/

1、页面

【知识积累】Thymeleaf + layui

【知识积累】Thymeleaf + layui

【知识积累】Thymeleaf + layui

【知识积累】Thymeleaf + layui

【知识积累】Thymeleaf + layui

【知识积累】Thymeleaf + layui

2、html

2.1、list.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head lang="en">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="UTF-8">
    <title>用户列表</title>
    <link rel="stylesheet" th:href="@{/layui.2.2.3/layui/css/layui.css}" media="all"/>
</head>
<body class="childrenBody">
<div style="width: 100%; text-align: center">
    <form class="layui-form">
        <blockquote class="layui-elem-quote" style="border-left-width: 0px;">
            <div class="layui-inline">
                <div class="layui-input-inline">
                    <input type="text" id="name" name="name" placeholder="姓名" class="layui-input"/>
                </div>
                <div class="layui-input-inline">
                    <label class="layui-form-label">性别</label>
                    <div class="layui-input-inline">
                        <select id="sex" name="sex">
                            <option value="">全部</option>
                            <option th:each="d : ${data}" th:value="${d.dictName}" th:text="${d.dictName}"></option>
                        </select>
                    </div>
                </div>
                <div class="layui-input-inline">
                    <input type="text" id="startTime" name="startTime" placeholder="开始时间" class="layui-input" th:readonly="true"/>
                </div>
                <div class="layui-input-inline">
                    <input type="text" id="endTime" name="endTime" placeholder="结束时间" class="layui-input" th:readonly="true"/>
                </div>
            </div>

            <div class="layui-inline">
                <a class="layui-btn searchBtn"><i class="layui-icon">&#xe615;</i>查询</a>
            </div>
            <div class="layui-inline">
                <a class="layui-btn add"><i class="layui-icon">&#xe634;</i>添加</a>
            </div>
        </blockquote>
    </form>
</div>
<!--<table class="layui-table">
    <tr>
        <th>姓名</th>
        <th>性别</th>
        <th>年龄</th>
        <th>号码</th>
        <th>创建时间</th>
        <th>更新时间</th>
    </tr>
    <tr th:if="${users.size()} eq 0">
        <td colspan="6">没有用户信息!!</td>
    </tr>
    <tr th:each="user : ${users}">
        <td th:text="${user.name}"/>
        <td th:text="${user.sex}"/>
        <td th:text="${user.age}"/>
        <td th:text="${user.mobile}"/>
        <td th:text="${#dates.format(user.createTime, 'yyyy-MM-dd HH:mm:ss')}"/>
        <td th:text="${#dates.format(user.updateTime, 'yyyy-MM-dd HH:mm:ss')}"/>
    </tr>
</table>-->
<table class="layui-table" id="dataTable"></table>

<script type="text/html" id="operationTemplet">
    <a class='layui-btn layui-btn-xs edit' data-id='{{d.id}}'>修改</a>
</script>
</body>
<script type="text/javascript" th:src="@{/layui.2.2.3/layui/layui.js}"></script>
<script type="text/javascript" th:src="@{/js/user.js}"></script>
<script type="text/javascript" th:src="@{/js/base.js}"></script>
</html>

2.2、add.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <title>用户信息新增</title>
    <link rel="stylesheet" th:href="@{/layui.2.2.3/layui/css/layui.css}" media="all"/>
</head>
<body class="childrenBody">
<form class="layui-form" style="width:80%;">
    <div class="layui-row" style="margin-top: 20px;">

        <div class="layui-form-item">
            <label class="layui-form-label">姓名</label>
            <div class="layui-input-block">
                <input type="text" name="name" class="layui-input" lay-verify="required"/>
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">性别</label>
            <div class="layui-input-block">
                <input type="text" name="sex" class="layui-input" lay-verify="required" />
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">年龄</label>
            <div class="layui-input-block">
                <input type="text" name="age" class="layui-input" lay-verify="required" />
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">电话</label>
            <div class="layui-input-block">
                <input type="text" name="mobile" class="layui-input" lay-verify="required" />
            </div>
        </div>

        <div class="layui-form-item">
            <div class="layui-input-block" style="text-align: center">
                <button class="layui-btn" lay-submit="" lay-filter="saveSubmit">保存</button>
            </div>
        </div>
    </div>
</form>
</body>
<script type="text/javascript" th:src="@{/layui.2.2.3/layui/layui.js}"></script>
<script type="text/javascript" th:src="@{/js/user.js}"></script>
<script type="text/javascript" th:src="@{/js/base.js}"></script>
</html>

2.3、edit.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="utf-8" />
    <title>用户信息编辑</title>
    <link rel="stylesheet" th:href="@{/layui.2.2.3/layui/css/layui.css}" media="all"/>
</head>
<body class="childrenBody">
<form class="layui-form" style="width:80%;">
    <div class="layui-row" style="margin-top: 20px;">

        <div class="layui-form-item">
            <label class="layui-form-label">姓名</label>
            <div class="layui-input-block">
                <input type="hidden" name="id" th:value="${user.id}" />
                <input type="text" name="name" th:value="${user.name}" class="layui-input" th:readonly="true" />
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">性别</label>
            <div class="layui-input-block">
                <input type="text" name="sex" th:value="${user.sex}" class="layui-input" th:readonly="true" />
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">年龄</label>
            <div class="layui-input-block">
                <input type="text" name="age" th:value="${user.age}" class="layui-input" th:readonly="true" />
            </div>
        </div>

        <div class="layui-form-item">
            <label class="layui-form-label">电话</label>
            <div class="layui-input-block">
                <input type="text" name="mobile" th:value="${user.mobile}" class="layui-input" lay-verify="required" />
            </div>
        </div>

        <div class="layui-form-item">
            <div class="layui-input-block" style="text-align: center">
                <button class="layui-btn" lay-submit="" lay-filter="saveSubmit">保存</button>
            </div>
        </div>
    </div>
</form>
</body>
<script type="text/javascript" th:src="@{/layui.2.2.3/layui/layui.js}"></script>
<script type="text/javascript" th:src="@{/js/user.js}"></script>
<script type="text/javascript" th:src="@{/js/base.js}"></script>
</html>

3、js

3.1、base.js

var s = {};

s = {
    rootUrl: '/spring-boot',
    successCode: '0',
    failureCode: '1'
};

3.2、user.js

var $;
layui.use(['form', 'layer', 'jquery', 'table', 'laydate'], function () {
    //定义参数
    var form = layui.form,
        layer = parent.layer === undefined ? layui.layer : parent.layer,
        $ = layui.jquery,
        table = layui.table,
        laydate = layui.laydate;

    //使用layui日期组件
    laydate.render({
        type: 'datetime',
        // lang: 'en',
        theme: 'grid',
        calendar: true,
        elem: '#startTime'
    });
    laydate.render({
        type: 'datetime',
        lang: 'en',
        // theme: 'grid',
        // calendar: true,
        elem: '#endTime'
    });

    //方法级渲染的重载 https://www.layui.com/doc/modules/table.html#reload
    //所获得的tableIns即为当前容器的实例
    var tableIns = table.render({
        //table的id
        elem: '#dataTable',
        //开启分页
        page: true,
        even: true,
        //数据接口
        url: s.rootUrl + '/user/listPage',
        //表头
        cols: [[{field: 'name', title: '姓名', width: '10%', sort: true, fixed: 'left', align: 'center'}
            , {field: 'sex', title: '性别', width: '10%', align: 'center'}
            , {field: 'age', title: '年龄', width: '10%', align: 'center'}
            , {field: 'mobile', title: '号码', width: '20%', align: 'center'}
            , {
                field: 'createTime',
                title: '创建时间',
                width: '20%',
                sort: true,
                align: 'center',
                templet: '<div>{{ Format(d.createTime,"yyyy-MM-dd hh:mm:ss")}}</div>'
            }
            , {
                field: 'updateTime',
                title: '更新时间',
                width: '20%',
                sort: true,
                align: 'center',
                templet: '<div>{{ Format(d.updateTime,"yyyy-MM-dd hh:mm:ss")}}</div>'
            }
            , {title: '操作', width: '10%', align: 'center', templet: '#operationTemplet'}
        ]]
    });

    //搜索
    $("body").on("click", ".searchBtn", function () {
        var name = $.trim($("#name").val());
        var sex = $.trim($("#sex").val());
        var startTime = $.trim($("#startTime").val());
        var endTime = $.trim($("#endTime").val());
        tableIns.reload({
            //请求参数
            where: {
                name: name
                , sex: sex
                , startTime: startTime
                , endTime: endTime
            },//重新从第1页开始
            page: {
                curr: 1
            }
        });
    })

    //新增
    $("body").on("click", ".add", function () {
        layui.layer.open({
            title: "新增菜单信息",//标题
            type: 2,//基本层类型
            area: ['500px', '350px'], //宽高
            content: s.rootUrl + "/user/add" //内容
        });
    })

    //编辑
    $("body").on("click", ".edit", function () {
        var id = $(this).attr('data-id');
        layui.layer.open({
            title: "编辑菜单信息",//标题
            type: 2,//基本层类型
            area: ['500px', '350px'], //宽高
            content: s.rootUrl + "/user/edit/" + id //内容
        });
    })

    //提交
    form.on('submit(saveSubmit)', function (data) {
        $.ajax({
            type: "post",
            url: s.rootUrl + "/user/save",
            data: data.field,
            success:function (result) {
                if (result["code"] == s.successCode){
                    window.parent.location.reload();
                    layer.closeAll();
                }else{
                    layer.alert(result["msg"]);
                    return false;
                }
            }
        });
        return false;
    });

});

// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
// 例子:
//Format("2016-10-04 8:9:4.423","yyyy-MM-dd hh:mm:ss.S") ==> 2016-10-04 08:09:04.423
// Format("1507353913000","yyyy-M-d h:m:s.S")      ==> 2017-10-7 13:25:13.0
function Format(datetime, fmt) {
    if (parseInt(datetime) == datetime) {
        if (datetime.length == 10) {
            datetime = parseInt(datetime) * 1000;
        } else if (datetime.length == 13) {
            datetime = parseInt(datetime);
        }
    }
    datetime = new Date(datetime);
    var o = {
        "M+": datetime.getMonth() + 1,                 //月份
        "d+": datetime.getDate(),                    //日
        "h+": datetime.getHours(),                   //小时
        "m+": datetime.getMinutes(),                 //分
        "s+": datetime.getSeconds(),                 //秒
        "q+": Math.floor((datetime.getMonth() + 3) / 3), //季度
        "S": datetime.getMilliseconds()             //毫秒
    };
    if (/(y+)/.test(fmt))
        fmt = fmt.replace(RegExp.$1, (datetime.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
        if (new RegExp("(" + k + ")").test(fmt))
            fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}

4、Controller

package com.darren.center.springboot.controller;

import com.darren.center.springboot.annotation.RequestLimit;
import com.darren.center.springboot.common.Constants;
import com.darren.center.springboot.common.ResponseHelper;
import com.darren.center.springboot.common.WebStatusEnum;
import com.darren.center.springboot.entity.Dict;
import com.darren.center.springboot.entity.User;
import com.darren.center.springboot.service.DictService;
import com.darren.center.springboot.service.UserService;
import com.darren.center.springboot.utils.ResponseUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

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

@Slf4j
@Controller
@RequestMapping("/user")
public class UserController extends BaseController{

    @Autowired
    private UserService userService;

    @Autowired
    private DictService dictService;

    @RequestMapping("/test")
    public String test(){
        return "user/test";
    }

    /**
     * 访问主页
     * @param model
     * @return
     */
    @RequestMapping("/list")
    public String list(Model model){
        List<Dict> data = dictService.selectDictByType(Constants.USER_SEX);
        model.addAttribute("data", data);
        return "user/list";
    }

    /**
     * 返回json数据
     * @param params
     * @return
     */
    @RequestMapping("/listPage")
    @ResponseBody
    public ResponseHelper listPage(@RequestParam Map<String, Object> params){
        List<User> users = userService.selectUserList(params);
        Integer pageCount = userService.selectUserListPageCount(params);
        return ResponseUtils.response(WebStatusEnum.SUCCESS.getCode(), WebStatusEnum.SUCCESS.getMsg(), users, pageCount);
    }

    /**
     * 跳转到新增页面
     * @return
     */
    @RequestMapping("/add")
    public String add(){
        return "user/add";
    }

    /**
     * 跳转到编辑页面
     * @param id
     * @param model
     * @return
     */
    @RequestMapping("/edit/{id}")
    public String edit(@PathVariable("id") int id, Model model){
        User user = userService.selectByPrimaryKey(Long.valueOf(id));
        model.addAttribute("user", user);
        return "user/edit";
    }

    /**
     * 保存
     * @param user
     * @return
     */
    @RequestMapping("/save")
    @ResponseBody
    @RequestLimit(count = 5)
    public ResponseHelper save(User user){
        int flag;
        if (null == user.getId()){
            flag = userService.addUser(user);
        }else {
            flag = userService.editUserById(user);
        }
        return ResponseUtils.responseWrap(flag);
    }
}

5、Response Class

package com.darren.center.springboot.common;

import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * 响应类
 */
@Getter
@Setter
@ToString
@EqualsAndHashCode
public class ResponseHelper implements Serializable{

    private static final long serialVersionUID = -4908915966053299827L;

    /**
     * 返回码
     */
    private String code;

    /**
     * 返回消息
     */
    private String msg;

    /**
     * 总记录数(分页)
     */
    private Integer count;

    /**
     * 数据列表
     */
    private List<?> data;

    private static ResponseHelper response = null;
    private static List<?> list = new ArrayList<>();


    /**
     * 单例模式(懒汉型)
     * @return
     */
    public static ResponseHelper getInstanse(){
        if (null == response){
            synchronized (ResponseHelper.class){
                if (null == response){
                    response = new ResponseHelper();
                }
            }
        }
        init();
        return response;
    }

    /**
     * 初始化list
     */
    private static void init(){
        if (null == list){
            list = new ArrayList<>();
        }else {
            list.clear();
        }
        response.setData(list);
    }

}

6、常见问题

对table.render的数据进行处理,例如:判断

//方法级渲染的重载 https://www.layui.com/doc/modules/table.html#reload
    //所获得的tableIns即为当前容器的实例
    var tableIns = table.render({
        //table的id
        elem: '#dataTable',
        //开启分页
        page: true,
        even: true,
        //数据接口
        url: s.rootUrl + '/user/listPage',
        //表头
        cols: [[{field: 'name', title: '姓名', width: '10%', sort: true, fixed: 'left', align: 'center'}
            , {field: 'sex', title: '性别', width: '10%', align: 'center'}
            , {field: 'age', title: '年龄', width: '10%', align: 'center'}
            , {field: 'mobile', title: '号码', width: '20%', align: 'center'}
            , {field: 'status', title: '状态', width: '20%', templet: '#status'}
            , {
                field: 'createTime',
                title: '创建时间',
                width: '20%',
                sort: true,
                align: 'center',
                templet: '<div>{{ Format(d.createTime,"yyyy-MM-dd hh:mm:ss")}}</div>'
            }
            , {
                field: 'updateTime',
                title: '更新时间',
                width: '20%',
                sort: true,
                align: 'center',
                templet: '<div>{{ Format(d.updateTime,"yyyy-MM-dd hh:mm:ss")}}</div>'
            }
            , {title: '操作', width: '10%', align: 'center', templet: '#operationTemplet'}
        ]]
    });
<script type="text/html" id="status">
	{{#  if(d.status == 0){ }}
	  <p style="color:#5FB878; float:left;">启用</p>
	{{#  } else { }}
	  <p style="color:red; float:left;">停用</p>
	{{#  } }}
</script>