【前端系列-2】layui+springboot实现表格增删改查

时间:2022-07-25
本文章向大家介绍【前端系列-2】layui+springboot实现表格增删改查,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

前言

本文将演示如何使用Springboot(后端框架)和layui(前端框架)将数据库中的数据渲染到前端页面,以及对前端页面的数据实现增删改。

效果图如下:

完整项目已上传至GitHub项目地址:https://github.com/ThinkMugz/mudemo

1 项目搭建

首先呢,把项目创建起来,后端项目结构就不说了,标准分层。然后,在resources目录下创建static文件夹,用来放置各种前端文件。

图中圈中的就是juqerylayui两个框架的源码文件,引入项目后,在我们自己写的js中引入相应的依赖,就可以使用大佬们提供的源码了。例如:

<!--引用 layui.css,注意路径要写自己项目的-->
<link rel="stylesheet" href="layui/css/layui.css" media="all"/>

<!--引用 layui.js和jQuery,注意路径要写自己项目的-->
<script src="layui/layui.js"></script>
<script src="js/libs/jquery-2.1.1.min.js"></script>

更详细内容请移步layui官网https://www.layui.com/doc/

数据库准备:

DROP TABLE IF EXISTS `goods`;
CREATE TABLE `goods` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `type` varchar(255) DEFAULT NULL,
  `price` decimal(10,0) DEFAULT NULL,
  `size` double DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  `description` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of goods
-- ----------------------------
INSERT INTO `goods` VALUES ('1', 'iPhone', '1', '6000', '55', '1', '说明');
INSERT INTO `goods` VALUES ('2', 'watch', '1', '500', '35', '1', '说明');
INSERT INTO `goods` VALUES ('3', 'television', '1', '1000', '90', '1', '说明');
INSERT INTO `goods` VALUES ('4', 'computer', '1', '4500', '60', '1', '说明');

1 渲染数据与刷新

首先呢,在页面放置一个元素 <table id="goods_table"></table>

<div style="margin: 5px 0 0 5px;width: 900px">
    <button class="layui-btn" id="queryGoods">查询商品</button>
    <table id="goods_table" lay-filter="goods_bar"></table>
</div>

表格有两个重要参数:idlay-filter

  • id:在后面渲染表格时,会以id作为纽带
  • lay-filter的值是表格头部工具按钮和行工具按钮监听事件的参数

然后通过 table.render() 方法指定该容器(可以看到elem通过id选择的方式绑定到了前面的table元素):

table.render({
      elem: '#goods_table'
    , id: 'goodsReload'
    , even: true //开启隔行背景
    , url: '/goods/goodsList'
    , request: {
        pageName: 'pageNum',
        limitName: 'pageSize'
    }
    , toolbar: '#goods_headerBar'
    , title:
        '商品详情表'
    , page:
        true //开启分页
      , limit: 5
      , limits: [1, 5, 10, 20, 50, 100]
      , cols:
          [[{field: 'id', title: '编号', width: 60, align: 'center'}
          , {field: 'type', title: '类&emsp;型', width: 76, align: 'center'}
          , {field: 'name', title: '商品名称', width: '8.5%', align: 'center'}
          , {field: 'price', title: '价&emsp;格', width: '9.1%', align: 'center'}
          , {field: 'size', title: '数&emsp;量', width: '9.5%', align: 'center'}
          , {field: 'status', title: '状&emsp;态', width: '7.5%', align: 'center'}
          , {field: 'description', title: '说&emsp;明', align: 'center'}
          , {
               fixed: 'right',
               title: '操作',
               toolbar: '#goods_lineBar',
               width: 160,
               align: 'center'
             }
          ]]
});

url这个参数非常关键,它的作用是:

接口地址。默认会自动传递两个参数:?page=1&limit=30(该参数可通过 request 自定义) page 代表当前页码、limit 代表每页数据量

我们看看,前端到底发送了什么请求,通过浏览器控制台看到:

Request URL: http://localhost:8086/goods/goodsList?pageNum=1&pageSize=5

那么后端返回给前端什么数据呢:

