springboot+mybatis+bootstrap简单项目实例二

前面写了个简单的登陆功能,这里就简单的实现一下crud。

dao层

实体

package com.example.student.entity;

import java.util.Date;

/**
 * 学生信息表
 *
 * @author xiaotao
 */
public class StudentDO {

    /**
     * 主键
     */
    private String id;

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 性别
     */
    private String sex;

    /**
     * 创建日期
     */
    private Date createTime;

    /**
     * 更新时间
     */
    private Date updateTime;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    @Override
    public String toString() {
        return "StudentDO{" +
                "id='" + id + '\'' +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                ", createTime=" + createTime +
                ", updateTime=" + updateTime +
                '}';
    }

}

访问对象

这里count接口是干什么的呢,其实是用来前端分页的。

我们前端使用表格来显示学生信息,但是我们几乎不会用表格的一页显示所有数据,所有需要分页,这里大致分服务器分页和客户端分页。

  • 客户端分页:一次性加载所有数据,切换数据不会再请求服务器。
  • 服务器分页:显示多少数据,请求多少数据。

我们这里采用服务器分页,count就是用来统计数据的总量。
为什么要有这个接口呢,当然是我们后面service会用到了。。。所以后面再讲。

count和getStudent的参数是用来传递搜索信息的,这里我们搜索就放在数据库了,所以你在其他层是看不到搜索相关代码的。

package com.example.student.dao;

import com.example.student.entity.StudentDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

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

/**
 * 学生DAO接口
 *
 * @author xiaotao
 */
@Mapper
public interface StudentDAO {

    /**
     * 获得学生信息数据的数量
     *
     * @param params 过滤参数
     * @return 学生的数量
     */
    int count(Map<String, Object> params);

    /**
     * 获取学生信息
     *
     * @param params 过滤参数
     * @return 学生信息主表链表
     */
    List<StudentDO> getStudent(Map<String, Object> params);

    /**
     * 插入一条记录
     *
     * @param studentDO 实体
     */
    void insert(StudentDO studentDO);

    /**
     * 删除
     *
     * @param id 主键
     */
    void delete(@Param("id") String id);

    /**
     * 修改客户信息
     *
     * @param studentDO 实体信息
     */
    void update(StudentDO studentDO);

}

xml文件

这里搜索就只搜索了name一个字段。

getStudent里面ORDER BY ${sort} ${order}用来按照字段排序,LIMIT #{offset}, #{limit}用来分页的,选取我们需要的数据。

