这里写目录标题
创建项目:删除一些不需要的文件。
pom依赖:注意,使用thyleaf注意要引入依赖的。
<dependencies>
<!--spring-web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.5.0</version>
</dependency>
<!--devtools-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!--mysql-connector-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--mybatis-plus-generator-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--模板引擎freemarker 依赖-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
<!--processor-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置文件的编写:
创建一个application.yml文件:
部分配置如下:
#服务器的配置
server:
port: 9000
servlet:
context-path: /book
#数据库的配置
spring:
#jdbc配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver #com.mysql.cj.jdbc.Driver
username: root
password: root
#jdbc:mysql://localhost:3306/test?allowMultiQueries=true&useSSL=false&serverTimezone=UTC
url: jdbc:mysql://localhost:3306/test?allowMultiQueries=true&useSSL=false&serverTimezone=UTC
#mybatis-plus配置
mybatis-plus:
mapper-locations: classpath*:mapper/*.xml #映射文件的位置
#在Mybatis的mapper.xml文件中resultType的type或者paramterType会返回自定义entity,
#此时可以用全类名名来指定这些实体。可以使用type-aliases-package中指定entity扫描包类让mybatis自定扫描到自定义的entity。
type-aliases-package: com.fan.bookshop.entity #设置封装实体类类的别名,批量设置别名扫描,多个package用逗号隔开
global-config:
db-config:
id-type: auto #主键策略,mysql是采取自增的
logic-delete-field: deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2,步骤2: 实体类字段上加上@TableLogic注解)
logic-delete-value: 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
configuration:
map-underscore-to-camel-case: true #开启驼峰命名,可以不用配置,默认就是配置了true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #控制台输出sql语句的日志
使用代码生成器生成三层架构的包:自己先不要写认个的包;
注意修改第一行的包名:package com.fan.bookshop.generator;以及导入一个生成器的依赖:
<!--mybatis-plus-generator-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--模板引擎 依赖-->
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
</dependency>
package com.fan.bookshop.generator;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class CodeGenerator {
/**
* <p>
* 读取控制台内容
* </p>
*/
public static String scanner(String tip) {
Scanner scanner = new Scanner(System.in);
StringBuilder help = new StringBuilder();
help.append("请输入" + tip + ":");
System.out.println(help.toString());
if (scanner.hasNext()) {
String ipt = scanner.next();
if (StringUtils.isNotBlank(ipt)) {
return ipt;
}
}
throw new MybatisPlusException("请输入正确的" + tip + "!");
}
public static void main(String[] args) {
// 代码生成器
AutoGenerator mpg = new AutoGenerator();
// 全局配置
GlobalConfig gc = new GlobalConfig();
//获取用户的目录
final String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath + "/src/main/java");//这里不用修改
gc.setAuthor("fan");
gc.setBaseResultMap(true);
gc.setBaseColumnList(true);
// 是否打开输出目录 默认为true
gc.setOpen(false);
mpg.setGlobalConfig(gc);
// 数据源配置
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/test?allowMultiQueries=true&useSSL=false&serverTimezone=UTC");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("root");
mpg.setDataSource(dsc);
// 包配置
final PackageConfig pc = new PackageConfig();
// pc.setModuleName(scanner("模块名"));
pc.setParent("com.fan");//这里需要修改成自己的模块名称
pc.setEntity("entity");//设置实体类包
/* pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");*/
mpg.setPackageInfo(pc);
// 自定义配置
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// to do nothing
}
};
// 如果模板引擎是 freemarker
String templatePath = "/templates/mapper.xml.ftl";
// 如果模板引擎是 velocity
// String templatePath = "/templates/mapper.xml.vm";
// 自定义输出配置
List<FileOutConfig> focList = new ArrayList<FileOutConfig>();
// 自定义配置会被优先输出
focList.add(new FileOutConfig(templatePath) {
@Override
public String outputFile(TableInfo tableInfo) {
// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
return projectPath + "/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 配置模板
TemplateConfig templateConfig = new TemplateConfig();
// 配置自定义输出模板
// 指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
// templateConfig.setEntity("templates/entity2.java");
// templateConfig.setService();
// templateConfig.setController();
templateConfig.setXml(null);
mpg.setTemplate(templateConfig);
// 策略配置
StrategyConfig strategy = new StrategyConfig();
//默认支持驼峰名称
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
// strategy.setSuperEntityClass("com.fame.common.BaseEntity");
strategy.setEntityLombokModel(true);//自动lombok
strategy.setLogicDeleteFieldName("deleted");//逻辑删除字段
//自动填充
TableFill createTime = new TableFill("createTime", FieldFill.INSERT);
TableFill updateTime = new TableFill("updateTime", FieldFill.UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(createTime);
tableFills.add(updateTime);
strategy.setTableFillList(tableFills);
//乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);//restful风格的支持
// strategy.setSuperControllerClass("com.fame.common.BaseController");
strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
strategy.setSuperEntityColumns("id");
// strategy.setControllerMappingHyphenStyle(true);
strategy.setTablePrefix("sys");
mpg.setStrategy(strategy);
mpg.setTemplateEngine(new FreemarkerTemplateEngine());
mpg.execute();
}
}
然后进行数据库的设计:
此处我们只先进行简单的数据库设计:如下单表
做登录页面;
注册使用模态框:
首页类似于这样:
上面是一个跑马灯一样的广告;
网上找几张图片然后写进div中,使用轮播图:
然后设置样式,让图片填充到整个div中:
body
{
background-image: url(images/firstlogin.jpg);
background-color: #000000;
}
img{
width: 100%;
height: 100%;
}
轮播图代码:
<div class="layui-row">
<div class="layui-col-xs12">
<!--轮播图-->
<div class="layui-carousel" id="test10" style="margin: 10px;">
<div carousel-item="">
<div><img th:src="@{/images/book1.jpg}"></div>
<div><img th:src="@{/images/book2.jpg}"></div>
<div><img th:src="@{/images/book3.jpg}"></div>
<div><img th:src="@{/images/book4.jpg}"></div>
<div><img th:src="@{/images/book5.jpg}"></div>
<div><img th:src="@{/images/book6.jpg}"></div>
</div>
</div>
</div>
</div>
使用layui的轮播图:让左右等距,高度我们定义,js
<script>
layui.use(['carousel'], function(){
var carousel = layui.carousel;
//图片轮播
carousel.render({
elem: '#test10'
,width: 'auto'
,height: '250px'
,interval: 3000
});
//事件
carousel.on('change(test4)', function(res){
console.log(res)
});
});
</script>
同样,导航条我们也使用layui的:
引入js,css:我这里放在head中引入的:
<link th:href="@{/layui/css/layui.css}" rel="stylesheet">
<script th:src="@{/layui/layui.js}"></script>
js代码如下:
<script>
//导航条需要的js
//注意:导航 依赖 element 模块,否则无法进行功能性操作
layui.use('element', function(){
var element = layui.element;
//…
});
</script>
初步效果如下:
百度搜图片素材:轮播图长条图片图书
给logo设置背景图片:
<div style="width: auto;height: auto">
<h1 id="logo">图书商城</h1>
</div>
简单的样式:
#logo{
background-image: url(images/logo.jpg);
text-align: center;
}
效果如下:
然后细微调整轮播图的间距:
<div class="layui-carousel" id="test10" style="margin: 10px;">
layer的使用:
官方参考文档:
链接: https://www.layui.com/doc/modules/layer.html#content.
使用layui的弹出层模块创建用户的修改信息:
1.layer概述:
layer 至今仍作为 layui 的代表作,它的受众广泛并非偶然,而是这数年来的坚持、不弃的执念,将那些不屑的眼光转化为应得的尊重,不断完善和维护、不断建设和提升社区服务,在 Web 开发者的圈子里口口相传,乃至于成为今天的 layui 最强劲的源动力。目前,layer 已然成为网页弹出层的首先交互方案,几乎随处可见。
2.使用方式:
如下使用:
<script>
layui.use('layer', function onAddBtn(){
//$("#add-form").show();
//页面层-自定义
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title:"修改用户信息",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
shift: 2,
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px','500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#add-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
success: function(layero, index){},//success - 层弹出后的成功回调方法
yes: function(index, layero){//yes - 确定按钮回调方法
//do something
layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
});
</script>
弹出层内部的内容:
宽高的设置:
弹出层坐标:
图标:
按钮:
这里特别注意,按钮一不论什么名字,它的回调都是yes
以下代码可以在在线调试工具中看效果:
layer.open({
content: 'test'
,btn: ['按钮一', '按钮二', '按钮三']
,yes: function(index, layero){
//按钮【按钮一】的回调
layer.msg("添加成功");
}
,btn2: function(index, layero){
//按钮【按钮二】的回调
layer.msg('删除成功',{icon:5});
//return false 开启该代码可禁止点击该按钮关闭
}
,btn3: function(index, layero){
//按钮【按钮三】的回调
layer.msg('取消',{icon:2});
//return false 开启该代码可禁止点击该按钮关闭
}
,cancel: function(){
//右上角关闭回调
//return false 开启该代码可禁止点击该按钮关闭
}
});
确认弹出框的使用:
layer.confirm('确定删除吗?', {
btn: ['确定', '按钮二'] //可以无限个按钮
}, function(index, layero){
//按钮【按钮一】的回调
layer.msg('确定');
}, function(index){
//按钮【按钮二】的回调
});
提示:
//tips层-上
layer.tips('上', '#id或者.class', {
tips: [1, '#0FA6D8'] //还可配置颜色
});
//tips层-右
layer.tips('默认就是向右的', '#id或者.class');
//tips层-下
layer.tips('下', '#id或者.class', {
tips: 3
});
//tips层-左
layer.tips('左边么么哒', '#id或者.class', {
tips: [4, '#78BA32']
});
//tips层-不销毁之前的
layer.tips('不销毁之前的', '#id或者.class', {
tipsMore: true
});
核心功能:使用弹出层做增删改查:
因为layui的特性,每次不管使用哪个组件,都要先把它的模块加载出来
比如我要用layer和form
那么就需要先这样定义,你的操作都是在这个里面进行,当然页可以一次性加载所有模块,详情去看api文档https://www.layui.com/doc/
部分代码:
<script>
layui.use(['layer','form'], function onAddBtn(){
var $ = layui.jquery, layer = layui.layer; //独立版的layer无需执行这一句
var form=layui.form;
//页面层-自定义
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title:"修改用户信息",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
shift: 2,
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px','500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#add-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
success: function(layero, index){},//success - 层弹出后的成功回调方法
yes: function(index, layero){//yes - 确定按钮回调方法
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
});
</script>
注意:上面的代码有缺陷:
我们参照修改如下:因为我在使用layui自带的导航栏的时候,她的nav中的a标签我们定义一个单击事件的时候最好使用这种形式:
//nav的a链接:
<a href="#" onclick="adminsys()" >
//然后调用js的时候要使用如下方式:
<script>
layui.use(['form','layer','element','carousel'],function () {
//导航条需要的js
var $ = layui.$;
var layer = layui.layer; //独立版的layer无需执行这一句
var form = layui.form;
var element = layui.element;
<!--轮播图的js-->
var carousel = layui.carousel;
//图片轮播
carousel.render({
elem: '#test10'
,width: 'auto'
,height: '250px'
,interval: 3000
});
//事件
carousel.on('change(test4)', function(res){
console.log(res)
});
//adminsys后台管理方法,<a href="#" onclick="adminsys()" >这个可行
window.adminsys =function () {
alert("test");
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '400px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#admin-login"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
id: 'admin',
//success: function(layero, index){},//success - 层弹出后的成功回调方法
yes: function (index, layero) {//yes - 确定按钮回调方法
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
};
/*这种也可以可行,但是破坏了原有的样式,不建议*/
$("#onAddBtn").click(function () {
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#add-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
id: 'admin2',
//success: function(layero, index){},//success - 层弹出后的成功回调方法
yes: function (index, layero) {
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
});
});
</script>
知识拓展:a标签添加onclick事件的几种方式
我们常用的在a标签中有点击事件:
- a href=“javascript:js_method();”
这种方法在传递this等参数的时候很容易出问题,而且javascript:协议作为a的href属性的时候不仅会导致不 必要的触发window.onbeforeunload事件,在IE里面更会使gif动画图片停止播放。W3C标准不推荐在href里面执行 javascript语句
- a href=“javascript:void(0);” οnclick=“js_method()”
这种方法是很多网站最常用的方法,也是最周全的方法,onclick方法负责执行js函数,而void是一个操作符,void(0)返回undefined,地址不发生跳转。而且这种方法不会像第一种方法一样直接将js方法暴露在浏览器的状态栏。
3.a href=“javascript:;” οnclick=“js_method()”
这种方法跟跟2种类似,区别只是执行了一条空的js代码。
4.a href="#" οnclick=“js_method()”
这种方法也是网上很常见的代码,#是标签内置的一个方法,代表top的作用。所以用这种方法点击后网页后返回到页面的最顶端。
5.a href="#" οnclick=“js_method();return false;”
这种方法点击执行了js函数后return false,页面不发生跳转,执行后还是在页面的当前位置。
6.用Jquery的preventDefault()方法
$(“a”).click(function(event){
event.preventDefault();
});
综合上述,在a中调用js函数最适当的方法推荐使用:
a href=“javascript:void(0);” οnclick=“js_method()”
a href=“javascript:;” οnclick=“js_method()”
a href="#" οnclick=“js_method();return false;”
开发中遇到的bug1:
数据回显的方法:结合layui的弹出层:
//数据回显的方法
window.onUpdateBtn =function () {
//先查找
var name = '[[${session.loginUser.name}]]';
alert(name);
$.post(
"/selectUserByName",
{name:name},
function (jsonData) {
//1.回调函数先把返回的json数据加载到form,此方法loadDatatoForm单独定义好了
loadDatatoForm("update-form", jsonData);
//2.然后打开弹出层。
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#update-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
//id: 'admin2',
success: function(layero, index){
},//success - 层弹出后的成功回调方法
yes: function (index, layero) {//yes - 确定按钮回调方法
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
},
"json"
);
/*layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#update-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
id: 'admin2',
success: function(layero, index){
},//success - 层弹出后的成功回调方法
yes: function (index, layero) {//yes - 确定按钮回调方法
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});*/
}
完整代码是放在 layui.use([‘form’,‘layer’,‘element’,‘carousel’],function () {}中的,如下:
<script>
layui.use(['form','layer','element','carousel'],function () {
//导航条需要的js
var $ = layui.$;
var layer = layui.layer; //独立版的layer无需执行这一句
var form = layui.form;
var element = layui.element;
<!--轮播图的js-->
var carousel = layui.carousel;
//图片轮播
carousel.render({
elem: '#test10'
,width: 'auto'
,height: '250px'
,interval: 3000
});
//事件
carousel.on('change(test4)', function(res){
console.log(res)
});
//adminsys后台管理方法,<a href="#" onclick="adminsys()" >这个可行
window.adminsys =function () {
//alert("test");
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '400px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#admin-login"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
//id: 'admin',
//success: function(layero, index){},//success - 层弹出后的成功回调方法
yes: function (index, layero) {
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
};
//数据回显的方法
window.onUpdateBtn =function () {
//先查找
var name = '[[${session.loginUser.name}]]';
alert(name);
$.post(
"/selectUserByName",
{name:name},
function (jsonData) {
//1.回调函数先把返回的json数据加载到form,此方法loadDatatoForm单独定义好了
loadDatatoForm("update-form", jsonData);
//2.然后打开弹出层。
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#update-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
//id: 'admin2',
success: function(layero, index){
},//success - 层弹出后的成功回调方法
yes: function (index, layero) {//yes - 确定按钮回调方法
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
},
"json"
);
/*layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['新增', '取消'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#update-main"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
id: 'admin2',
success: function(layero, index){
},//success - 层弹出后的成功回调方法
yes: function (index, layero) {//yes - 确定按钮回调方法
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});*/
}
});
</script>
加载json数据到form的:
<!--加载json数据到表格loadDatatoForm-->
<script >
/*回填controller返回的json数据到form表单,将前天数据以json格式返回, @ResponseBody: return book;*/
function loadDatatoForm(fromId, jsonDate) {
var obj = jsonDate;
var key, value, tagName, type, arr;
for (x in obj) {
key = x;
value = obj[x];
$("#" + fromId + " [name='" + key + "'],#" + fromId + " [name='" + key + "[]']").each(function () {
tagName = $(this)[0].tagName;
type = $(this).attr('type');
if (tagName == 'INPUT') {
if (type == 'radio') {
$(this).attr('checked', $(this).val() == value);
} else if (type == 'checkbox') {
try {
arr = value.split(',');
for (var i = 0; i < arr.length; i++) {
if ($(this).val() == arr[i]) {
$(this).attr('checked', true);
break;
}
}
} catch (e) {
$(this).attr('checked', value);
}
} else {
$(this).val(value);
}
} else if (tagName == 'TEXTAREA') {
$(this).val(value);
} else if (tagName == 'SELECT') {
if ($(this).hasClass("select2")) {
$(this).val(value).trigger("change");
} else {
$(this).val(value);
}
}
});
}
}
</script>
然后紧接着设计修改表单的提交:
做如下准备:将修改表单的action设计成thymleaf的形式:
<form style="margin: 15%;"
class="layui-form" id="update-form" th:action="@{/updateUser}">
//提交的按钮
<button type="submit" class="layui-btn" lay-filter="save" >提交</button>
后台的修改提交:
@RequestMapping("/updateUser")//修改提交
public String updateUser(User user, HttpSession session){
//System.out.println(name);
System.out.println("前端的参数:"+user);
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("name",user.getName());
int update = service.getBaseMapper().update(user, updateWrapper);
if(update!= 0){
session.setAttribute("loginUser",user);
}
return "front/index";
}
最终效果如下:
layui的分页:
参考:https://www.cnblogs.com/laowenBlog/p/11240503.html
注意分页之前要的pom依赖和config:
其中mybatisplus的分页插件如下:
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
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;
}
}
1.前台页面分页的功能
后台我们使用MybatisPlus,前端使用thymleaf模板和layui的laypage分页条:
前端的分页我们后台这样写,使用LoginController:
@RequestMapping("/index.html")//修改成带分页的
public String toIndex(@RequestParam(required = true,defaultValue = "1",value = "pageNum")String pageNum,
@RequestParam(required = false,defaultValue = "4",value = "pageSize")String pageSize,
Model model
){
System.out.println("================"+pageNum);
System.out.println(pageSize);
//分页的逻辑,构建分页对对象page
Page<Book> bookPage = new Page<Book>(Long.valueOf(pageNum),Long.valueOf(pageSize));
//QueryWrapper<Book> wrapper = new QueryWrapper<>();
Page<Book> page = bookService.getBaseMapper().selectPage(bookPage, null);
System.out.println("测试后台的page分页总数:===="+page.getTotal());
System.out.println("当前页:===="+page.getCurrent());
System.out.println("每页的条目数:===="+page.getSize());
System.out.println("总页数:===="+page.getPages());
System.out.println("数据的记录:===="+page.getRecords());
model.addAttribute("page",page);
return "front/index";
}
前端使用layui的栅格和面板来呈现数据和图片:(thymleaf模板引擎)
<!--栅格系统展示图书-->
<div style="margin: 0 auto; max-width: 1140px;">
<!--分类标签-->
<div class="layui-row">
<div class="layui-col-xs12" style="background-color: white;padding-bottom: 10px">
<!--分类-->
<div style="margin-right: 5%;margin-left: 5%;padding-top: 10px" id="typeId">
<i class="layui-icon layui-icon-template-1"></i>
<span style="font-weight: bolder;color: #1CAF9A">精选图书</span>
</div>
</div>
</div>
<!--前端图书列表-->
<div class="layui-row" >
<div class="layui-col-xs3" th:each="book : ${page.records}">
<div class="layui-card">
<div class="layui-card-header">
<!--<img th:src="@{/images/book/bk4.jpg}">-->
<img alt="图片" th:src="${book.getImgPath()}">
</div>
<div class="layui-card-body">
价格:[[${book.price}]] | 作者:[[${book.author}]]<br>
<a style="color: #1CAF9A" href="#">更多信息...</a>
</div>
</div>
</div>
</div>
<!--<div class="layui-row">
<div class="layui-col-xs3">
<div class="layui-card">
<div class="layui-card-header">
<img th:src="@{/images/book/bk4.jpg}">
</div>
<div class="layui-card-body">
价格:99 作者:佚名<br>
更多信息...
</div>
</div>
</div>
<div class="layui-col-xs3">
<div class="layui-card">
<div class="layui-card-header">
<img th:src="@{/images/book/bk1.jpg}">
</div>
<div class="layui-card-body">
价格:99 作者:佚名<br>
更多信息...
</div>
</div>
</div>
<div class="layui-col-xs3">
<div class="layui-card">
<div class="layui-card-header">
<img th:src="@{/images/book/bk2.jpg}">
</div>
<div class="layui-card-body">
价格:99 作者:佚名<br>
更多信息...
</div>
</div>
</div>
<div class="layui-col-xs3">
<div class="layui-card">
<div class="layui-card-header">
<img th:src="@{/images/book/bk3.jpg}">
</div>
<div class="layui-card-body">
价格:99 作者:佚名<br>
更多信息...
</div>
</div>
</div>
</div>-->
<!--前端分页导航-->
<div class="layui-row">
<div class="layui-col-xs12" style="background-color: white">
<!--前端分页-->
<div style="margin-right: 10%;margin-left: 10%" id="demo7"></div>
</div>
</div>
<!--底部导航-->
<div class="layui-row">
<div class="layui-col-xs12" style="background-color: #1CAF9A;padding-top: 20px;padding-bottom: 20px">
<!--前端分页-->
<div style="width: 50%;margin-left: auto;margin-right: auto" >
<h5 style="text-align: center">© 2021 layui.com MIT license</h5>
<h5 style="text-align: center">
<a href="#" class="">免责声明</a>
<a href="#">公众号</a>
<a href="#">友情链接</a>
<a href="#">联系我</a>
</h5>
</div>
</div>
</div>
</div>
如果是jsp页面可以这样写:
数据库中mysql图片地址格式:注意不写static前缀。
2.layui的跳转链接实现分页的js:
将前端的多个静态div换成后台遍历的,如下:
<!--分类标签-->
<div class="layui-row">
<div class="layui-col-xs12" style="background-color: white;padding-bottom: 10px">
<!--分类-->
<div style="margin-right: 5%;margin-left: 5%;padding-top: 10px" id="typeId">
<i class="layui-icon layui-icon-template-1"></i>
<span style="font-weight: bolder;color: #1CAF9A">精选图书</span>
</div>
</div>
</div>
<!--前端图书列表-->
<div class="layui-row" >
<div class="layui-col-xs3" th:each="book : ${page.records}">
<div class="layui-card">
<div class="layui-card-header">
<!--<img th:src="@{/images/book/bk4.jpg}">-->
<img alt="图片" th:src="${book.getImgPath()}">
</div>
<div class="layui-card-body">
价格:[[${book.price}]] | 作者:[[${book.author}]]<br>
<a style="color: #1CAF9A" href="#">更多信息...</a>
</div>
</div>
</div>
</div>
<!--分页条的开始-->
<div class="layui-row">
<div class="layui-col-xs12" style="background-color: white">
<!--前端分页-->
<div style="margin-right: 10%;margin-left: 10%" id="demo7"></div>
</div>
</div>
<!--分页条的结束-->
然后写分页的js代码:(用的是thymleaf模板,th:inline="javascript"用于行内取值[[]]用。)
<script th:inline="javascript">
layui.use(['form','layer','element','carousel','laypage'],function () {
//导航条需要的js
var $ = layui.$;
var layer = layui.layer; //独立版的layer无需执行这一句
var form = layui.form;
var element = layui.element;
var carousel = layui.carousel;
var laypage = layui.laypage;
//前端分页完整功能开始
var total = [[${page.total}]];//总条目数
var limit_ = [[${page.size}]];//每页的显示条数
var last_ = [[${page.pages}]];
var current_ = [[${page.current}]];//当前页
laypage.render({
elem: 'demo7' //分页条坐在的id#demo7
,count: total //数据总数。一般通过服务端得到
,pages: [[${page.pages}]] //总页数
,limit: limit_ //每页显示的条数。laypage将会借助 count 和 limit 计算出分页数。
,limits: [4,8] //下拉选择每页展示的条目数,每页条数的选择项。
,groups: 4 //连续出现的页码个数
,curr:current_ //当前页
,first: 1 //不起作用
,last: last_ //不起效果
,layout: ['count', 'prev', 'page', 'next', 'limit', 'refresh', 'skip'] //自定义排版。可选值有:count(总条目输区域)、prev(上一页区域)、page(分页区域)、next(下一页区域)、limit(条目选项区域)、refresh(页面刷新区域。注意:layui 2.3.0 新增) 、skip(快捷跳页区域)
,jump: function(obj, first){
console.log(obj);
if (!first) {//如果不是第一页,跳转页面
var pageSize=obj.limit;得到每页显示的条数
var pageNum=obj.curr;//得到当前页,以便向服务端请求对应页的数据。固定写法
window.location.href="/index?pageNum="+pageNum+"&pageSize="+pageSize;//跳转链接
}
}
});
//前端分页完整功能结束
});
最终效果展示:
3.前端页面的条件查询:
注意一下form表单的数据回显:
动态条件查询的表单:
<form class="navbar-form navbar-right" th:action="@{/index}" method="get" style="margin-right: 15%;margin-top: 14px">
<div class="form-group">
<input type="text" id="bookName" name="name" class="form-control" placeholder="请输入图书名" th:value="${param.name}" >
</div>
<button type="submit" class="btn btn-default">查找</button>
</form>
此时将数据回显的行内写法的[[]]上的单引号去掉,script 标签上加th:inline=“javascript”
然后在原先分页的基础上修改如下代码:
window.location.href="/index?pageNum="+pageNum+"&pageSize="+pageSize+"&name="+name;//跳转链接
修改后台代码:
//定义查询全局/成员变量
QueryWrapper<Book> wrapper;
@RequestMapping({"/index.html","/index"})//修改成带分页的
public String toIndex(
@RequestParam(required = false,value = "name")String name,
@RequestParam(required = true,defaultValue = "1",value = "pageNum")String pageNum,
@RequestParam(required = false,defaultValue = "4",value = "pageSize")String pageSize,
Model model
){
System.out.println("================"+pageNum);
System.out.println("========bookname========"+name);
System.out.println(pageSize);
//分页的逻辑,构建分页对对象page
Page<Book> bookPage = new Page<Book>(Long.valueOf(pageNum),Long.valueOf(pageSize));
wrapper=null;//让查询条件为空,这一步很关键。当我们清空输入框内容,点击查询则查询所有。
if(!"".equals(name) && name != null){
wrapper = new QueryWrapper<>();
wrapper.like("name",name);
}
System.out.println("wrapper===="+wrapper);
Page<Book> page = bookService.getBaseMapper().selectPage(bookPage, wrapper);
System.out.println("测试后台的page分页总数:===="+page.getTotal());
System.out.println("当前页:===="+page.getCurrent());
System.out.println("每页的条目数:===="+page.getSize());
System.out.println("总页数:===="+page.getPages());
System.out.println("数据的记录:===="+page.getRecords());
model.addAttribute("page",page);
return "front/index";
}
效果:
登录后台管理界面:
遇到问题的解决参考链接:https://www.jb51.net/article/171150.htm
(1).利用ajax发送请求:
开发中有一个需求是:发送ajax请求并发生页面跳转:
一般情况下是不能发送ajax请求的同时并进行页面跳转的。
ajax 本身是不适用于页面跳转的;
可以借助其他方法实现:
1,window.location.href = “/home”;
2,springMVC 返回的modelAndView (redirect:xxx)
两者用一个即可。
核心代码如下:
ajax请求最好只用于发送数据,和从后端拿数据,不要做跳转页面的…如果一定要做页面的跳转,可以约定后端放回的数据为1或0,当返回的数据为1时,用Windows.location.href="index.html"来跳转
function (dat) {
if (dat==1){//返回一个1字符串或者0,json形式的。
window.location.href="/toadminHtml" ;
}else {
alert("0");
}
}
否则就用submit提交,记住了,ajax用于发送请求到那个方法后,后端是跳转不了页面的,也不会报错,因为ajax用于默认是异步请求,如果要跳就在前端跳转页面也是可以的
(2)过程实现:
点击后台管理的nav,使用layui的弹出层弹出一个form登录表单:
form表单设置成隐藏的(dispaly:none)
后台登录系统form表单:
<!--后台登录的表单-->
<div id="admin-login" style="display:none;">
<form style="margin: 15%;" class="layui-form" id="admin-form" action="">
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">名字 </label>
<div class="layui-input-block">
<input name="name" id="admin_name" type="text" style="width: 240px" placeholder="请输入账户名称" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">密码 </label>
<div class="layui-input-block">
<input name="password" id="admin_password" type="text" style="width: 240px" placeholder="请输入密码" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" id="admin_save" class="layui-btn" >登录</button>
<button type="button" class="layui-btn layui-btn-primary" id="closeBtn-admin" >重置</button>
</div>
</div>
</form>
</div>
js代码如下:
//adminsys后台管理方法,<a href="#" onclick="adminsys()" >这个可行
window.adminsys =function () {
//alert("test");
layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "登录后台账号",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '400px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
//time: 90000, //time - 自动关闭所需毫秒
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
//btn: ['提交'],//模态框自带的最下边的按钮
//btnAlign: 'c',//btnAlign: 'c' 按钮居中对齐
content: $("#admin-login"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
//id: 'admin',
success: function(layero, index){//success - 层弹出后的成功回调方法
/*后台管理系统登录的ajax开始*/
$("#admin_save").click(function() {
//alert("后台管理系统");
var admin_name = $("#admin_name").val();
var admin_password = $("#admin_password").val();
$.post(
"/selectUserByNameAndPwd",
{"name":admin_name,"password":admin_password},
function (dat) {
if (dat==1){//返回一个1字符串或者0,json形式的。
window.location.href="/toadminHtml" ;
}else {
alert("1")
}
}
);
//layer.close(index);//点击登录的时候将层关闭
});
/*后台管理系统登录的ajax结束*/
//layer.close(index);
},
yes: function (index, layero) {
//do something
//layer.close(index); //如果设定了yes回调,需进行手工关闭
}
});
};
后台controller的代码:
//登录后台管理系统
@RequestMapping("/selectUserByNameAndPwd")
@ResponseBody
public String selectUserByNameAndPwd( @RequestParam(required = true,value = "name") String name,
@RequestParam(required = true,value = "password") String password,
HttpSession session,
Model model){//查找方法,只用于回显数据
//System.out.println(name);
System.out.println("前端的参数ajax发送的=====:"+name+",password:"+password);
User adminUser = service.getLoginUserByNameAndPwd(name,password);
if(adminUser != null){
session.setAttribute("adminUser",adminUser);
//跳转到后台页面
System.out.println("跳转后台页面----");
return "1";
}else{
model.addAttribute("admin_msg","用户名或者密码不正确");
return "0";
}
}
@RequestMapping("/toadminHtml")
public String toadminTest(Model model){
return "admin/adminx";
}
效果:我们从layui的官网上找到文档–>布局–>滚轴拉到最下找到:管理系统界面布局,整个代码复制过来使用。
LayUI的基本使用 - Tab选项卡切换显示对应数据
参考官方链接:https://www.layui.com/doc/modules/element.html#use
基本的实现效果:
需求:将对应的数据表格放到选项卡内容区进行展示:
1.1 先给每一个Tab选项卡一个属性lay-id=""、用来存放id值。具体代码如下:
<!--头部tab选项卡开始-->
<div class="layui-tab layui-tab-card layui-layout-left " style="background-color: white;" lay-filter="demo" lay-allowclose="true">
<ul class="layui-tab-title" style="height: 60px;line-height: 60px;margin-top: -10px;margin-left: -0.5px;">
<li class="layui-this" lay-id="11" style="height: 60px;line-height: 60px">图书管理</li>
<li lay-id="22" style="height: 60px;line-height: 60px">用户管理</li>
<li lay-id="33" style="height: 60px;line-height: 60px">权限分配</li>
<li lay-id="44" style="height: 60px;line-height: 60px">商品管理</li>
<li lay-id="55" style="height: 60px;line-height: 60px">订单管理</li>
</ul>
<!--tab选项卡下对应的内容-->
<div class="layui-tab-content" style="width: 1000px;height: 1500px;">
<div class="layui-tab-item layui-show">内容1</div>
<div class="layui-tab-item">内容2</div>
<div class="layui-tab-item">内容3</div>
<div class="layui-tab-item">内容4</div>
<div class="layui-tab-item">内容5</div>
</div>
</div>
<!--头部tab选项卡结束-->
2.2 获取对应的值。在官网手册文档上、我们可以找到监听Tab切换事件
删除商品事件:
触发选项卡切换:
对应的代码:
//tab切换事件,触发选项卡切换
element.on('tab(layui_tab)', function(data){
console.log("*************");
console.log(this); //当前Tab标题所在的原始DOM元素
console.log(data.index); //得到当前Tab的所在下标
console.log(data.elem); //得到当前的Tab大容器
var lay_id = $(this).attr('lay-id');
console.log(lay_id);
console.log("*************");
});
table数据渲染(render):
//table渲染
table.render({
elem: '#book_table'//指定原始表格元素选择器(推荐id选择器)
,height: 400//容器高度,高度不能太高,不然影响分页条的显示
,url: '/getBookByPage' //数据接口,异步数据接口相关参数。其中 url 参数为必填项,相当于发送一个ajax请求
,limit: 3//每页显示的条数(默认 10)。值需对应 limits 参数的选项。注意:优先级低于 page 参数中的 limit 参数
,limits: [3,5,10,20]//每页条数的选择项,默认:[10,20,30,40,50,60,70,80,90]。注意:优先级低于 page 参数中的 limits 参数
,request: {
pageName: 'pageNum' //页码的参数名称,默认:page
,limitName: 'pageSize' //每页数据量的参数名,默认:limit
}
,page: true //开启分页
,cellMinWidth: 60//全局定义所有常规单元格的最小宽度
,skin: 'line' //行边框风格
,even: true //开启隔行背景
,cols: [[ //设置表头
{type:'checkbox',fixed: 'left'}//左边固定多选框的设定,横向滚动条的设定.layui-body{overflow-y: scroll;}
,{field: 'id', title: 'ID', width:80, sort: true, fixed: 'left'}
,{field: 'name', title: '书名', width:100}
,{field: 'price', title: '价格', width:70, sort: true}
,{field: 'author', title: '作者', width:80}
,{field: 'sales', title: '销量', width: 70,sort: true}
,{field: 'stock', title: '库存', width: 70, sort: true}
,{field: 'create_time', title: '创建时间', width: 120, sort: true,templet:function(d){return util.toDateString(d.commPosttime*1000, "yyyy-MM-dd HH:mm:ss");}}
,{field: 'update_time', title: '修改时间', width: 120,sort: true,templet:function(d){return util.toDateString(d.commPosttime*1000, "yyyy-MM-dd HH:mm:ss");}}
,{fixed: 'right', title: '操作',width:170, align:'center', toolbar: '#barDemo'} //这里的toolbar值是模板元素的选择器
]]
});
上面的数据表格渲染代码需要写到以下代码中:
//预先加载各种内置模块
layui.use(['element', 'layer', 'util','table'], function(){
var element = layui.element
,layer = layui.layer
,util = layui.util
,table = layui.table
,$ = layui.$;
}
各项参数详情请参照官网进行对应设置:
重要参数1: url: ‘/getBookByPage’ //数据接口,异步数据接口相关参数。其中 url 参数为必填项,相当于发送一个ajax请求,并收到后台的json数据
重要参数2:request参数的作用:用于对分页请求的参数:page、limit重新设定名称,如:
重要参数3:
{fixed: ‘right’, title: ‘操作’,width:170, align:‘center’, toolbar: ‘#barDemo’} //这里的toolbar值是模板元素的选择器
作用:toolbar - 绑定工具条模板:
通常你需要在表格的每一行加上 查看、编辑、删除 这样类似的操作按钮,而 tool 参数就是为此而生,你因此可以非常便捷地实现各种操作功能。tool 参数和 templet 参数的使用方式完全类似,通常接受的是一个选择器,也可以是一段HTML字符。
下述是 toolbar 对应的模板,它可以存放在页面的任意位置:
<script type="text/html" id="barDemo">
<a class="layui-btn layui-btn-xs" lay-event="detail">查看</a>
<a class="layui-btn layui-btn-xs" lay-event="edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
注意:属性 lay-event="" 是模板的关键所在,值可随意定义。
后台代码(使用Mybatis-plus):
@Resource
private IBookService bookService;
//getBookByName
@RequestMapping("/getBookByPage")
@ResponseBody//返回json
public Map<String,Object> getBookByPage(
@RequestParam(required = true,defaultValue = "1",value = "pageNum")String pageNum,
@RequestParam(required = false,defaultValue = "3",value = "pageSize")String pageSize,
Model model
){
Page<Book> bookPage = new Page<Book>(Long.valueOf(pageNum),Long.valueOf(pageSize));
Page<Book> page = bookService.getBaseMapper().selectPage(bookPage, null);
Map<String,Object> map = new LinkedHashMap<String,Object>();//自己设置一个map,将code,msg放进去。
map.put("code","0");//注意状态必须是0,0代表成功
map.put("msg","成功");
map.put("count",page.getTotal());
map.put("data",page.getRecords());
return map;//返回json
}
然后最终效果:
注意如果底下的分页条不显示,请重新设置height参数:
table.render({
elem: '#book_table'//指定原始表格元素选择器(推荐id选择器)
,height: 400//容器高度,高度不能太高,不然影响分页条的显示
toolbar:表格头部工具条
代码演示:
defaultToolbar - 头部工具栏右侧图标
注意:toolbar参数有的话,头部工具栏右侧图标默认有。
done - 数据渲染完的回调
是否开启合并行totalRow:true/false
text - 自定义文本
合计功能开启:
单元格可编辑开启:
比如:
{field: 'name', title: '书名', width:100,edit:true}
模板语法:
总结表头参数:
数据表格的监听事件:
1.头部监听事件:
2.触发复选框选择
点击复选框时触发,回调函数返回一个 object 参数:
table.on('checkbox(test)', function(obj){//test位数据表格的lay-filter
console.log(obj); //当前行的一些常用操作集合
console.log(obj.checked); //当前是否选中状态
console.log(obj.data); //选中行的相关数据
console.log(obj.type); //如果触发的是全选,则为:all,如果触发的是单选,则为:one
});
3.触发单元格编辑
前提是单元格可以被编辑,在字段设置上添加edit:true;
单元格被编辑,且值发生改变时触发,回调函数返回一个object参数,携带的成员如下:
table.on('edit(test)', function(obj){ //注:edit是固定事件名,test是table原始容器的属性 lay-filter="对应的值"
console.log(obj.value); //得到修改后的值
console.log(obj.field); //当前编辑的字段名
console.log(obj.data); //所在行的所有相关数据
});
4.触发行单双击事件
注意,单击事件和双击事件只能有一个
点击或双击行时触发。该事件为 layui 2.4.0 开始新增
//触发行单击事件
table.on('row(test)', function(obj){
console.log(obj.tr) //得到当前行元素对象
console.log(obj.data) //得到当前行数据
//obj.del(); //删除当前行
//obj.update(fields) //修改当前行数据
});
//触发行双击事件
table.on('rowDouble(test)', function(obj){
//obj 同上
});
5.触发行中工具条点击事件
//行工具条事件
table.on('tool(test)', function(obj){ //注:tool 是工具条事件名,test 是 table 原始容器的属性 lay-filter="对应的值"
var data = obj.data; //获得当前行数据
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
var tr = obj.tr; //获得当前行 tr 的 DOM 对象(如果有的话)
if(layEvent === 'detail'){ //查看
//do somehing
} else if(layEvent === 'del'){ //删除
layer.confirm('真的删除行么', function(index){
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
layer.close(index);
//向服务端发送删除指令
});
} else if(layEvent === 'edit'){ //编辑
//do something
//同步更新缓存对应的值
obj.update({
username: '123'
,title: 'xxx'
});
} else if(layEvent === 'LAYTABLE_TIPS'){
layer.alert('Hi,头部工具栏扩展的右侧图标。');
}
});
基础方法:
1.获取选中行:
第二种表格重载:
利用弹出层做表格的增删改查:
动态查询表单的制作:
打开新增form弹出层:
监听修改事件:注意使用lay-filter在每一行的编辑按钮上;
打开修改弹出层:
修改表单数据的回显:
新增表单数据的清空:
表单提交事件:
代码演示:
前端的html
<!--user头部左边工具条,使用按钮组-->
<div style="display: none" id="user_tool_bar">
<div >
<button type="button" class="layui-btn layui-btn-sm" lay-event="u-add">增加</button>
<button type="button" class="layui-btn layui-btn-sm" lay-event="u-deleteAll">批量删除</button>
</div>
</div>
<!--user用户添加/修改的表单弹出层开始-->
<div id="add_user" style="display:none;">
<form style="margin: 15%;" class="layui-form" id="user-form" lay-filter="user-form" action="">
<input name="id" id="user_id" type="hidden" style="width: 240px" placeholder="id" autocomplete="off" class="layui-input">
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">姓名 </label>
<div class="layui-input-block">
<input name="name" id="user_name" type="text" lay-verify="required" style="width: 240px" placeholder="请输入用户名" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">年龄 </label>
<div class="layui-input-block">
<input name="age" id="user_price" type="text" lay-verify="required" th:value="${param.age}" style="width: 240px" placeholder="请输入年龄" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">邮箱 </label>
<div class="layui-input-block">
<input name="email" id="user_email" type="text" lay-verify="required" style="width: 240px" placeholder="请输入邮箱" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">密码 </label>
<div class="layui-input-block">
<input name="password" id="user_password" type="text" lay-verify="required" style="width: 240px" placeholder="请输入密码" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label" style="width: 100px">电话 </label>
<div class="layui-input-block">
<input name="phone" id="user_phone" type="text" lay-verify="required" style="width: 240px" placeholder="请输入电话" autocomplete="off" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button type="button" id="save_user" class="layui-btn" lay-submit="" lay-filter="save_user" >提交</button>
<button type="reset" class="layui-btn layui-btn-primary" id="closeBtn-user" >重置</button>
</div>
</div>
</form>
</div>
<!--user用户添加/修改的表单弹出层结束-->
<!--user行操作工具条开始-->
<script type="text/html" id="userbarDemo">
<a class="layui-btn layui-btn-xs" lay-event="u-detail">查看</a>
<a class="layui-btn layui-btn-xs" lay-event="u-edit">编辑</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="u-del">删除</a>
</script>
<!--user行操作工具条结束-->
前端的js:
layui.use(['element', 'layer', 'util','table','form'], function(){
var element = layui.element
,layer = layui.layer
,util = layui.util
,table = layui.table
,form = layui.form
,$ = layui.$;
/* ===============================用户的js开始==================================================*/
var totalRecord ;//总记录数
var mycurr;//当前页码
var currPageSize ;//当前页的实际数据量
//用户table渲染
var userTableIns=table.render({
id:'user_table'
,elem: '#user_table'//渲染的目标对象,指定原始表格元素选择器(推荐id选择器), <table id="book_table"
,height: 330//容器高度,高度不能太高,不然影响分页条的显示;'full-300'可用高度减去300
,url: '/getUserByPage' //数据接口,异步数据接口相关参数。其中 url 参数为必填项,相当于发送一个ajax请求
,title : '用户数据表'//数据导出来的标题
,toolbar : '#user_tool_bar'//头部工具条,这里我们跟一个选择器
//,totalRow:true //开启合并行
,text:{ none: '暂无相关数据' }//默认:无数据。没有数据的时候的提示信息
,limit: 3//每页显示的条数(默认 10)。值需对应 limits 参数的选项。注意:优先级低于 page 参数中的 limit 参数
,limits: [3,5,10,20]//每页条数的选择项,默认:[10,20,30,40,50,60,70,80,90]。注意:优先级低于 page 参数中的 limits 参数
,request: {
pageName: 'pageNum' //页码的参数名称,默认:page
,limitName: 'pageSize' //每页数据量的参数名,默认:limit
}
,page: true //开启分页
,cellMinWidth: 60//全局定义所有常规单元格的最小宽度
,skin: 'line' //行边框风格
,even: true //开启隔行背景
,cols: [[ //设置用户的表头
{type:'checkbox',fixed: 'left'}//左边固定多选框的设定,横向滚动条的设定.layui-body{overflow-y: scroll;}
,{type:'numbers',fixed: 'left',title: '序号',totalRowText:'合计'} //numbers(序号列)
,{field: 'id', title: 'ID', width:80, sort: true, fixed: 'left',hide:true}
,{field: 'name', title: '用户名', width:100,edit:true,align: 'center'}
,{field: 'email', title: '邮箱', width:180, sort: true}
,{field: 'password', title: '密码', width:80}
,{field: 'phone', title: '电话', width: 170}
,{fixed: 'right', title: '操作',width:170, align:'center', toolbar: '#userbarDemo'} //这里的toolbar值是模板元素的选择器
]]
,done: function(res, curr, count){//数据渲染完的回调。你可以借此做一些其它的操作
//如果是异步请求数据方式,res即为你接口返回的信息。
//如果是直接赋值的方式,res即为:{data: [], count: 99} data为当前页数据、count为数据总长度
console.log(res);
console.log(res.data.length);//当前页的实际数据量
currPageSize = res.data.length;
//得到当前页码
console.log(curr);
mycurr = curr;//将后台数据赋值给前台当前页
//得到数据总量
console.log(count);
totalRecord = count;//将数据总量赋值给全局的变量
}
});
//user头部工具条事件
table.on('toolbar(userTable)', function(obj) {//userTable为user数据表的filter
var checkStatus = layui.table.checkStatus("user_table");//user表格被选中的状态,找table位置的id
switch(obj.event){
case 'u-add':
layer.msg('添加');
opeAddUser();//调用打开添加弹出层
break;
case 'u-deleteAll':
layer.msg('批量删除');
batchDelUserByIds(checkStatus);//调用批量删除的方法
break;
};
});
//定义批量删除的方法:
function batchDelUserByIds(checkStatus) {//checkStatus为user表格选中状态
alert("批量删除");
//当一页数据全部删除,出现无数据的bug
var ids = '';//定义一个空字符串。放id
var data = checkStatus.data;//获取所有选中行的数据,是数组
console.log(data);
for (var i=0;i<data.length;i++){
ids+= checkStatus.data[i].id + ',' ;//串联字符换id
}
ids = ids.substring(0,ids.length-1);//去掉做后一个,
console.log(ids);
if(data.length==currPageSize){//如果选中批量删除的数据量等于每页显示的条数,回到上一页
mycurr=mycurr-1;//定位到上一页
}
$.post(//发送ajax的post请求
"/batchDelUserByIds",
{"ids":ids},//格式是key:value
function (dat) {//成功之后的回调函数
console.log(dat);
userTableIns.reload({url:'/getUserByPage',page:{
curr:mycurr //重新回到前一页
}},true);//刷新数据
}
);
};
//user行工具条事件
table.on('tool(userTable)', function(obj){ //注:tool 是工具条事件名,userTable 是 table 原始容器的属性 lay-filter="对应的值"
var data = obj.data; //获得当前行数据
var layEvent = obj.event; //获得 lay-event 对应的值(也可以是表头的 event 参数对应的值)
if(layEvent === 'u-detail'){ //查看
//do somehing
layer.msg("查看")
} else if(layEvent === 'u-del'){ //删除,这里事件名字修改一下
layer.confirm('真的删除吗?', function(index){//在此layer.confirm中调用删除方法
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
layer.close(index);
//向服务端发送删除指令
delById(data);//删除的方法调用,u-del
});
} else if(layEvent === 'u-edit'){ //编辑
//do something
layer.msg("编辑");
openUpdateUser(data);//调用此方法,data参数为当前行数据,此处定义两个方法,隐藏的那个div是公用的
} else if(layEvent === 'LAYTABLE_TIPS'){
layer.alert('Hi,头部工具栏扩展的右侧图标。');
}
});
var userurl;//动态的url
var mainUserIndex;//定义user的form新增/修改的公共弹出层
//打开用户添加的方法
function opeAddUser(){//新增不需要传参数
mainUserIndex=layer.open({
id: 'userlayer',
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "添加用户",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
content: $("#add_user"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
success: function(layero, index){//成功打开页面之后的回调函数
//新增的方法需要先清空表单数据
$("#user-form")[0].reset();
userurl="/addUser";//,成功打开弹出层之后,动态的给url赋值
},
});
};
//打开修改页面的方法
function openUpdateUser(data){//传递的参数是修改的数据
mainUserIndex=layer.open({
type: 1,//type - 基本层类型,layer提供了5种层类型。可传入的值有:0(信息框,默认)1(页面层)2(iframe层)3(加载层)4(tips层)。 若你采用layer.open({type: 1})方式调用,则type为必填项(信息框除外)
title: "修改用户",//模态框的左上角的标题,如果你不想显示标题栏,你可以title: false
closeBtn: 1,//closeBtn - 右上关闭按钮,可通过配置1和2来展示,如果不显示,则closeBtn: 0
skin: 'layui-layer-molv',//skin - (皮肤)样式类名,两种内置的layui-layer-lan,layui-layer-molv
area: ['600px', '500px'],//模态框的大小,在默认状态下,layer是宽高都自适应的,但当你只想定义宽度时,你可以area: '500px',高度仍然是自适应的。当你宽高都要定义时,你可以area: ['500px', '300px']
shadeClose: true,//开启遮罩关闭,如果你的shade是存在的,那么你可以设定shadeClose来控制点击弹层外区域关闭。
anim: 5,//anim: 0 平滑放大。默认;anim: 5 渐显;anim: 1 从上掉落等
content: $("#add_user"),//加载的内容,这里可以是一个隐藏的div,form等,#add-main尾div的id
success: function(layero, index){
form.val("user-form",data);//第一个参数是form的id的filter,给表单赋值,data为这一行的数据
userurl="/updateUser";//动态给url赋值,在提交的时候用
},
});
};
//删除的方法
function delById(data){
//alert(data.id);
//向服务端发送删除指令
$.get(
'/delUserById',
{"id":data.id},
function (dat) {
if(dat==200){
obj.del(); //删除对应行(tr)的DOM结构,并更新缓存
}
}
);
//layer.close(index);//不能少了这一行
};
//保存,用户的submit提交事件
form.on('submit(save_user)', function(data){//form表单提交按钮的lay-filter="save_user"
var params = $("#user-form").serialize();//序列化表单数据
//alert(params);
//alert(userurl);
$.post(
userurl,//动态的url
params,//或者使用{"key":value}
function (obj) {
layer.msg("成功");
//关闭弹出层
layer.close(mainUserIndex);
//获取每页显示的记录数、当前记录总数,计算新添加的记录在第几页
console.log("-------------------");
totalRecord +=1;//总记录数,totalRecord的值是在表格渲染的done回调函数中赋值的。
console.log(totalRecord);
var pageSize = $(".layui-laypage-limits").find("select").val();
console.log("-------------------");
console.log(pageSize);
if($.type(pageSize) == "string"){
pageSize = parseInt(pageSize);
}
var lastCurrPageNo = Math.ceil(totalRecord / pageSize);//计算最后一页的页码数
console.log("每页显示的记录数:"+pageSize+" 类型:"+$.type(pageSize)+" 总的记录数:"+totalRecord+" 类型:"+$.type(totalRecord)
+" 新增行所在页码:"+lastCurrPageNo+" 类型:"+$.type(lastCurrPageNo));
//刷新表格数据,直接定位到了当前修改的地方,厉害
if(userurl=="/addUser"){//如果是新增,则携带最后一个的参数
userTableIns.reload({url:'/getUserByPage',
page : {
curr : lastCurrPageNo//page参数中携带当前页
},
},true);
}else{//如果是修改,则使用默认参数
userTableIns.reload({url:'/getUserByPage'},true);
}
}
);
});
});
后台代码:
package com.fan.bookshop.controller;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fan.bookshop.entity.User;
import com.fan.bookshop.service.IUserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* <p>
* 前端控制器
* </p>
*
* @author fan
* @since 2021-05-26
*/
@Controller
public class UserController {
@Resource
private IUserService userservice;
@RequestMapping("/addUser")
public String addUser( User user){
//System.out.println(name);
System.out.println("前端的参数:"+user);
int i = userservice.getBaseMapper().insert(user);
return "front/login";
}
@RequestMapping("/selectUserByName")
@ResponseBody
public User selectUserByName( String name){//查找方法,只用于回显数据
//System.out.println(name);
System.out.println("前端的参数:"+name);
User loginUserByName = userservice.getLoginUserByName(name);
return loginUserByName;//返回json数据
}
//登录后台管理系统
@RequestMapping("/selectUserByNameAndPwd")
@ResponseBody
public String selectUserByNameAndPwd( @RequestParam(required = true,value = "name") String name,
@RequestParam(required = true,value = "password") String password,
HttpSession session,
Model model){//查找方法,只用于回显数据
//System.out.println(name);
System.out.println("前端的参数ajax发送的=====:"+name+",password:"+password);
User adminUser = userservice.getLoginUserByNameAndPwd(name,password);
if(adminUser != null){
session.setAttribute("adminUser",adminUser);
//跳转到后台页面
System.out.println("跳转后台页面----");
return "1";
}else{
model.addAttribute("admin_msg","用户名或者密码不正确");
return "0";
}
}
@RequestMapping("/toadminHtml")
public String toadminTest(Model model){
return "admin/adminx";
}
@RequestMapping("/updateUser")//修改提交,注意修改是不需要分页参数的
public String updateUser(
User user
){
//System.out.println(name);
System.out.println("前端的参数:"+user);
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id",user.getId());
int update = userservice.getBaseMapper().updateById(user);
HashMap<String, Object> map = new HashMap<>();
return "admin/adminx";
}
//分页getUserByPage
@ResponseBody
@RequestMapping("/getUserByPage")
public Map<String,Object> getUserByPage(@RequestParam(required = true,defaultValue = "1",value = "pageNum")String pageNum
, @RequestParam(required = false,defaultValue = "3",value = "pageSize")String pageSize
){
Page<User> userPage = new Page<User>(Long.parseLong(pageNum), Long.parseLong(pageSize));
Page<User> page = userservice.getBaseMapper().selectPage(userPage, null);
HashMap<String, Object> map = new HashMap<>();
map.put("code","0");
map.put("msg","ok");
map.put("count",page.getTotal());
map.put("data",page.getRecords());
return map;
}
//删除delUserById
@RequestMapping("/delUserById")
public String delUserById(@RequestParam("id") Integer id){
int i = userservice.getBaseMapper().deleteById(id);
return "admin/adminx";
}
//批量删除
@RequestMapping("/batchDelUserByIds")
public String batchDelUserByIds(@RequestParam("ids") String ids){
System.out.println("ids:"+ids);
String[] split = ids.split(",");
List<String> strIds = Arrays.asList(split);//参数需要一个集合的
int i = userservice.getBaseMapper().deleteBatchIds(strIds);
return "admin/adminx";
}
}