{
	"msg": "操作成功!",
	"code": "0",
	"data": [
		{
			"id": 1,
			"name": "iPhone",
			"type": "1",
			"price": 6000.0,
			"size": 55,
			"status": 1,
			"description": "说明"
		},
		{
			"id": 2,
			"name": "watch",
			"type": "1",
			"price": 500.0,
			"size": 35,
			"status": 1,
			"description": "说明"
		},
		{
			"id": 3,
			"name": "television",
			"type": "1",
			"price": 1000.0,
			"size": 90,
			"status": 1,
			"description": "说明"
		},
		{
			"id": 4,
			"name": "computer",
			"type": "1",
			"price": 4500.0,
			"size": 60,
			"status": 1,
			"description": "说明"
		}
	],
	"count": 4
}

那么后端是怎么从数据库获取数据,并将数据加工成前端要求的格式然后返给前端的呢?为了方便,我直接在controller中写逻辑了:

@RequestMapping(value = "/goodsList", method = RequestMethod.GET)
public JSONObject getGoodsList(@RequestParam("pageNum") int pageNum, @RequestParam("pageSize") int pageSize) {
    JSONObject result = new JSONObject();
    try {
        PageHelper.startPage(pageNum, pageSize);
        PageInfo<Good> pageInfo = new PageInfo(goodsMapper.getGoodsList());

        result.put("code", "0");
        result.put("msg", "操作成功!");
        result.put("data", pageInfo.getList());
        result.put("count", pageInfo.getTotal());
    } catch (Exception e) {
        result.put("code", "500");
        result.put("msg", "查询异常!");
    }
    return result;
}

goodsMapper.getGoodsList()呢,就是与数据库交互的方法了:

@Select("SELECT * FROM mutest.goods")
List<Good> getGoodsList();

经过PageHelper的分页处理,将前端传来的pageNumpageSize 织入sql语句中:

SELECT * FROM mutest.goods LIMIT 0,5

至此,渲染数据的前后端已经完成,那么刷新数据是怎么实现的呢?

首先,要页面放置头部工具按钮,包括新增和刷新:

<!--头部工具按钮-->
<script type="text/html" id="goods_headerBar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm" lay-event="add">
            <i class="layui-icon">&#xe608;</i> 新&emsp;增
        </button>
        <button class="layui-btn layui-btn-normal layui-btn-sm" lay-event="refresh" style=" margin-left: 15px">
            <i class="layui-icon">&#xe669;</i> 刷&emsp;新
        </button>
    </div>
</script>

然后,监听头部按钮点击事件:

// 监听头部工具栏
table.on('toolbar(goods_bar)', function (obj) {
    switch (obj.event) {
        case 'refresh':
        // 执行一个表格重载即实现刷新功能
             table.reload('goodsReload', {
                 where: '',
                 contentType: 'application/x-www-form-urlencoded',
                 page: {
                     curr: 1 //重新从第 1 页开始
                 },
                 url: '/goods/goodsList',
                 method: 'get'
             });
             break;
    }
});
<table id="goods_table" lay-filter="goods_bar"></table>

有这么几点需要强调一下:

  • toolbar是头部工具事件,与之对应的还有tool(行工具),后面括号中的goods_bar是与table元素的lay-filter的值对应起来的
  • table.reload('goodsReload'中的goodsReload是与table.render的id对应起来的,通过再次向特定url请求数据实现了表格的重载。

2 新增和编辑

新增和编辑在本文中,是使用弹层来实现的。思路是这样的:

  1. 首先,准备一个div元素,其display设置为none
  2. 通过新增和编辑按钮的点击事件触发弹出form,在form内填写好内容
  3. 通过点击弹层中的【提交】按钮,将form提交到后端对应的接口,从而实现后端数据的更新
  4. 提交完成后,ajax请求的success回调中添加表格重载,完成前端数据更新

2.1 弹层

弹层的div元素是这样的:

<div class="layui-row" id="open_div" style="display:none;">
    <form id="add_form" class="layui-form" action="" style="margin-top: 20px;align:center;">
        <!--隐藏字段action,用来区分增加和编辑行为-->
        <input type="hidden" name="action" id="action">
        <!--隐藏字段id,用于提供编辑需要的主键-->
        <input type="hidden" name="id" id="id">
        <!--隐藏字段request_type,用于提供请求方式:get,post,put-->
        <input type="hidden" name="request_type" id="request_type">

        <div class="layui-form-item" style="display: table;width: 96%">
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">类&emsp;&emsp;型</label>
                <div class="layui-input-block">
                    <select id="" name="type" lay-filter="type" lay-verify="required">
                        <option value="">请选择</option>
                        <option value="国产">国产</option>
                        <option value="进口">进口</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">产品名称</label>
                <div class="layui-input-block">
                    <input type="text" name="name" placeholder="请输入产品名称"
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
            </div>
        </div>

        <div class="layui-form-item" style="display: table;width: 96%">
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">价&emsp;&emsp;格</label>
                <div class="layui-input-block">
                    <input type="text" name="price" placeholder="请输入价格"
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
            </div>
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">数&emsp;&emsp;量</label>
                <div class="layui-input-block">
                    <input type="text" name="size" placeholder="请输入数量"
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
            </div>
        </div>

        <div class="layui-form-item" style="width: 96%">
            <label class="layui-form-label">说&emsp;&emsp;明</label>
            <div class="layui-input-block">
                <input type="text" name="description" placeholder="请输入产品说明"
                       autocomplete="off" class="layui-input" lay-verify="required">
            </div>
        </div>

        <div class="layui-form-item" style="margin-left: 40%">
            <div class="layui-btn-group">
                <button class="layui-btn" lay-submit="" lay-filter="update_submit">提&ensp;交</button>
                <button type="reset" class="layui-btn layui-btn-primary">重&ensp;置</button>
            </div>
        </div>
    </form>
</div>

接下来,我们看打开弹层时,做了什么?首先是【新增】事件:

// 监听头部工具栏
table.on('toolbar(goods_bar)', function (obj) {
    switch (obj.event) {
        // 根据增加行为给form隐藏项赋值
        case 'add':
            var data = {};
            data.action = 'addGood';
            data.request_type = 'post';
            // 调用打开弹层的工具方法
            open_form("#open_div", data, '添加商品', '620px', '282px');
            break;
    }
});

【编辑】事件:

table.on('tool(goods_bar)', function (obj) {
    var data = obj.data;
    var layEvent = obj.event;
    var id = data.id;

    switch (layEvent) {
        case 'edit':
            // 根据编辑行为为form隐藏项赋值
            data.action = 'updateGood';
            data.request_type = 'post';
            open_form("#open_div", data, '编辑用例', '620px', '282px');
            break; 
    }
});

仔细观察,div中有很多隐藏元素,之所以隐藏起来,是因为这些值必须要传递给后端,且不能被用户篡改,而是由程序赋值

  • id:就是你所操作的数据的主键,通过该值来告知后端,我要修改的是哪条数据。【新增】没有对id赋值,因为id设为自增字段,插库时无需传入id
  • action:区分新增和编辑的重要字段,【新增】赋值addGood,【编辑】赋值updateGood
  • request_type:区分get请求和post请求的字段,新增和编辑都赋值post

**open_formsetForm是两个工具方法,前者是打开弹层,后者是为form初始化(也是编辑弹窗会代入数据的实现方法),源码见 3.2 工具方法部分。

2.2 form submit

当打开弹层并填入内容后,当然是要提交了。通过监听form的提交按钮点击事件来实现表单提交:

form.on('submit(update_submit)', function (data) {
    var uri = data.field.action;
    var type = data.field.request_type;

    $.ajax({
         type: type,
         url: '/goods/' + uri,
         contentType: "application/json; charset=utf-8",
         data: JSON.stringify(data.field),
         dataType: "json",
         success: function (result) {
            if (result.code == "0") {
                table.reload('goodsReload', {
                    contentType: 'application/x-www-form-urlencoded',
                    page: {
                        curr: 1 //重新从第 1 页开始
                    },
                    url: '/goods/goodsList',
                    method: 'get'
                });
                layer.msg('修改成功', {icon: 1, time: 1000});
            } else {  //失败
                layer.alert(result.msg, {icon: 2}, function () {
                    layer.close(index);
                });
            }
        }
    });
    layer.close(index);//关闭弹出层
    return false;
});

【新增】和【编辑】使用的是同一套提交逻辑,而后端接口肯定不是同一个,所以action在打开弹层时被赋值,而提交时引用该值,从而指向了各自的后端接口。

后端接口:

// 新增接口
@RequestMapping(value = "/addGood", method = RequestMethod.POST)
public JSONObject addGood(@RequestBody JSONObject request) {
    JSONObject result = new JSONObject();
    try {
        goodsMapper.addGood(request);
        result.put("code", "0");
        result.put("msg", "操作成功!");
    } catch (Exception e) {
        result.put("code", "500");
        result.put("msg", "新增商品异常!");
    }
    return result;
}

// 编辑接口
@RequestMapping(value = "/updateGood", method = RequestMethod.POST)
public JSONObject updateGood(@RequestBody JSONObject request) {
    JSONObject result = new JSONObject();
    try {
        goodsMapper.updateGood(request);
        result.put("code", "0");
        result.put("msg", "操作成功!");
    } catch (Exception e) {
        result.put("code", "500");
        result.put("msg", "修改商品异常!");
        System.out.println(e.getMessage());
    }
    return result;
}

// 新增sql
@Insert("INSERT INTO mutest.goods(type,name,price,size,status,description)VALUES(#{type},#{name},#{price},#{size},#{status},#{description})")
int addGood(JSONObject request);

// 编辑sql
@Update("UPDATE mutest.goods SET type=#{type},name=#{name},price=#{price},size=#{size},status=#{status},description=#{description} WHERE id=#{id}")
void updateGood(JSONObject request);

3 完整代码

3.1 后端

pom.xml依赖

项目用到的完整的pom.xml依赖如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>mudemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>mudemo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <swagger.version>2.8.0</swagger.version>
        <google.guava>23.0</google.guava>
        <fastjson.version>1.2.47</fastjson.version>
        <druid.version>1.1.9</druid.version>
        <poi.version>3.17</poi.version>
        <jwt.version>0.9.0</jwt.version>
        <mybatis.version>1.3.2</mybatis.version>
    </properties>

    <dependencies>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>

        <!--连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>${druid.version}</version>
        </dependency>

		<!--mysql-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

		<!--data:省略set、get方法-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>

        <!--分页插件-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

实体类

package mudemo.model;

import lombok.Data;

/**
 * @author guozhengMu
 * @version 1.0
 * @date 2019/8/26 16:16
 * @description
 * @modify
 */
@Data
public class Good {
    private int id;
    private String name;
    private String type;
    private double price;
    private int size;
    private int status;
    private String description;
}

controller层

package mudemo.controller;

import com.alibaba.fastjson.JSONObject;
import mudemo.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @author guozhengMu
 * @version 1.0
 * @date 2019/8/26 16:51
 * @description
 * @modify
 */
@RestController
@RequestMapping(value = "/goods")
public class GoodsController {
    @Autowired
    private GoodsService goodsService;

    @RequestMapping(value = "/goodsList", method = RequestMethod.GET)
    public JSONObject getGoodsList(@RequestParam("pageNum") int pageNum, @RequestParam("pageSize") int pageSize) {
        return goodsService.getGoodsList(pageNum, pageSize);
    }

    @RequestMapping(value = "/updateGood", method = RequestMethod.POST)
    public JSONObject updateGood(@RequestBody JSONObject request) {
        return goodsService.updateGood(request);
    }

    @RequestMapping(value = "/addGood", method = RequestMethod.POST)
    public JSONObject addGood(@RequestBody JSONObject request) {
        return goodsService.addGood(request);
    }

    @RequestMapping(value = "/deleteGood", method = RequestMethod.GET)
    public JSONObject deleteGood(@RequestParam("id") int id) {
        return goodsService.deleteGood(id);
    }
}

接口层实现层

接口层省略,这里只贴上接口实现类:

package mudemo.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import mudemo.dao.GoodsMapper;
import mudemo.model.Good;
import mudemo.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author guozhengMu
 * @version 1.0
 * @date 2019/8/26 16:55
 * @description
 * @modify
 */
@Service(value = "GoodsService")
public class GoodsServiceImpl implements GoodsService {
    @Autowired
    private GoodsMapper goodsMapper;

    @Override
    public JSONObject getGoodsList(int pageNum, int pageSize) {
        JSONObject result = new JSONObject();
        try {
            PageHelper.startPage(pageNum, pageSize);
            PageInfo<Good> pageInfo = new PageInfo(goodsMapper.getGoodsList());

            result.put("code", "0");
            result.put("msg", "操作成功!");
            result.put("data", pageInfo.getList());
            result.put("count", pageInfo.getTotal());
        } catch (Exception e) {
            result.put("code", "500");
            result.put("msg", "查询异常!");
        }
        return result;
    }

    @Override
    public JSONObject addGood(JSONObject request) {
        JSONObject result = new JSONObject();
        try {
            goodsMapper.addGood(request);
            result.put("code", "0");
            result.put("msg", "操作成功!");
        } catch (Exception e) {
            result.put("code", "500");
            result.put("msg", "新增商品异常!");
        }
        return result;
    }

    @Override
    public JSONObject updateGood(JSONObject request) {
        JSONObject result = new JSONObject();
        try {
            goodsMapper.updateGood(request);
            result.put("code", "0");
            result.put("msg", "操作成功!");
        } catch (Exception e) {
            result.put("code", "500");
            result.put("msg", "修改商品异常!");
            System.out.println(e.getMessage());
        }
        return result;
    }

    @Override
    public JSONObject deleteGood(int id) {
        JSONObject result = new JSONObject();
        try {
            goodsMapper.deleteGood(id);
            result.put("code", "0");
            result.put("msg", "操作成功!");
        } catch (Exception e) {
            result.put("code", "500");
            result.put("msg", "删除商品异常!");
        }
        return result;
    }
}

dao层

package mudemo.dao;

import com.alibaba.fastjson.JSONObject;
import mudemo.model.Good;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface GoodsMapper {
    @Select("SELECT * FROM mutest.goods")
    List<Good> getGoodsList();

    @Insert("INSERT INTO mutest.goods(type,name,price,size,status,description)VALUES(#{type},#{name},#{price},#{size},#{status},#{description})")
    int addGood(JSONObject request);

    @Update("UPDATE mutest.goods SET type=#{type},name=#{name},price=#{price},size=#{size},status=#{status},description=#{description} WHERE id=#{id}")
    void updateGood(JSONObject request);

    @Delete("DELETE FROM mutest.goods WHERE id=#{id}")
    void deleteGood(@Param("id") int id);
}

3.2 前端

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>商品信息</title>
    <!--根据自己的项目目录修改-->
    <link rel="stylesheet" href="layui/css/layui.css" media="all"/>
</head>
<body>
<table id="goods_table" lay-filter="goods_bar"></table>
<div class="layui-row" id="open_div" style="display:none;">
    <form id="add_form" class="layui-form" action="" style="margin-top: 20px;align:center;">
        <!--隐藏字段action,用来区分增加和编辑行为-->
        <input type="hidden" name="action" id="action">
        <!--隐藏字段id,用于提供编辑需要的主键-->
        <input type="hidden" name="id" id="id">
        <!--隐藏字段request_type,用于提供请求方式:get,post,put-->
        <input type="hidden" name="request_type" id="request_type">

        <div class="layui-form-item" style="display: table;width: 96%">
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">类&emsp;&emsp;型</label>
                <div class="layui-input-block">
                    <select id="" name="type" lay-filter="type" lay-verify="required">
                        <option value="">请选择</option>
                        <option value="国产">国产</option>
                        <option value="进口">进口</option>
                    </select>
                </div>
            </div>
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">产品名称</label>
                <div class="layui-input-block">
                    <input type="text" name="name" placeholder="请输入产品名称"
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
            </div>
        </div>

        <div class="layui-form-item" style="display: table;width: 96%">
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">价&emsp;&emsp;格</label>
                <div class="layui-input-block">
                    <input type="text" name="price" placeholder="请输入价格"
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
            </div>
            <div class="layui-form-item" style="display: table-cell;width: 50%">
                <label class="layui-form-label">数&emsp;&emsp;量</label>
                <div class="layui-input-block">
                    <input type="text" name="size" placeholder="请输入数量"
                           autocomplete="off" class="layui-input" lay-verify="required">
                </div>
            </div>
        </div>

        <div class="layui-form-item" style="width: 96%">
            <label class="layui-form-label">说&emsp;&emsp;明</label>
            <div class="layui-input-block">
                <input type="text" name="description" placeholder="请输入产品说明"
                       autocomplete="off" class="layui-input" lay-verify="required">
            </div>
        </div>

        <div class="layui-form-item" style="margin-left: 40%">
            <div class="layui-btn-group">
                <button class="layui-btn" lay-submit="" lay-filter="update_submit">提&ensp;交</button>
                <button type="reset" class="layui-btn layui-btn-primary">重&ensp;置</button>
            </div>
        </div>
    </form>
</div>

<script src="layui/layui.js"></script>
<script src="js/libs/jquery-2.1.1.min.js"></script>
<script src="utils/common.js"></script>

<!--头部工具按钮-->
<script type="text/html" id="goods_headerBar">
    <div class="layui-btn-container">
        <button class="layui-btn layui-btn-sm" lay-event="add">
            <i class="layui-icon">&#xe608;</i> 新&emsp;增
        </button>
        <button class="layui-btn layui-btn-normal layui-btn-sm" lay-event="refresh" style=" margin-left: 15px">
            <i class="layui-icon">&#xe669;</i> 刷&emsp;新
        </button>
    </div>
</script>

<!--行工具按钮-->
<script type="text/html" id="goods_lineBar">
    <a class="layui-btn layui-btn-xs layui-btn-warm" lay-event="edit">编辑</a>
    <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="del">删除</a>
</script>

<script>
    layui.use(['table', 'layer', 'form', 'laypage'], function () {
        var table = layui.table;
        var form = layui.form;

        table.render({
            elem: '#goods_table'
            , id: 'goodsReload'
            , even: true //开启隔行背景
            , url: '/goods/goodsList'
            , request: {
                pageName: 'pageNum',
                limitName: 'pageSize'
            }
            , toolbar: '#goods_headerBar'
            , title:
                '商品详情表'
            , page:
                true //开启分页
            , limit: 5
            , limits: [1, 5, 10, 20, 50, 100]
            , cols:
                [[{field: 'id', title: '编号', width: 60, align: 'center'}
                    , {field: 'type', title: '类&emsp;型', width: 76, align: 'center'}
                    , {field: 'name', title: '商品名称', width: '8.5%', align: 'center'}
                    , {field: 'price', title: '价&emsp;格', width: '9.1%', align: 'center'}
                    , {field: 'size', title: '数&emsp;量', width: '9.5%', align: 'center'}
                    , {field: 'status', title: '状&emsp;态', width: '7.5%', align: 'center'}
                    , {field: 'description', title: '说&emsp;明', align: 'center'}
                    , {
                        fixed: 'right',
                        title: '操作',
                        toolbar: '#goods_lineBar',
                        width: 160,
                        align: 'center'
                    }
                ]]
        });

        // 监听头部工具栏
        table.on('toolbar(goods_bar)', function (obj) {
            switch (obj.event) {
                // 根据增加行为给form隐藏项赋值
                case 'add':
                    var data = {};
                    data.action = 'addGood';
                    data.request_type = 'post';
                    // 调用打开弹层的工具方法
                    open_form("#open_div", data, '添加商品', '620px', '282px');
                    break;
                case 'refresh':
                    // 执行一个表格重载即实现刷新功能
                    table.reload('goodsReload', {
                        where: '',
                        contentType: 'application/x-www-form-urlencoded',
                        page: {
                            curr: 1 //重新从第 1 页开始
                        },
                        url: '/goods/goodsList',
                        method: 'get'
                    });
                    break;
            }
        });

        table.on('tool(goods_bar)', function (obj) {
            var data = obj.data;
            var layEvent = obj.event;
            var id = data.id;

            switch (layEvent) {
                case 'edit':
                    // 根据编辑行为为form隐藏项赋值
                    data.action = 'updateGood';
                    data.request_type = 'post';
                    open_form("#open_div", data, '编辑用例', '620px', '282px');
                    break;
                case 'del':
                    layer.confirm('真的删除该行么', function (index) {
                        obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
                        //向服务端发送删除指令
                        $.ajax({
                            type: "get",  //数据提交方式(post/get)
                            url: "/goods/deleteGood?id=" + id,  //提交到的url
                            contentType: "application/json; charset=utf-8",
                            dataType: "json",//返回的数据类型格式
                            success: function (result) {
                                layer.msg(result.msg, {icon: 1, time: 1000});
                            }, error: function (e) {
                                console.log(e, 'error');
                                layer.msg("查询商品异常,请联系管理员!", {icon: 1, time: 1000});
                            }
                        });
                        layer.close(index);
                    });
                    break;
            }
        });

        form.on('submit(update_submit)', function (data) {
            var uri = data.field.action;
            var type = data.field.request_type;

            $.ajax({
                type: type,
                url: '/goods/' + uri,
                contentType: "application/json; charset=utf-8",
                data: JSON.stringify(data.field),
                dataType: "json",
                success: function (result) {
                    if (result.code == "0") {
                        table.reload('goodsReload', {
                            contentType: 'application/x-www-form-urlencoded',
                            page: {
                                curr: 1 //重新从第 1 页开始
                            },
                            url: '/goods/goodsList',
                            method: 'get'
                        });
                        layer.msg('修改成功', {icon: 1, time: 1000});
                    } else {  //失败
                        layer.alert(result.msg, {icon: 2}, function () {
                            layer.close(index);
                        });
                    }
                }
            });
            layer.close(index);//关闭弹出层
            return false;
        });
    });
</script>
</body>
</html>

工具方法

var index;

function open_form(element, data, title, width, height) {
    if (title == null || title == '') {
        title = false;
    }
    if (width == null || width == '') {
        width = '100%';
    }
    if (height == null || height == '') {
        height = '100%';
    }

    index = layer.open({
        type: 1,
        title: title,
        area: [width, height],
        fix: false, //不固定
        maxmin: true,//开启最大化最小化按钮
        shadeClose: true,//点击阴影处可关闭
        shade: 0.4,//背景灰度
        // skin: 'layui-layer-rim', //加上边框
        content: $(element),
        success: function () {
            $(element).setForm(data);
            layui.form.render();  // 下拉框赋值
        }
    });
}

$.fn.setForm = function (jsonValue) {
    var obj = this;
    $.each(jsonValue, function (name, ival) {
        var $oinput = obj.find("input[name=" + name + "]");
        if ($oinput.attr("type") === "checkbox") {
            if (ival !== null) {
                var checkboxObj = $("[name=" + name + "]");
                var checkArray = ival.split(";");
                for (var i = 0; i < checkboxObj.length; i++) {
                    for (var j = 0; j < checkArray.length; j++) {
                        if (checkboxObj[i].value === checkArray[j]) {
                            checkboxObj[i].click();
                        }
                    }
                }
            }
        } else if ($oinput.attr("type") === "radio") {
            $oinput.each(function () {
                var radioObj = $("[name=" + name + "]");
                for (var i = 0; i < radioObj.length; i++) {
                    if (radioObj[i].value == ival) {
                        radioObj[i].click();
                    }
                }
            });
        } else if ($oinput.attr("type") === "textarea") {
            obj.find("[name=" + name + "]").html(ival);
        } else {
            obj.find("[name=" + name + "]").val(ival);
        }
    })
};