insert里面selectKey可以自动生成id。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.student.dao.StudentDAO">
    <resultMap id="StudentDO" type="com.example.student.entity.StudentDO">
        <id column="id" property="id" jdbcType="VARCHAR"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="sex" property="sex"/>
        <result column="create_time" property="createTime"/>
        <result column="update_time" property="updateTime"/>
    </resultMap>

    <select id="count" resultType="java.lang.Integer">
        SELECT count(*)
        FROM `t_student`
        <where>
            <if test="name != null"> AND `name` LIKE CONCAT('%', #{name ,jdbcType=VARCHAR}, '%') </if>
        </where>
    </select>

    <select id="getStudent" resultMap="StudentDO">
        SELECT *
        FROM `t_student`
        <where>
            <if test="name != null"> AND `name` LIKE CONCAT('%', #{name ,jdbcType=VARCHAR}, '%') </if>
        </where>
        <choose>
            <when test="sort != null and sort.trim() != ''">
                ORDER BY ${sort} ${order}
            </when>
        </choose>
        <if test="offset != null and limit != null">
            LIMIT #{offset}, #{limit}
        </if>
    </select>

    <insert id="insert" parameterType="com.example.student.entity.StudentDO">
        <selectKey keyProperty="id" resultType="String" order="BEFORE">
            SELECT replace(uuid(),'-','') FROM dual;
        </selectKey>
        INSERT INTO `t_student` (`id`, `name`, `age`, `sex`, `create_time`, `update_time`)
        VALUES (#{id}, #{name}, #{age}, #{sex}, now(), now())
    </insert>

    <delete id="delete">
        DELETE FROM `t_student`
        WHERE `id` = #{id};
    </delete>

    <update id="update" parameterType="com.example.student.entity.StudentDO">
        UPDATE `t_student`
        SET `name` = #{name},
            `age` = #{age},
            `sex` = #{sex},
            `update_time` = now()
        WHERE `id` = #{id};
    </update>

</mapper>

测试

尽管测试很简单,只是判断一下代码写的成不成功,但是也不能忽略。

package com.example.student.dao;

import com.example.student.entity.StudentDO;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;

import java.util.List;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

@SpringBootTest
class StudentDAOTest {

    @Resource
    private StudentDAO studentDAO;

    @Test
    void testCount() {
        assertEquals(1, studentDAO.count(null));
    }

    @Test
    void testGetStudent() {
        List<StudentDO> result =  studentDAO.getStudent(null);
        assertNotNull( result );
        result.forEach( System.out::println );
    }

    @Test
    void testInsert() {
        StudentDO studentDO = new StudentDO();

        studentDO.setName("xxx");
        studentDO.setAge(10);
        studentDO.setSex("男");

        studentDAO.insert(studentDO);
    }

    @Test
    void testDelete() {
        studentDAO.delete("b4de711f900c11ea8fc654e1ad394a4a");
    }

    @Test
    void testUpdate() {
        StudentDO studentDO = new StudentDO();

        studentDO.setId("b4de711f900c11ea8fc654e1ad394a4a");
        studentDO.setName("yyy");
        studentDO.setAge(20);
        studentDO.setSex("女");

        studentDAO.update(studentDO);
    }

}

添加学生展示页面

添加插件

Bootstrap-table 显示表格
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

sweetalert 提示框(稍微好看点)
在这里插入图片描述
jquery-ui 拖动模态框等效果
在这里插入图片描述

在这里插入图片描述

插件具体如何使用可以去官网查看,这里只用最简单的一些功能。

添加一些js功能

  1. 初始化表格
  2. 弹出对话框
  3. 提示框样式修改
  4. ajax请求封装
  5. 时间格式化
  6. 模态框居中和拖拽功能
/**
 * 渲染表格要用到的常用代码封装
 */

// 初始化表格
function initTable(node, url, pageList, queryParams, columns, toolbar = '#toolbar') {
    node.bootstrapTable("destroy");         // 先销毁用来的表格再构造新的表格
    node.bootstrapTable({
        toolbar: toolbar,                   // 工具按钮用哪个容器
        method: 'get',                      // 请求方式
        url: url,                           // 请求路径
        dataType: "json",                   // 服务器返回的数据类型
        contentType: "application/json",    // 发送到服务器的数据编码类型
        striped: true,                     // 是否显示行间隔色
        cache: false,                      // 是否使用缓存,默认为true,所以一般情况下需要设置一下这个属性(*)
        pagination: true,                  // 是否显示分页(*)
        sortable: false,                   // 是否启用排序
        sortOrder: "asc",                   // 排序方式
        sidePagination: "server",           // 分页方式:client客户端分页,server服务端分页(*)
        queryParamsType: "limit",           // 设置为 ‘limit’ 则会发送符合 RESTFul 格式的参数
        pageNumber: 1,                      // 初始化加载第一页,默认第一页
        pageSize: 10,                       // 每页的记录行数(*)
        pageList: pageList,                 // 可供选择的每页的行数(*)
        showColumns: true,                 // 是否显示所有的列
        showRefresh: true,                 // 是否显示刷新按钮
        minimumCountColumns: 2,             // 最少允许的列数
        clickToSelect: true,               // 是否启用点击选中行
        showToggle:true,                   // 是否显示详细视图和列表视图的切换按钮
        cardView: false,                   // 是否显示详细视图
        detailView: false,                 // 是否显示父子表
        uniqueId: "id",                     // 每一行的唯一标识,一般为主键列
        dataField: "rows",                  // 这是返回的json数组的key.默认好像是"rows".这里只要前后端约定好就行
        queryParams: queryParams,
        responseHandler: result => {
            if (result.success === false) {
                switch (result.code) {
                    case 9001: swal("错误", "数据库错误", "error");   break;
                    case 9002: swal("错误", "参数错误", "error");     break;
                    case 9999: swal("错误", "系统错误", "error");     break;
                }
                return null;
            } else {
                return { total: result.module.total, rows: result.module.rows, };
            }
        },
        columns: columns,
        rowStyle: function (row, index) {
            let classesArr = ['info', '#ffffff'];
            let strClass = "";
            if (index % 2 === 0) {  // 偶数行
                strClass = classesArr[0];
            } else {    // 奇数行
                strClass = classesArr[1];
            }
            return { classes: strClass };
        }// 隔行变色
    });
}

// 弹出框
function dialog(message, callback) {
    swal(message, {
        buttons: {
            true: "确定",
            cancel: "取消"
        },
    }).then((value) => {
        switch (value) {
            case "true":
                callback();
                break;
            default:
                break;
        }
    });
}

// 修改提示框样式
function changeToolTip() {
    $(function() {
        $( document ).tooltip({
            position: {
                my: "center bottom-20",
                at: "center top",
                using: function( position, feedback ) {
                    $( this ).css( position );
                    $( "<div>" )
                        .addClass( "arrow" )
                        .addClass( feedback.vertical )
                        .addClass( feedback.horizontal )
                        .appendTo( this );
                }
            },
            show: {
                effect: "slideDown",
                delay: 250
            },
            hide: {
                effect: "explode",
                delay: 250
            }
        });

        $("select").on("select2:close", () => $("[role=tooltip]").remove());
    });
}

// 无参数请求
function noParameterPostRequest(url, callback, method = "POST") {
    $.ajax({
        type: method,
        url: url,
        dataType: "json",
        contentType : "application/json",
        success: function (result) {
            if (result.success === false) {
                switch (result.code) {
                    case 9001: swal("错误", "数据库错误", "error");   break;
                    case 9002: swal("错误", "参数错误", "error");     break;
                    case 9999: swal("错误", "系统错误", "error");     break;
                }
            } else {
                callback(result);
            }
        },
        error: function () {
            swal("错误", "404", "error");
        }
    });
}

// 有参数请求
function parameterPostRequest(url, data, callback, method = "POST") {
    $.ajax({
        type: method,
        url: url,
        dataType: "json",
        data: JSON.stringify(data),
        traditional: true,
        contentType : "application/json",
        success: function (result) {
            if (result.success === false) {
                switch (result.code) {
                    case 9001: swal("错误", "数据库错误", "error");   break;
                    case 9002: swal("错误", "参数错误", "error");     break;
                    case 9999: swal("错误", "系统错误", "error");     break;
                }
            } else {
                callback(result);
            }
        },
        error: function () {
            swal("错误", "404", "error");
        }
    });
}

// UTC时间格式转换
function addZero(num) {
    return num < 10 ? '0' + num : num;
}
function formatDateTime(date) {
    let time = new Date(Date.parse(date));
    let Y = time.getFullYear() + '-';
    let M = this.addZero(time.getMonth() + 1) + '-';
    let D = this.addZero(time.getDate()) + ' ';
    let h = this.addZero(time.getHours()) + ':';
    let m = this.addZero(time.getMinutes()) + ':';
    let s = this.addZero(time.getSeconds());
    return Y + M + D + h + m + s;
}

// 普通数据处理
function stringFormatter(value) {
    return null === value ? "" : '<span title="'+ value +'">' + value +'</span>';
}

// 时间数据处理
function dateFormatter(value) {
    return null === value ? "" : '<span title="'+ formatDateTime(value) +'">' + formatDateTime(value) +'</span>';
}
/**
 * 修改模态框的操作
 */

// 修改模态框显示位置
function changeModalDialogLocation(node) {
    node.on('show.bs.modal', function (e) {
        // 关键代码,如没将modal设置为 block,则$modala_dialog.height() 为零
        $(this).css('display', 'block');
        let modalHeight=$(window).height() / 2 - node.find('.modal-dialog').height() / 2;
        $(this).find('.modal-dialog').css({
            'margin-top': modalHeight
        });
    });
}

// 设置模态框可拖动
function dragTheModalDialog() {
    $(".modal").each((index, element) => changeModalDialogLocation($(element)));

    // 在模态框出现后添加可拖拽功能
    $(document).on("show.bs.modal", ".modal", function() {
        // draggable 属性规定元素是否可拖动
        $(this).draggable({
            handle: ".modal-header", // 只能点击头部拖动
            cursor: 'move' // 光标呈现为指示链接的指针(一只手),
        });
        $(this).css("overflow", "hidden"); // 防止出现滚动条,出现的话,你会把滚动条一起拖着走的
    });
}

修改页面

用来那个只有登陆成功的页面就改成我们显示学生信息的页面吧。

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

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>学生信息</title>
    <!-- Bootstrap CSS-->
    <link rel="stylesheet" href="../../static/css/lib/bootstrap3.4.1.min.css" th:href="@{/css/lib/bootstrap3.4.1.min.css}">
    <!-- Bootstrap-table CSS-->
    <link rel="stylesheet" href="../../static/css/lib/bootstrap-table.min.css" th:href="@{/css/lib/bootstrap-table.min.css}">
     <!-- jquery-ui CSS-->
    <link rel="stylesheet" href="../../static/css/lib/jquery-ui.min.css" th:href="@{/css/lib/jquery-ui.min.css}">
    <!-- theme stylesheet-->
    <link rel="stylesheet" href="../../static/css/table.css" th:href="@{/css/table.css}">
</head>
<body onload="init();">

    <div class="panel-body" style="padding-bottom:0;">
        <div class="panel panel-default">
            <div class="panel-heading">查询条件</div>
            <div class="panel-body">
                <div class="form-group" style="margin-top:15px">
                    <div class="row row-gap">
                    <label class="control-label col-sm-2 label-font" for="txt_search_name" title="姓名">姓名</label>
                    <div class="col-sm-3">
                        <input type="text" class="form-control" id="txt_search_name">
                    </div>
                    <div class="col-sm-4" style="text-align:left;">
                        <button type="button" style="margin-left:50px" id="btn_filter" class="btn btn-primary" onclick="filter();">过滤</button>
                        <button type="button" style="margin-left:50px" id="btn_reset_filter" class="btn btn-primary" onclick="init();">重置过滤</button>
                    </div>
                </div>
            </div>
        </div>

        <div id="toolbar" class="btn-group">
            <button id="btn_add" type="button" class="btn btn-default" onclick="insert();">
                <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>添加学生
            </button>
        </div>
        <table id="table"></table>
    </div>

<!-- JavaScript files-->
<!-- jquery.js -->
<script src="../../static/js/lib/jquery.min.js" th:src="@{/js/lib/jquery.min.js}"></script>
<!-- Bootstrap.js -->
<script src="../../static/js/lib/bootstrap3.4.1.min.js" th:src="@{/js/lib/bootstrap3.4.1.min.js}"></script>
<!-- Bootstrap-table.js -->
<script src="../../static/js/lib/bootstrap-table.min.js" th:src="@{/js/lib/bootstrap-table.min.js}"></script>
<script src="../../static/js/lib/bootstrap-table-zh-CN.min.js" th:src="@{/js/lib/bootstrap-table-zh-CN.min.js}"></script>
<!-- sweetalert2.js -->
<script src="../../static/js/lib/sweetalert.min.js" th:src="@{/js/lib/sweetalert.min.js}"></script>
<script src="../../static/js/lib/es6-promise.auto.min.js" th:src="@{/js/lib/es6-promise.auto.min.js}"></script>
<!-- jquery-ui.js -->
<script src="../../static/js/lib/jquery-ui.min.js" th:src="@{/js/lib/jquery-ui.min.js}"></script>
<script src="../../static/js/common.js" th:src="@{/js/common.js}"></script>
<script src="../../static/js/dragModel.js" th:src="@{/js/dragModel.js}"></script>
<script>
    
    function init() {
        
    }
    
    function filter() {
        
    }

    function insert() {

    }
    
</script>
</body>
</html>

运行结果:
在这里插入图片描述

添加增删改查功能

前戏做足了,要开始到高潮部分了。

显示数据

添加工具类

我们为了实现分页,先添加一些工具类,也是为了配合Bootstrap-table插件的使用。

这里total字段是固定的,rows字段其实不一定要叫rows也可以叫别的,和刚刚写的初始化表格里面的设置是对应的。
在这里插入图片描述

package edu.yctc.erpsystem.util;

import java.util.List;

/**
 * 分页存放工具类
 *
 * @author xiaotao
 */
public class PageUtils<T> {

    /**
     * 数据总数
     */
    private int total;

    /**
     * 数据
     */
    private List<T> rows;

    public PageUtils(int total, List<T> rows) {
        this.total = total;
        this.rows = rows;
    }

    public int getTotal() {
        return total;
    }

    public void setTotal(int total) {
        this.total = total;
    }

    public List<T> getRows() {
        return rows;
    }

    public void setRows(List<T> rows) {
        this.rows = rows;
    }

    @Override
    public String toString() {
        return "PageUtils{" +
                "total=" + total +
                ", rows=" + rows +
                '}';
    }

}

这个是帮助判断前端传递的参数的。

package edu.yctc.erpsystem.util;

import java.util.Map;

/**
 * 处理参数
 *
 * @author xiaotao
 */
public class ParamUtils {

    /** list 为 All */
    private static final String NAN = "NaN";

    /** 偏移量 */
    private static final String OFFSET = "offset";

    /** 步长 */
    private static final String LIMIT = "limit";

    /**
     * 验证入参正确性
     *
     * @param params 参数
     * @return 是否正确
     */
    public static Boolean validation(Map<String, Object> params) {
        try {
            if (NAN.equals(params.get(OFFSET))) {
                params.remove(OFFSET);
                params.remove(LIMIT);
                return true;
            }
            params.replace(OFFSET, Integer.valueOf((String)params.get(OFFSET)));
            params.replace(LIMIT, Integer.valueOf((String)params.get(LIMIT)));
            return true;
        } catch (Exception e) {
            return false;
        }
    }

}

编写service层

package com.example.student.service;

import com.example.student.entity.ResultDO;
import com.example.student.entity.StudentDO;
import com.example.student.util.PageUtils;

import java.util.Map;

/**
 * 学生逻辑接口
 *
 * @author xiaotao
 */
public interface StudentInterService {

    /**
     * 获得所有学生信息
     *
     * @param params 过滤参数
     * @return 学生信息
     */
    ResultDO<PageUtils<StudentDO>> getStudent(Map<String, Object> params);

}

这里就不做参数检验了,放到控制层做检验。

package com.example.student.service.impl;

import com.example.student.constant.ResultCode;
import com.example.student.dao.StudentDAO;
import com.example.student.entity.ResultDO;
import com.example.student.entity.StudentDO;
import com.example.student.service.StudentInterService;
import com.example.student.util.PageUtils;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * 学生逻辑实现
 *
 * @author xiaotao
 */
@ComponentScan({"com.example.student.dao"})
@Service("studentService")
public class StudentServiceImpl implements StudentInterService {

    @Resource
    private StudentDAO studentDAO;

    @Override
    public ResultDO<PageUtils<StudentDO>> getStudent(Map<String, Object> params) {
        List<StudentDO> result = studentDAO.getStudent(params);
        if (result == null) {
            return new ResultDO<>(false, ResultCode.DB_ERROR, ResultCode.MSG_DB_ERROR, null);
        }

        return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, new PageUtils<>(studentDAO.count(params), result));
    }

}

编写rest数据接口

package com.example.student.controller.rest;

import com.example.student.entity.ResultDO;
import com.example.student.entity.StudentDO;
import com.example.student.util.PageUtils;

import java.util.Map;

/**
 * 学生数据接口
 *
 * @author xiaotao
 */
public interface StudentRestController {

    /**
     * 获得所有学生信息
     *
     * @param params 过滤参数
     * @return 学生信息
     */
    ResultDO<PageUtils<StudentDO>> getStudent(Map<String, Object> params);

}

代码挺简单的,要注意一下@RequestParam不要忘记了。

package com.example.student.controller.rest.impl;

import com.example.student.constant.ResultCode;
import com.example.student.controller.rest.StudentRestController;
import com.example.student.entity.ResultDO;
import com.example.student.entity.StudentDO;
import com.example.student.service.StudentInterService;
import com.example.student.util.PageUtils;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Map;

import static com.example.student.util.ParamUtils.validation;

/**
 * 学生数据接口实现
 *
 * @author xiaotao
 */
@RestController
@ComponentScan({"com.example.student.service"})
@RequestMapping("/student")
public class StudentRestControllerImpl implements StudentRestController {

    @Resource
    private StudentInterService studentService;

    @Override
    @GetMapping("getStudent")
    public ResultDO<PageUtils<StudentDO>> getStudent(@RequestParam Map<String, Object> params) {
        if (!validation(params)) {
            return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
        }

        return studentService.getStudent(params);
    }

}

编写js渲染代码

这里初始化表格里面field对应的是rest传过来的StudentDO的字段名字,title是前端显示的内容,width为列宽,可以用formatter给列添加样式(看性别那一列)。

<script>
    /** 初始化 */
    let $table = $('#table');

    changeToolTip();
    
    // 服务器分页获取数据
    function getServerPaging(node, url, queryParams) {
        initTable(node, url, [10, 25, 50, 100, "All"], queryParams, [{
            checkbox: true
        }, {
            field: 'name',
            title: '姓名',
            width: "170px",
            formatter: stringFormatter
        }, {
            field: 'age',
            title: '年龄',
            width: '70px',
            formatter: stringFormatter
        }, {
            field: 'sex',
            title: '性别',
            width: '70px',
            align: "center",
            formatter: value => null === value ? "" : "男" === value ? '<span title="男" class="label label-success"></span>' : '<span title="女" class="label label-warning"></span>'
        }, {
            field: 'createTime',
            title: '创建时间',
            width: "170px",
            formatter: dateFormatter
        }, {
            field: 'updateTime',
            title: '修改时间',
            width: "170px",
            formatter: dateFormatter
        }]);
    }

    function init() {
        getServerPaging($table, "/student/getStudent", params => {
            return { limit: params.limit, offset: params.offset, sort: "create_time", order: "DESC" };
        });
    }

    function filter() {

    }

    function insert() {

    }

</script>

运行了一下发现少了点字体文件
在这里插入图片描述
加上后的运行结果:
在这里插入图片描述

提示效果:
在这里插入图片描述
这里的两个数据是dao层测试的时候加上去的。。。

添加记录

编写service层

/**
 * 插入记录
 *
 * @param studentDO 学生实体
 * @return 是否成功
 */
ResultDO<Void> insert(StudentDO studentDO);
@Override
public ResultDO<Void> insert(StudentDO studentDO) {
    if (StringUtils.isBlank(studentDO.getName())) {
        return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
    }

    try {
        studentDAO.insert(studentDO);
    } catch (Exception e) {
        return new ResultDO<>(false, ResultCode.DB_ERROR, ResultCode.MSG_DB_ERROR, null);
    }

    return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, null);
}

编写rest数据接口

/**
 * 插入记录
 *
 * @param studentDO 学生实体
 * @return 是否成功
 */
ResultDO<Void> insert(StudentDO studentDO);
@Override
@PostMapping("insert")
public ResultDO<Void> insert(@RequestBody StudentDO studentDO) {
    if (StringUtils.isBlank(studentDO.getName())) {
        return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
    }

    return studentService.insert(studentDO);
}

编写js渲染代码

我们使用模态框输入信息,单击添加按钮当然就是打开模态框了。

<div id="toolbar" class="btn-group">
    <button id="btn_add" type="button" class="btn btn-default" data-toggle="modal" data-target="#addModal">
        <span class="glyphicon glyphicon-plus" aria-hidden="true"></span>添加学生
    </button>
</div>

模态框也很简单

<!-- 模态框(Modal) 新增 -->
<div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="addModalLabel" aria-hidden="true">
    <div class="modal-dialog" style="min-width: 800px">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="modal-title text-center" id="addModalLabel">
                    添加学生信息
                </h2>
            </div>
            <div class="modal-body">
                <form class="form-horizontal" role="form" onsubmit="return false;">

                    <div class="form-group has-success">
                        <label class="col-sm-2 control-label label-font" for="insert_input_name">姓名</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="insert_input_name" title="不能为空">
                        </div>
                    </div>

                    <div class="form-group has-success">
                        <label class="col-sm-2 control-label label-font" for="insert_input_age">年龄</label>
                        <div class="col-sm-10">
                            <input type="number" class="form-control" id="insert_input_age">
                        </div>
                    </div>

                    <div class="form-group has-success">
                        <label class="col-sm-2 control-label label-font" for="insert_input_sex">性别</label>
                        <div class="col-sm-10">
                            <select class="form-control" id="insert_input_sex">
                                <option value=""></option>
                                <option value=""></option>
                            </select>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-success" onclick="insert();">添加</button>
            </div>
        </div><!-- /.modal-content -->
    </div><!-- /.modal -->
</div>

添加函数里面简单的判断了一下输入的值的合法性,插入成功后刷新表格信息。

dragTheModalDialog();
function insert() {
    let data = {
        name: $('#insert_input_name').val(),
        age: $('#insert_input_age').val(),
        sex: $('#insert_input_sex').val()
    };
    if ("" === data.name) {
        swal("操作提示", "姓名不能为空", "info");
    } else{
        parameterPostRequest("/student/insert", data, () => {
            $('#addModal').modal('hide');
            swal("正确", "添加成功", "success");
            init();
        });
    }
}

运行效果:
在这里插入图片描述

查询

现在实现这个功能已经很简单了,后端已经建好了。
过滤是模糊查询,重置过滤可以说是重新初始化。

function filter() {
        let data = {
            name: $("#txt_search_name").val()
        };
        if ("" === data.name) {
            swal("操作提示", "请填写过滤参数", "info");
            return;
        }
        getServerPaging($table, "/student/getStudent", params => {
            return { limit: params.limit, offset: params.offset, sort: "create_time", order: "DESC", name: data.name};
        });
    }

运行效果:
在这里插入图片描述

删除

编写service层

/**
 * 删除
 *
 * @param id 记录id
 * @return 是否成功
 */
ResultDO<Void> delete(String id);
@Override
public ResultDO<Void> delete(String id) {
    if (StringUtils.isBlank(id)) {
        return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
    }

    try {
        studentDAO.delete(id);
    } catch (Exception e) {
        return new ResultDO<>(false, ResultCode.DB_ERROR, ResultCode.MSG_DB_ERROR, null);
    }

    return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, null);
}

