接着上期内容:秒杀项目之用户验证_爱嘤斯塔的博客-CSDN博客
一、框架搭建
1、页面跳转方法
login.js文件:
success(e){
// 成功的回调函数
layer.msg(e.message,{icon: 6},()=>{
if(e.code===200){
location.href="goods/goodsList"
}
});
}
2、进入layui网站,设置首页的样式
新建goodsList.js文件,暂未写内容
goodsList.ftl:
<!DOCTYPE html>
<html lang="en">
<head>
<#include "../common/head.ftl">
<style>
.layui-this{
background: deepskyblue !important;
}
</style>
</head>
<body class="layui-container layui-bg-orange">
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">普通商品</li>
<li>秒杀商品</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<table id="normal_goods" lay-filter="normal_goods"></table>
</div>
<div class="layui-tab-item">内容2</div>
</div>
</div>
<#--引入js-->
<script src="/static/asset/js/project/goodsList.js"></script>
</body>
</html>
呈现出的界面:
3、后台生成器生成goods数据
在goodsMapper中加入注解
@Repository
4、PageBean
package com.example.seckill.util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean {
private int total;
private int page = 1;
private int rows = 5;
private boolean pagination = true;
private String url;
private Map<String, String[]> ms;
public void setMs(Map<String, String[]> ms) {
this.ms = ms;
}
public int calcStartIndex() {
return (page - 1) * rows;
}
public int calcMaxPage() {
return total % rows == 0 ? total / rows : total / rows + 1;
}
public int nextPage() {
return Math.min(page + 1, calcMaxPage());
}
public int prevPage() {
return Math.max(page - 1, 1);
}
public void setRequest(HttpServletRequest req) {
setUrl(req.getRequestURL().toString());
setMs(req.getParameterMap());
String page = req.getParameter("page");
if (page == null) {
setPage(1);
} else {
setPage(Integer.parseInt(page));
}
String rows = req.getParameter("rows");
if (rows == null) {
setRows(5);
} else {
setRows(Integer.parseInt(rows));
}
String pagination = req.getParameter("pagination");
if ("false".equals(pagination)) {
setPagination(false);
}
}
}
5、Mybatis Plus02中的分页配置
MybatisPlusConfig :
package com.example.seckill.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 加入分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
return interceptor;
}
}
6、编写得到数据方法
IGoodsService:
package com.example.seckill.service;
import com.example.seckill.pojo.Goods;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.seckill.util.PageBean;
import com.example.seckill.util.response.ResponseResult;
import java.util.List;
/**
* <p>
* 商品信息表 服务类
* </p>
*
* @author lv
* @since 2022-03-17
*/
public interface IGoodsService extends IService<Goods> {
ResponseResult<List<Goods>> getGoodsList(Goods goods, PageBean pageBean);
}
GoodsServiceImpl :
package com.example.seckill.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.example.seckill.pojo.Goods;
import com.example.seckill.mapper.GoodsMapper;
import com.example.seckill.service.IGoodsService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.seckill.util.PageBean;
import com.example.seckill.util.response.ResponseResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 商品信息表 服务实现类
* </p>
*
* @author lv
* @since 2022-03-17
*/
@Service
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements IGoodsService {
@Autowired
GoodsMapper goodsMapper;
@Override
public ResponseResult<List<Goods>> getGoodsList(Goods goods, PageBean pageBean) {
// 分页
Page<Goods> page=PageDTO.of(pageBean.getPage(),pageBean.getRows());
// 模糊查询+条件
QueryWrapper<Goods> wrapper=new QueryWrapper<>();
if(StringUtils.isNotEmpty(goods.getGoodsName())){
wrapper.like("goods_name","%"+goods.getGoodsName()+"%");
}
// 进数据库查出结果
Page<Goods> result=goodsMapper.selectPage(page,wrapper);
return ResponseResult.success(result.getRecords(),page.getTotal());
}
}
GoodsController :
package com.example.seckill.controller;
import com.example.seckill.pojo.Goods;
import com.example.seckill.service.IGoodsService;
import com.example.seckill.util.PageBean;
import com.example.seckill.util.response.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* <p>
* 商品信息表 前端控制器
* </p>
*
* @author lv
* @since 2022-03-17
*/
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private IGoodsService goodsService;
@RequestMapping("/queryAll")
public ResponseResult<List<Goods>> getGoodsList(Goods goods, HttpServletRequest request){
PageBean pageBean=new PageBean();
pageBean.setRequest(request);
return goodsService.getGoodsList(goods,pageBean);
}
}
后端查看数据成功:
7、将图片放到static包中
8、前端得到数据
let layer
layui.define(()=>{
let table=layui.table
layer=layui.layer
table.render({
elem: '#normal_goods'
,height: 500
,url: '/goods/queryAll' //数据接口
,page: true //开启分页
,parseData(res){ //res 即为原始返回的数据
return {
"code": res.code===200?0:1, //解析接口状态
"msg": res.message, //解析提示文本
"count": res.total, //解析数据长度
"data": res.data //解析数据列表
};
}
,cols: [[ //表头
{field: 'gid', title: '商品编号', width:80, sort: true, fixed: 'left'}
,{field: 'goodsName', title: '商品名字'}
,{field: 'goodsTitle', title: '商品标题'}
,{field: 'goodsImg',
title: '商品图片',
width:200,
templet: (goods) => `<b onmouseover='showImg("${goods.goodsImg}",this)'>` + goods.goodsImg + `</b>` }
,{field: 'goodsDetail', title: '商品详情'}
,{field: 'goodsPrice', title: '商品价格', sort: true}
,{field: 'goodsStock', title: '商品库存', sort: true}
]]
});
})
let showImg = (src,obj)=> {
layer.tips(`<img src="${src}" width="100px">`, obj);
}
9、呈现界面
二、搜索功能
1、添加搜索界面
goodsList.ftl:
<div class="layui-form-item">
<label class="layui-form-label">搜索栏</label>
<div class="layui-input-inline">
<input type="text" id="normal_name" name="text" placeholder="请输入搜索内容" class="layui-input">
</div>
<div class="layui-input-inline">
<button class="layui-btn layui-btn-primary" id="normal_search">🔍</button>
<button class="layui-btn layui-btn-primary" id="normal_add">增加</button>
</div>
</div>
<!DOCTYPE html>
<html lang="en">
<head>
<#include "../common/head.ftl">
<style>
.layui-this{
background: deepskyblue !important;
}
</style>
</head>
<body class="layui-container layui-bg-orange">
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">普通商品</li>
<li>秒杀商品</li>
</ul>
<div class="layui-tab-content">
<div class="layui-tab-item layui-show">
<div class="layui-form-item">
<label class="layui-form-label">搜索栏</label>
<div class="layui-input-inline">
<input type="text" id="normal_name" name="text" placeholder="请输入搜索内容" class="layui-input">
</div>
<div class="layui-input-inline">
<button class="layui-btn layui-btn-primary" id="normal_search">🔍</button>
<button class="layui-btn layui-btn-primary" id="normal_add">增加</button>
</div>
</div>
<table id="normal_goods" lay-filter="normal_goods"></table>
</div>
<div class="layui-tab-item">内容2</div>
</div>
</div>
<#--引入js-->
<script src="/static/asset/js/project/goodsList.js"></script>
</body>
</html>
2、js实现搜索功能
goodsList.js:
page、limit重新设定名称,否则无法根据选择展示的几条数据而更改,如无法显示20条每页
let $=layui.jquery
//用于对分页请求的参数:page、limit重新设定名称
request: {
pageName: 'page' //页码的参数名称,默认:page
,limitName: 'rows' //每页数据量的参数名,默认:limit
}
$("#normal_search").click(()=>{
let goodsName=$("#normal_name").val()
// 【JS】自动化渲染的重载,重载表格
normal_table.reload({
where: {
//设定异步数据接口的额外参数,height: 300
goodsName
},
page:{
curr:1 //current
}
});
})
let layer
layui.define(()=>{
let table=layui.table
layer=layui.layer
let $=layui.jquery
let normal_table=table.render({
elem: '#normal_goods'
,height: 500
,url: '/goods/queryAll' //数据接口
,page: true //开启分页
,parseData(res){ //res 即为原始返回的数据
return {
"code": res.code===200?0:1, //解析接口状态
"msg": res.message, //解析提示文本
"count": res.total, //解析数据长度
"data": res.data //解析数据列表
};
},
//用于对分页请求的参数:page、limit重新设定名称
request: {
pageName: 'page' //页码的参数名称,默认:page
,limitName: 'rows' //每页数据量的参数名,默认:limit
}
,cols: [[ //表头
{field: 'gid', title: '商品编号', width:80, sort: true, fixed: 'left'}
,{field: 'goodsName', title: '商品名字'}
,{field: 'goodsTitle', title: '商品标题'}
,{field: 'goodsImg',
title: '商品图片',
width:200,
templet: (goods) => `<b onmouseover='showImg("${goods.goodsImg}",this)'>` + goods.goodsImg + `</b>` }
,{field: 'goodsDetail', title: '商品详情'}
,{field: 'goodsPrice', title: '商品价格', sort: true}
,{field: 'goodsStock', title: '商品库存', sort: true}
]]
});
$("#normal_search").click(()=>{
let goodsName=$("#normal_name").val()
// 【JS】自动化渲染的重载,重载表格
normal_table.reload({
where: {
//设定异步数据接口的额外参数,height: 300
goodsName
},
page:{
curr:1 //current
}
});
})
})
let showImg = (src,obj)=> {
layer.tips(`<img src="${src}" width="100px">`, obj);
}
三、商品的操作
1、给表格增加操作列
goodsList.ftl:放到表单后
<script type="text/html" id="button_1">
<a class="layui-btn layui-btn-xs" lay-event="normal_del">删除</a>
<a class="layui-btn layui-btn-xs" lay-event="normal_edit">编辑</a>
</script>
goodsList.js:
{field: 'operate', title: '商品操作',toolbar: '#button_1'}
2、弹出框界面
goodsOperate.js:编辑框读取数据
let form, $
layui.define(() => {
form = layui.form
$ = layui.jquery
loadFormData()
})
// 子界面引用父界面使用parent
function loadFormData() {
if (parent.row) {
form.val('goods_operate', $.extend({}, parent.row || {}));
}
}
/*
将表单的对象转成一个值,丢出去
父界面想使用子界面直接调用getFormData方法即可
*/
function getFormData() {
return form.val("goods_operate")
}
goodsOperate.ftl:
<!DOCTYPE html>
<html lang="zh">
<head>
<link rel="stylesheet" href="/static/asset/js/layui/css/layui.css" media="all">
<script src="/static/asset/js/layui/layui.js" charset="utf-8"></script>
</head>
<body>
<div>
<div class="layui-container" style="padding-top: 20px">
<form class="layui-form layui-form-pane" lay-filter="goods_operate">
<input type="hidden" name="gid"/>
<div class="layui-form-item">
<label class="layui-form-label">商品名称</label>
<div class="layui-input-block">
<input type="text" name="goodsName" placeholder="请输入标题" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品标题</label>
<div class="layui-input-block">
<input type="text" name="goodsTitle" placeholder="请输入" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品图片</label>
<div class="layui-input-block">
<select name="goodsImg">
<option value="">---请选择---</option>
<option value="/static/images/a.png">小米10</option>
<option value="/static/images/b.png">小米11</option>
<option value="/static/images/c.png">红米pro</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品价格</label>
<div class="layui-input-block">
<input type="text" name="goodsPrice" placeholder="请输入价格" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">商品库存</label>
<div class="layui-input-block">
<input type="text" name="goodsStock" placeholder="请输入库存" class="layui-input">
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">商品描述</label>
<div class="layui-input-block">
<textarea name="goodsDetail" placeholder="请输入内容" class="layui-textarea"></textarea>
</div>
</div>
</form>
</div>
</div>
<script src="/static/asset/js/project/goodsOperate.js"></script>
</body>
</html>
3、后端增加、删除、修改方法
IGoodsService:
ResponseResult<?> goodsInsert(Goods goods);
ResponseResult<?> goodsEdit(Goods goods);
ResponseResult<?> deleteGoodsById(Long goodsId);
GoodsServiceImpl:
@Override
public ResponseResult<?> goodsInsert(Goods goods) {
boolean b=this.save(goods);
if(b){
return ResponseResult.success();
}
return ResponseResult.failure(ResponseResultCode.GOODS_ADD_ERROR);
}
@Override
public ResponseResult<?> goodsEdit(Goods goods) {
boolean b=this.updateById(goods);
if(b){
return ResponseResult.success();
}
return ResponseResult.failure(ResponseResultCode.GOODS_EDIT_ERROR);
}
@Override
public ResponseResult<?> deleteGoodsById(Long goodsId) {
boolean b = this.removeById(goodsId);
if (b) {
return ResponseResult.success();
}
return ResponseResult.failure(ResponseResultCode.UNKNOWN);
}
GoodsController:
@RequestMapping("/insert")
public ResponseResult<?> goodsInsert(Goods goods){
return goodsService.goodsInsert(goods);
}
@RequestMapping("/edit")
public ResponseResult<?> goodsEdit(Goods goods){
return goodsService.goodsEdit(goods);
}
@RequestMapping("/del/{gid}")
public ResponseResult<?> deleteGoodsById(@PathVariable("gid") Long gid) {
return goodsService.deleteGoodsById(gid);
}
4、实现增加、删除、修改方法
goodList.js
let layer
var row
layui.define(()=>{
let table=layui.table
layer=layui.layer
let $=layui.jquery
let normal_table=table.render({
elem: '#normal_goods'
,height: 500
,url: '/goods/queryAll' //数据接口
,page: true //开启分页
,parseData(res){ //res 即为原始返回的数据
return {
"code": res.code===200?0:1, //解析接口状态
"msg": res.message, //解析提示文本
"count": res.total, //解析数据长度
"data": res.data //解析数据列表
};
},
//用于对分页请求的参数:page、limit重新设定名称
request: {
pageName: 'page' //页码的参数名称,默认:page
,limitName: 'rows' //每页数据量的参数名,默认:limit
}
,cols: [[ //表头
{field: 'gid', title: '商品编号', width:80, sort: true, fixed: 'left'}
,{field: 'goodsName', title: '商品名字'}
,{field: 'goodsTitle', title: '商品标题'}
,{field: 'goodsImg',
title: '商品图片',
width:200,
templet: (goods) => `<b onmouseover='showImg("${goods.goodsImg}",this)'>` + goods.goodsImg + `</b>` }
,{field: 'goodsDetail', title: '商品详情'}
,{field: 'goodsPrice', title: '商品价格', sort: true}
,{field: 'goodsStock', title: '商品库存', sort: true}
,{field: 'operate', title: '商品操作',toolbar: '#button_1'}
]]
});
// 刷新表格
let reloadTable=()=>{
let goodsName=$("#normal_value").val()
// 【JS】自动化渲染的重载,重载表格
normal_table.reload({
where: {
//设定异步数据接口的额外参数,height: 300
goodsName
},
page:{
curr:1 //current
}
});
}
// 搜索
$("#normal_search").click(reloadTable)
// 增加
$("#normal_add").click(()=>{
row = null
openDialog()
})
//工具条事件
table.on('tool(normal_goods)', function(obj) { //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值"
let data = obj.data; //获得当前行数据
let layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
let tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)
if (layEvent === 'normal_del') { //删除
row = data//获得当前行的数据
let url="/goods/del/"+data.gid
layer.confirm('确定删除吗?',{title:'删除'}, function(index){
//向服务端发送删除指令og
$.getJSON(url,{gid:data.gid}, function(ret){
layer.close(index);//关闭弹窗
reloadTable()
});
layer.close(index);//关闭弹窗
});
}
if (layEvent === 'normal_edit') { //编辑
row = data
openDialog()
}
})
// 页面弹出
let openDialog=()=>{
// 如果是iframe层
layer.open({
type: 2,
content: '/goods/goodsOperate', //这里content是一个URL,如果你不想让iframe出现滚动条,你还可以content: ['http://sentsin.com', 'no']
area:['800px','600px'],
btn: ['确定','取消'],
yes(index,layero){
let url="/goods/insert"
// 拿到表格数据
let data=$(layero).find("iframe")[0].contentWindow.getFormData()
if(row) {
url="/goods/edit"
}
$.ajax({
url,
data,
datatype: "json",
success(res){
layer.closeAll()
reloadTable()
layer.msg(res.message)
}
})
}
});
}
})
// 图片显示
let showImg = (src,obj)=> {
layer.tips(`<img src="${src}" width="100px">`, obj);
}
5、展示结果
增加:
编辑:
删除: