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

以下是一个使用Bootstrap项目实例: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/css/bootstrap.min.css"> <title>Bootstrap Project</title> </head> <body> <nav class="navbar navbar-expand-lg navbar-light bg-light"> <a class="navbar-brand" href="#">My Website</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarNav"> <ul class="navbar-nav"> <li class="nav-item active"> <a class="nav-link" href="#">Home</a> </li> <li class="nav-item"> <a class="nav-link" href="#">About</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Services</a> </li> <li class="nav-item"> <a class="nav-link" href="#">Contact</a> </li> </ul> </div> </nav> <div class="jumbotron"> <h1 class="display-4">Welcome to My Website</h1> <p class="lead">This is a simple Bootstrap project.</p> <hr class="my-4"> <p>It uses Bootstrap to create a responsive and modern website.</p> <a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a> </div> <div class="container"> <div class="row"> <div class="col-md-6"> <h2>About</h2> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam auctor, nunc id aliquet tincidunt, nisl nunc tincidunt nunc, id lacinia nunc nunc id nunc. Sed euismod, nunc id aliquet tincidunt, nisl nunc tincidunt nunc, id lacinia nunc nunc id nunc.</p> </div> <div class="col-md-6"> <h2>Services</h2> <ul> <li>Web Design</li> <li>Graphic Design</li> <li>SEO</li> </ul> </div> </div> </div> <footer class="bg-light text-center py-3"> <p>© 2020 My Website. All rights reserved.</p> </footer> <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.2/dist/js/bootstrap.min.js"></script> </body> </html> ``` 这个项目实例包括了一个导航栏、一个Jumbotron(大标题)、关于和服务的内容区块以及页脚。它使用了Bootstrap的CSS和JavaScript库来实现响应式和现代化的网站。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值