编写rest数据接口

/**
 * 删除
 *
 * @param studentDO 学生实体
 * @return 是否成功
 */
ResultDO<Void> delete(StudentDO studentDO);
@Override
@PostMapping("delete")
public ResultDO<Void> delete(@RequestBody StudentDO studentDO) {
    if (StringUtils.isBlank(studentDO.getId())) {
        return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
    }

    return studentService.delete(studentDO.getId());
}

编写js渲染代码

这里我们稍微修改一下initTable里面的参数:
在这里插入图片描述

function operateFormatter(value, row, index) {  // 赋予的参数
    return [
        '<button class="btn btn-primary view" data-toggle="modal" data-target="#alterModal" οnclick="initUpdate('+ index +');">编辑</button>&nbsp;&nbsp;'+
        '<button class="btn btn-danger view"  οnclick="deleteOne('+ index +');">删除</button>'
    ].join('');
}

这里的$table.bootstrapTable('getData')可以获取到表格的所有数据,具体看官网。
删除成功了也还是刷新表格。

function deleteOne() {
    dialog("确定删除吗?", () => {
        let data = { id: $table.bootstrapTable('getData')[index].id };
        parameterPostRequest("/student/delete", data, () => {
            swal("正确", "删除成功", "success");
            init();
        });
    });
}

function initUpdate() {
        
}

运行效果:
在这里插入图片描述

修改

编写service层

/**
 * 修改实体
 *
 * @param studentDO 学生实体
 * @return 是否成功
 */
ResultDO<Void> update(StudentDO studentDO);
@Override
public ResultDO<Void> update(StudentDO studentDO) {
    if (StringUtils.isBlank(studentDO.getId()) || StringUtils.isBlank(studentDO.getName())) {
        return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
    }

    try {
        studentDAO.update(studentDO);
    } catch (Exception e) {
        return new ResultDO<>(false, ResultCode.DB_ERROR, ResultCode.MSG_DB_ERROR, null);
    }

    return new ResultDO<>(true, ResultCode.SUCCESS, ResultCode.MSG_SUCCESS, null);
}

编写rest数据接口

/**
 * 修改实体
 *
 * @param studentDO 学生实体
 * @return 是否成功
 */
ResultDO<Void> update(StudentDO studentDO);
@Override
@PostMapping("update")
public ResultDO<Void> update(@RequestBody StudentDO studentDO) {
    if (StringUtils.isBlank(studentDO.getId()) || StringUtils.isBlank(studentDO.getName())) {
        return new ResultDO<>(false, ResultCode.PARAMETER_INVALID, ResultCode.MSG_PARAMETER_INVALID, null);
    }

    return studentService.update(studentDO);
}

编写js渲染代码

编辑的模态框

<!--模态框(Modal) 编辑-->
<div class="modal fade" id="alterModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
    <div class="modal-dialog" style="min-width: 800px">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="modal-title text-center" id="alterModalLabel">
                    编辑学生信息
                </h2>
            </div>
            <div class="modal-body">
                <form class="form-horizontal" role="form" onsubmit="return false;">

                    <div class="form-group has-success">
                        <label class="col-sm-2 control-label label-font" for="alert_input_name">姓名</label>
                        <div class="col-sm-10">
                            <input type="text" class="form-control" id="alert_input_name" title="不能为空">
                        </div>
                    </div>

                    <div class="form-group has-success">
                        <label class="col-sm-2 control-label label-font" for="alert_input_age">年龄</label>
                        <div class="col-sm-10">
                            <input type="number" class="form-control" id="alert_input_age">
                        </div>
                    </div>

                    <div class="form-group has-success">
                        <label class="col-sm-2 control-label label-font" for="alert_input_sex">性别</label>
                        <div class="col-sm-10">
                            <select class="form-control" id="alert_input_sex">
                                <option value=""></option>
                                <option value=""></option>
                            </select>
                        </div>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-primary" onclick="alter()">编辑</button>
            </div>
        </div> <!--/.modal-content -->
    </div><!--/.modal-->
</div>
// alter记录id
let alterId;
function initUpdate(index) {
    let rows = $table.bootstrapTable('getData');
    $('#alert_input_name').val(rows[index].name);
    $('#alert_input_age').val(rows[index].age);
    $('#alert_input_sex').val(rows[index].sex);
    alterId = rows[index].id;
}

function alter() {
    let data = {
        id: alterId,
        name: $('#alert_input_name').val(),
        age: $('#alert_input_age').val(),
        sex: $('#alert_input_sex').val()
    };
    if ("" === data.id) {
        swal("操作提示", "用户不存在", "info");
    } else if ("" === data.name) {
        swal("操作提示", "姓名不能为空", "info");
    } else if (data.age <= 0 || data.age >= 200) {
        swal("操作提示", "年龄不合法", "info");
    } else {
        parameterPostRequest("/student/update", data, () => {
            $('#alterModal').modal('hide');
            swal("正确", "编辑成功", "success");
            init();
        });
    }
}

运行结果:在这里插入图片描述

百度云链接

项目代码 百度云链接:https://pan.baidu.com/s/1QoUR61paTpUBii5piBHCYw
提取码:xy7f

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值