还是接着之前的内容,我把新增的功能代码贴出来,给大家参考学习。
数据库
drop table if exists an_user;
create table an_user(
id int not null auto_increment primary key comment '主键id',
name varchar(255) not null unique comment '姓名',
`password` varchar(255) not null comment '密码',
age int(3) default null comment '年龄',
sex varchar(10) default null comment '性别',
phone varchar(20) default null comment '电话',
role varchar(255) default 'ROLE_' comment '角色名'
) comment '用户表';
insert into an_user values (1,'admin','1234',33,'男','13300000000','ROLE_ADMIN');
insert into an_user values (2,'zhangsan','1234',13,'女','13400000000','ROLE_TEACHER');
insert into an_user values (3,'lisi','1234',13,'女','13400000000','ROLE_STUDENT');
drop table if exists an_book;
create table an_book(
id int not null auto_increment primary key comment '主键id',
name varchar(100) not null comment '图书名称',
price decimal(6,2) default null comment '价格',
author varchar(50) default null comment '作者',
express varchar(200) default null comment '出版社',
img varchar(255) default null comment '图书封面',
type_id int not null comment '图书分类id'
) comment '图书表';
insert into an_book values(1,'三国演义',999.99,'罗贯中','商务出版社', 'http:',1);
drop table if exists an_book_type;
create table an_book_type(
id int not null auto_increment primary key comment '主键id',
name varchar(50) not null comment '分类名称',
description varchar(100) default null comment '分类描述'
) comment '图书分类';
insert into an_book_type values (1,'工具类','全部工具类书籍');
drop table if exists an_audit;
create table an_audit(
id int not null auto_increment primary key comment '主键id',
name varchar(100) not null comment '请假缘由',
`time` datetime default CURRENT_TIMESTAMP comment '请假日期',
`day` varchar(10) default null comment '请假天数',
user_id int not null comment '用户id',
`status` tinyint default 0 comment '审核状态,0未审核,1已通过,2未通过',
reason varchar(200) default null comment '审核意见'
) comment '请假审核表';
insert into an_audit values (1,'请假','2022-01-01','3天',1,0,'');
drop table if exists an_hotel;
create table an_hotel(
id int not null auto_increment primary key comment '主键id',
`name` varchar(100) not null comment '酒店名称',
price decimal(6,2) default null comment '入住价格',
img varchar(255) default null comment '酒店图片',
room_num int default null comment '剩余房间数'
) comment '酒店表';
insert into an_hotel values(1,'速八酒店',299,'',30);
insert into an_hotel values(2,'常青藤酒店',399,'',30);
insert into an_hotel values(3,'如家酒店',199,'',30);
drop table if exists an_reserve;
create table an_reserve(
id int not null auto_increment primary key comment '主键id',
hotel_id int not null comment '酒店id',
user_id int not null comment '用户id',
reserve_date datetime default CURRENT_TIMESTAMP comment '预订时间'
) comment '酒店预订记录表';
insert into an_reserve values(1,1,1,'2020-01-01');
drop table if exists an_log;
create table an_log(
id int not null auto_increment primary key comment '主键id',
name varchar(255) not null comment '操作内容',
log_date datetime default CURRENT_TIMESTAMP comment '日志时间',
user_name varchar(100) default null comment '操作人',
`ip` varchar(100) default null comment 'ip地址'
) comment '操作日志表';
insert into an_log values(1,'操作','2022-01-01','admin','192.168.0.1');
drop table if exists an_notice;
create table an_notice(
id int not null auto_increment primary key comment '主键id',
name varchar(255) not null comment '公告标题',
content text default null comment '公告内容',
pub_date datetime default CURRENT_TIMESTAMP comment '发布时间'
) comment '系统公告表';
insert into an_notice values(1,'紧急通知','云服务器奔溃了','2023-01-01');
pom.xml
<!-- 切面 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- 验证码 -->
<dependency>
<groupId>com.github.whvcse</groupId>
<artifactId>easy-captcha</artifactId>
<version>1.6.2</version>
</dependency>
application.properties
server.port=8089
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimeZone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=mysql123
#格式化时间
spring.jackson.date-format= yyyy-MM-dd
spring.jackson.time-zone= GMT+8
#日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
#配置别名
mybatis-plus.type-aliases-package=com.shrimpking.pojo
#开启逻辑删除,标识字段
mybatis-plus.global-config.db-config.logic-delete-field=is_deleted
#删除
mybatis-plus.global-config.db-config.logic-delete-value=1
#未删除
mybatis-plus.global-config.db-config.logic-not-delete-value=0
#swagger
spring.mvc.pathmatch.matching-strategy=ant_path_matcher
pojo
notice.java
package com.shrimpking.pojo;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.time.LocalDateTime;
import java.io.Serializable;
import java.util.Date;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 系统公告表
* </p>
*
* @author shrimpking
* @since 2023-11-15
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("an_notice")
@ApiModel(value="Notice对象", description="系统公告表")
public class Notice implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "公告标题")
private String name;
@ApiModelProperty(value = "公告内容")
private String content;
@ApiModelProperty(value = "发布时间")
private Date pubDate;
}
user.java
package com.shrimpking.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
* 用户表
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("an_user")
@ApiModel(value="User对象", description="用户表")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "主键id")
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@ApiModelProperty(value = "姓名")
private String name;
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "年龄")
private Integer age;
@ApiModelProperty(value = "性别")
private String sex;
@ApiModelProperty(value = "电话")
private String phone;
@ApiModelProperty(value = "角色名")
private String role;
@TableField(exist = false)
private String token;
}
mapper
noticeMapper.java
package com.shrimpking.mapper;
import com.shrimpking.pojo.Notice;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 系统公告表 Mapper 接口
* </p>
*
* @author shrimpking
* @since 2023-11-15
*/
public interface NoticeMapper extends BaseMapper<Notice> {
}
usermapper.java
package com.shrimpking.mapper;
import com.shrimpking.pojo.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.shrimpking.req.QueryParams;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
/**
* <p>
* 用户表 Mapper 接口
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
public interface UserMapper extends BaseMapper<User> {
/**
* 基于注解的方式
* @return
*/
@Select("select * from an_user")
List<User> getUsers();
/**
* 基于MapperXml的方式
* @return
*/
List<User> getAllUsers();
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
List<User> findBySearch2(@Param("queryParams") QueryParams queryParams);
}
mapperxml
noticeMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shrimpking.mapper.NoticeMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.shrimpking.pojo.Notice">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="content" property="content" />
<result column="pub_date" property="pubDate" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, name, content, pub_date
</sql>
</mapper>
userMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shrimpking.mapper.UserMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.shrimpking.pojo.User">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="password" property="password" />
<result column="age" property="age" />
<result column="sex" property="sex" />
<result column="phone" property="phone" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
id, name, password, age, sex, phone
</sql>
<!-- 基于MapperXml的方式 -->
<select id="getAllUsers" resultType="com.shrimpking.pojo.User">
select <include refid="Base_Column_List"/> from an_user
</select>
<!-- 基于MapperXml的方式,有条件时,获取全部数据 -->
<select id="findBySearch2" resultType="com.shrimpking.pojo.User">
select <include refid="Base_Column_List"/> from an_user
<where>
<if test="queryParams != null and queryParams.name != null and queryParams.name != ''">
or name like concat('%',#{queryParams.name},'%')
</if>
<if test="queryParams != null and queryParams.phone != null and queryParams.phone != ''">
or phone like concat('%',#{queryParams.phone},'%')
</if>
</where>
</select>
</mapper>
service
noticeService.java
package com.shrimpking.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Notice;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shrimpking.req.NoticeParams;
/**
* <p>
* 系统公告表 服务类
* </p>
*
* @author shrimpking
* @since 2023-11-15
*/
public interface NoticeService extends IService<Notice> {
IPage<Notice> findBySearchPage(NoticeParams noticeParams);
}
userService.java
package com.shrimpking.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.User;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shrimpking.req.QueryParams;
import com.shrimpking.req.UserParams;
import com.shrimpking.res.Result;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* <p>
* 用户表 服务类
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
public interface UserService extends IService<User> {
/**
* 基础注解的方式
* @return
*/
List<User> getUsers();
/**
* 基于MapperXml的方式
* @return
*/
List<User> getAllUsers();
/**
* 有查询条件,获取全部数据
* @param queryParams
* @return
*/
List<User> findBySearch(QueryParams queryParams);
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
List<User> findBySearch2(QueryParams queryParams);
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
IPage<User> findBySearchPage(QueryParams queryParams);
User login(UserParams userParams, HttpServletRequest request);
}
serviceImpl
noticeserviceImpl.java
package com.shrimpking.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shrimpking.pojo.Book;
import com.shrimpking.pojo.Notice;
import com.shrimpking.mapper.NoticeMapper;
import com.shrimpking.pojo.User;
import com.shrimpking.req.NoticeParams;
import com.shrimpking.service.NoticeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 系统公告表 服务实现类
* </p>
*
* @author shrimpking
* @since 2023-11-15
*/
@Service
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements NoticeService {
@Override
public IPage<Notice> findBySearchPage(NoticeParams noticeParams)
{
//声明分页
IPage<Notice> page = new Page<>(noticeParams.getCurrentPage(), noticeParams.getPageSize());
//声明查询条件
LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
//标题不为空,有条件值时,加入此条件
queryWrapper.like(
StringUtils.isNotBlank(noticeParams.getName()),
Notice::getName, noticeParams.getName())
//内容不为空,有条件值时,加入此条件
.like(
StringUtils.isNotBlank(noticeParams.getContent()),
Notice::getContent,noticeParams.getContent())
.orderByDesc(Notice::getId);
//返回结果
return this.baseMapper.selectPage(page, queryWrapper);
}
}
userServiceImpl.java
package com.shrimpking.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shrimpking.exception.CustomException;
import com.shrimpking.pojo.User;
import com.shrimpking.mapper.UserMapper;
import com.shrimpking.req.QueryParams;
import com.shrimpking.req.UserParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shrimpking.utils.CaptchaConfig;
import com.shrimpking.utils.JwtUtils;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* <p>
* 用户表 服务实现类
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private UserMapper userMapper;
/**
* 基于注解的方式
* @return
*/
@Override
public List<User> getUsers()
{
return this.userMapper.getUsers();
}
/**
* 基于MapperXml的方式
* @return
*/
@Override
public List<User> getAllUsers()
{
return this.userMapper.getAllUsers();
}
/**
* 有查询条件,获取全部数据
* @param queryParams
* @return
*/
@Override
public List<User> findBySearch(QueryParams queryParams)
{
//声明查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//姓名不为空,有条件值时,加入此条件
queryWrapper.like(
StringUtils.isNotBlank(queryParams.getName()),
User::getName,queryParams.getName())
//电话不为空,有条件值时,加入此条件
.or().like(
StringUtils.isNotBlank(queryParams.getPhone()),
User::getPhone,queryParams.getPhone());
//返回结果
return this.baseMapper.selectList(queryWrapper);
}
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
@Override
public List<User> findBySearch2(QueryParams queryParams)
{
return this.userMapper.findBySearch2(queryParams);
}
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
@Override
public IPage<User> findBySearchPage(QueryParams queryParams)
{
//声明分页
IPage<User> page = new Page<>(queryParams.getCurrentPage(),queryParams.getPageSize());
//声明查询条件
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
//姓名不为空,有条件值时,加入此条件
queryWrapper.ne(User::getRole,"ROLE_ADMIN")
.like(
StringUtils.isNotBlank(queryParams.getName()),
User::getName,queryParams.getName())
//电话不为空,有条件值时,加入此条件
.or().like(
StringUtils.isNotBlank(queryParams.getPhone()),
User::getPhone,queryParams.getPhone())
.orderByDesc(User::getId);
//返回结果
return this.baseMapper.selectPage(page, queryWrapper);
}
@Override
public User login(UserParams userParams, HttpServletRequest request)
{
//前端传的key
String key = userParams.getKey().toLowerCase();
//根据key,找到的后端存的验证码
String code = CaptchaConfig.CAPTCHA_MAP.get(key);
//判断验证码
if(!userParams.getVerCode().equals(code)){
//清除验证码,session
CaptchaUtil.clear(request);
throw new CustomException("验证码不正确,请重新输入");
}
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,userParams.getName());
User one = this.baseMapper.selectOne(queryWrapper);
if(one == null || !one.getPassword().equals(userParams.getPassword())){
throw new CustomException("用户名或密码错误");
}
//如果查询出来,有用户,生成token,与user一起返回
String token = JwtUtils.createToken(one.getId().toString(), one.getPassword());
one.setToken(token);
//屏蔽密码
one.setPassword("***");
//清除map中的验证码
CaptchaConfig.CAPTCHA_MAP.remove(key);
return one;
}
}
controller
noticeController.java
package com.shrimpking.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shrimpking.annotation.AutoLog;
import com.shrimpking.pojo.Notice;
import com.shrimpking.pojo.User;
import com.shrimpking.req.NoticeParams;
import com.shrimpking.req.QueryParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.NoticeService;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 系统公告表 前端控制器
* </p>
*
* @author shrimpking
* @since 2023-11-15
*/
@RestController
@RequestMapping("/notice")
public class NoticeController {
@Autowired
private NoticeService noticeService;
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
@GetMapping("/searchPage")
public Result findBySearchPage(NoticeParams noticeParams){
IPage<Notice> list = this.noticeService.findBySearchPage(noticeParams);
return Result.success(list);
}
@AutoLog("新增公告")
@PostMapping("/save")
public Result save(@RequestBody Notice notice){
boolean save = this.noticeService.save(notice);
if(!save) return Result.error("保存失败");
return Result.success("保存成功");
}
@AutoLog("更新公告")
@PostMapping("/update")
public Result update(@RequestBody Notice notice){
boolean save = this.noticeService.updateById(notice);
if(!save) return Result.error("更新失败");
return Result.success("更新成功");
}
@AutoLog("删除公告")
@DeleteMapping("/delete")
public Result delete(@RequestParam("id") Integer id){
boolean remove = this.noticeService.removeById(id);
if(!remove) return Result.error("删除失败");
return Result.success("删除成功");
}
@GetMapping("/findTop")
public Result findTop(){
//获取top 5
IPage<Notice> page = new Page<>(1,5);
LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.orderByDesc(Notice::getPubDate);
IPage<Notice> resultPage = this.noticeService.page(page, queryWrapper);
return Result.success(resultPage);
}
}
captchaController.java
package com.shrimpking.controller;
import com.shrimpking.utils.CaptchaConfig;
import com.wf.captcha.ArithmeticCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import com.wf.captcha.utils.CaptchaUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/16 11:21
*/
@RestController
public class CaptchaController
{
@GetMapping("/captcha")
public void captcha(
@RequestParam String key,
HttpServletRequest request,
HttpServletResponse response) throws IOException
{
//png类型,宽度135,高度33,长度5位
SpecCaptcha captcha = new SpecCaptcha(135,33,4);
//设置类型
captcha.setCharType(Captcha.TYPE_NUM_AND_UPPER);
//存到map中备用
CaptchaConfig.CAPTCHA_MAP.put(key, captcha.text().toLowerCase());
//输出
CaptchaUtil.out(captcha,request,response);
// //算数类型
// ArithmeticCaptcha captcha1 = new ArithmeticCaptcha(135,33);
// //几位数运算,默认是2两位
// captcha1.setLen(2);
// //获取运算的公式 3+2= ?
// captcha1.getArithmeticString();
// //获取运算结果
// CaptchaConfig.CAPTCHA_MAP.put(key, captcha1.text().toLowerCase());
// //输出
// CaptchaUtil.out(captcha1,request,response);
}
}
usercontroller.java
package com.shrimpking.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.annotation.AutoLog;
import com.shrimpking.exception.CustomException;
import com.shrimpking.pojo.User;
import com.shrimpking.req.QueryParams;
import com.shrimpking.req.UserParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.UserService;
import net.bytebuddy.implementation.bytecode.Throw;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
/**
* <p>
* 用户表 前端控制器
* </p>
*
* @author shrimpking
* @since 2023-11-09
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 3基于mybatisplus的方式
* @return
*/
@GetMapping("/getList")
public List<User> getUserList(){
return this.userService.list();
//http://localhost:8089/user/getList
}
/**
* 2基于注解的方式
*
* @return
*/
@GetMapping("/getUsers")
public List<User> getUsers(){
return this.userService.getUsers();
//http://localhost:8089/user/getUsers
//[{"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]
}
/**
* 1基于MapperXml的方式
* @return
*/
@GetMapping("/getAll")
public List<User> getAllUsers(){
return this.userService.getAllUsers();
//http://localhost:8089/user/getAll
//[{"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]
}
/**
* 3基于mybatisplus的方式
* @return
*/
@GetMapping("/getList2")
public Result getUserList2(){
return Result.success(this.userService.list());
//http://localhost:8089/user/getList2
//{"code":"200","msg":"成功","data":[
// {"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]}
}
/**
* 2基于注解的方式
*
* @return
*/
@GetMapping("/getUsers2")
public Result getUsers2(){
return Result.success(this.userService.getUsers());
//http://localhost:8089/user/getUsers2
//{"code":"200","msg":"成功","data":[
// {"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]}
}
/**
* 1基于MapperXml的方式
* @return
*/
@GetMapping("/getAll2")
public Result getAllUsers2(){
return Result.success(this.userService.getUsers());
//http://localhost:8089/user/getAll2
//{"code":"200","msg":"成功","data":[
// {"id":1,"name":"zhangsan","password":"1234","age":33,"sex":"男","phone":"13300000000"},
// {"id":2,"name":"lisi","password":"1234","age":13,"sex":"女","phone":"13400000000"}]}
}
/**
* 获取全部数据
* @return
*/
@GetMapping("/findAll")
public Result findAll(){
return Result.success(this.userService.list());
}
/**
* 有查询条件时,获取全部数据
* @param queryParams
* @return
*/
@GetMapping("/search")
public Result findBySearch(QueryParams queryParams){
List<User> list = this.userService.findBySearch(queryParams);
return Result.success(list);
}
/**
* 基于MapperXml的,有条件,获取全部数据
* @param queryParams
* @return
*/
@GetMapping("/search2")
public Result findBySearch2(QueryParams queryParams){
List<User> list = this.userService.findBySearch2(queryParams);
return Result.success(list);
}
/**
* 有查询条件时,获取分页数据
* @param queryParams
* @return
*/
@GetMapping("/searchPage")
public Result findBySearchPage(QueryParams queryParams){
IPage<User> list = this.userService.findBySearchPage(queryParams);
return Result.success(list);
}
@PostMapping("/save")
public Result save(@RequestBody User user){
//先查询有无同名用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
int count = this.userService.count(queryWrapper);
if(count > 0) return Result.error("此用户名已存在");
boolean save = this.userService.save(user);
if(!save) return Result.error("保存失败");
return Result.success("保存成功");
}
@PostMapping("/update")
public Result update(@RequestBody User user){
//先查询有无同名用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
User one = this.userService.getOne(queryWrapper);
if(one != null && !one.getId().equals(user.getId())){
return Result.error("此用户名已存在");
}
boolean save = this.userService.updateById(user);
if(!save) return Result.error("更新失败");
return Result.success("更新成功");
}
@DeleteMapping("/delete")
public Result delete(@RequestParam("id") Integer id){
boolean remove = this.userService.removeById(id);
if(!remove) return Result.error("删除失败");
return Result.success("删除成功");
}
@AutoLog("用户登录")
@PostMapping("/login")
public Result login(@RequestBody UserParams userParams, HttpServletRequest request){
User login = this.userService.login(userParams,request);
return Result.success(login);
}
@PostMapping("/register")
public Result register(@RequestBody User user){
//先查询有无同名用户
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getName,user.getName());
int count = this.userService.count(queryWrapper);
if(count > 0) {
throw new CustomException("此用户已经存在,请重新注册!");
}
//默认是学生
//user.setRole("ROLE_STUDENT");
boolean save = this.userService.save(user);
if(!save) return Result.error("注册失败");
return Result.success("注册成功");
}
@AutoLog("用户退出")
@PostMapping("/logout")
public Result logout(@RequestBody User user){
if(user != null){
//模拟做一些事情
}
return Result.success("退出成功!");
}
}
req
noticeParams.java
package com.shrimpking.req;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/12 21:10
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class NoticeParams extends QueryParams
{
private String content;
}
userParam.java
package com.shrimpking.req;
import com.shrimpking.pojo.User;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/16 13:34
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class UserParams extends User
{
private String verCode;
private String key;
}
utils
CaptchaConfig.java
package com.shrimpking.utils;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* Created by IntelliJ IDEA.
*
* @Author : Shrimpking
* @create 2023/11/16 12:18
*/
@Component
public class CaptchaConfig
{
public static Map<String,String> CAPTCHA_MAP = new HashMap<>();
}
router
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/login',
name:'LoginView',
component: ()=> import('@/views/LoginView.vue'),
},
{
path:'/register',
name: 'Register',
component: ()=> import('@/views/RegisterView.vue'),
},
{
path: '/',
redirect: '/home',
name: 'Layout',
component: ()=> import('@/views/Layout.vue'),
children:[
{
path: 'home',
name: 'HomeView',
component: ()=> import('@/views/HomeView.vue')
},
{
path: 'admin',
name: 'AdminView',
component: ()=> import('@/views/User/AdminView.vue'),
},
{
path:'user',
name:'UserView',
component: ()=> import('@/views/User/UserView.vue'),
},
{
path:'book',
name:'BookView',
component: ()=> import('@/views/Info/BookView.vue'),
},
{
path:'type',
name:'BookType',
component: ()=> import('@/views/Info/BookType.vue'),
},
{
path:'audit',
name:'AuditView',
component: ()=> import('@/views/AuditView.vue'),
},
{
path:'hotel',
name:'HotelView',
component: ()=> import('@/views/hotel/HotelView.vue'),
},
{
path:'reserve',
name:'ReserveView',
component: ()=> import('@/views/hotel/ReserveView.vue'),
},
{
path:'log',
name:'LogView',
component: ()=> import('@/views/Log/LogView.vue'),
},
{
path:'notice',
name:'NoticeView',
component: ()=> import('@/views/Notice/NoticeView.vue'),
},
]
},
]
const router = new VueRouter({
routes
})
//白名单
const IGNORE_URLS = ['/login','/register'];
//前置守卫
router.beforeEach((to, from, next) => {
//在白名单中,放行
if(IGNORE_URLS.includes(to.path)){
next();
}
//获取用户
let admin = JSON.parse(window.localStorage.getItem('access-admin'));
if(!admin && !IGNORE_URLS.includes(to.path)){
//没有登录 ,没有在白名单中,跳转登录
return next('/login');
}
next();
});
export default router
notice.vue
<template>
<div>
<!-- 搜索区域 -->
<div style="margin-bottom:15px;">
<el-input
v-model="searchForm.name"
style="width:200px;"
placeholder="请输入标题"
@clear="doSearch"
@keypress.native.enter="doSearch"
clearable>
</el-input>
<el-input
v-model="searchForm.content"
style="width:200px;margin-left: 10px;"
placeholder="请输入内容"
@clear="doSearch"
@keypress.native.enter="doSearch"
clearable>
</el-input>
<el-button
type="warning"
style="margin-left: 10px;"
icon="el-icon-search"
@click="doSearch">查询</el-button>
<el-button
type="primary"
style="margin-left: 10px;"
icon="el-icon-toilet-paper"
@click="clearSearch">清空</el-button>
<el-button
type="primary"
style="margin-left: 10px;"
icon="el-icon-plus" @click="addBtn">新增</el-button>
</div>
<!-- 表格区域 -->
<el-table
:data="tableData"
border
style="width: 100%">
<el-table-column
prop="id"
label="ID">
</el-table-column>
<el-table-column
prop="name"
label="公告标题"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="content"
label="公告内容"
show-overflow-tooltip>
</el-table-column>
<el-table-column
prop="pubDate"
label="发布时间">
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button type="primary" icon="el-icon-edit" @click="editBtn(scope.row)">编辑</el-button>
<el-button type="danger" icon="el-icon-delete" @click="deleteBtn(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页区域 -->
<div style="margin-top:15px;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="searchForm.currentPage"
:page-sizes="[2, 5, 10, 20]"
:page-size="searchForm.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
<!-- 对话框 -->
<div>
<el-dialog
:title="dialogTitle"
:visible.sync="dialogFormVisible"
:close-on-click-modal="false"
@close="closeDialog"
width="50%">
<el-form
:model="addForm"
:rules="rules"
ref="addForm"
:label-width="formLabelWidth"
label-position="left">
<el-form-item label="标题" prop="name">
<el-input
v-model="addForm.name"
maxlength="50"
minlength="1"
:show-word-limit="true"
clearable></el-input>
</el-form-item>
<el-form-item label="内容" prop="content">
<el-input
type="textarea"
:rows="22"
maxlength="800"
minlength="1"
:show-word-limit="true"
resize="none"
v-model="addForm.content"
clearable></el-input>
</el-form-item>
<el-form-item label="发布时间" prop="pubDate">
<el-date-picker
v-model="addForm.pubDate"
type="datetime"
placeholder="选择日期时间"
default-time="12:00:00">
</el-date-picker>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="resetBtn" v-show="dialogTitle === '新增公告'">重 置</el-button>
<el-button type="primary" @click="submitBtn">确 定</el-button>
</div>
</el-dialog>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "AdminView",
data() {
return {
//添加表单
addForm:{
name:'',
content:'',
pubDate:'',
},
rules:{
name:[{required: true, message: '请输入标题', trigger: 'blur'}],
content:[{required: true, message: '请输入内容', trigger: 'blur'}],
pubDate:[{required: true, message: '请选择时间', trigger: 'blur'}],
},
//表单标题宽度
formLabelWidth:'80px',
//对话框标题
dialogTitle:'',
//对话框
dialogFormVisible: false,
//搜索条件
searchForm:{
name: '',
content: '',
currentPage: 1,
pageSize: 5
},
tableData: [],
total:0
}
},
methods: {
//删除
deleteBtn(row){
this.$confirm(`您确定要删除【${row.name}】吗`,'删除提示',{
confirmButtonText:'删除',
cancelButtonText:'取消',
type:'warning',
}).then(()=>{
request.delete('/notice/delete',{
params:{ id : row.id}
}).then(res => {
if(res.code === '200'){
this.$message.success(res.data);
this.doSearch();
}else {
this.$message.error(res.msg);
this.doSearch();
}
})
}).catch(_=>{
this.$message.warning('已取消删除');
})
},
//编辑
editBtn(row){
let obj = JSON.parse(JSON.stringify(row));
this.addForm = obj;
this.dialogTitle = "编辑公告";
this.dialogFormVisible = true;
},
//关闭对话框
closeDialog(){
this.resetBtn();
this.dialogFormVisible = false;
},
//新增保存
submitBtn(){
this.$refs.addForm.validate((valid)=>{
if(valid){
//校验通过
//有id,编辑,没有id是新增
request.post(this.addForm.id ? '/notice/update':'/notice/save',this.addForm)
.then(res=>{
if(res.code === '200'){
this.$message.success(res.data);
this.resetBtn();
this.dialogFormVisible = false;
this.doSearch();
}else {
this.$message.error(res.msg);
}
})
}
})
},
//新增重置
resetBtn(){
this.$refs.addForm.resetFields();
//修复bug
this.addForm = {};
},
addBtn(){
this.dialogTitle = '新增公告';
this.dialogFormVisible = true;
},
clearSearch(){
this.searchForm.name = '';
this.searchForm.content = '';
this.doSearch();
},
//搜索
doSearch(){
//修复bug
this.searchForm.currentPage = 1;
this.getData();
},
handleSizeChange(val) {
this.searchForm.pageSize = val;
this.searchForm.currentPage = 1;
this.getData();
},
handleCurrentChange(val) {
this.searchForm.currentPage = val;
this.getData();
},
//获取数据
getData(){
request.get('/notice/searchPage',{
params: this.searchForm
}).then(res=>{
if(res.code === '200'){
this.tableData = res.data.records; //数据
this.searchForm.currentPage = res.data.current; //当前页
this.searchForm.pageSize = res.data.size; //页条数
this.total = res.data.total; //总条数
}else {
this.$message.error(res.msg);
}
});
}
},
created(){
//获取数据
this.getData();
}
}
</script>
<style scoped>
</style>
layout.vue
<template>
<div>
<el-container class="container">
<el-header class="header-area">
<img src="@/assets/logo.png" alt="logo" class="logo">
<span class="title">手牵手带小白做毕设</span>
<span class="admin-info">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
用户: <strong>{{ admin.name }}</strong>
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="logout">退出</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
</el-header>
<el-container class="middle-area">
<el-aside class="left-aside">
<el-menu
:default-active="$route.path"
class="el-menu-vertical-demo"
background-color="#545c64"
text-color="#fff"
active-text-color="#ffd04b"
:unique-opened="true"
router>
<el-menu-item index="/home">
<i class="el-icon-menu"></i>
<span slot="title">系统首页</span>
</el-menu-item>
<el-submenu index="/admin" v-if="admin.role === 'ROLE_ADMIN'">
<template slot="title">
<i class="el-icon-location"></i>
<span>用户管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/admin">用户信息</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="/book">
<template slot="title">
<i class="el-icon-location"></i>
<span>信息管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/book">图书信息</el-menu-item>
<el-menu-item index="/type">图书分类</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="/audit">
<template slot="title">
<i class="el-icon-location"></i>
<span>请假管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/audit">请假申请</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="/hotel">
<template slot="title">
<i class="el-icon-location"></i>
<span>酒店管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/hotel">酒店信息</el-menu-item>
<el-menu-item index="/reserve">预订记录</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="/log" v-if="admin.role === 'ROLE_ADMIN'">
<template slot="title">
<i class="el-icon-location"></i>
<span>日志管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/log">操作日志</el-menu-item>
</el-menu-item-group>
</el-submenu>
<el-submenu index="/notice" v-if="admin.role === 'ROLE_ADMIN'">
<template slot="title">
<i class="el-icon-location"></i>
<span>公告管理</span>
</template>
<el-menu-item-group>
<el-menu-item index="/notice">公告信息</el-menu-item>
</el-menu-item-group>
</el-submenu>
</el-menu>
</el-aside>
<el-main>
<router-view/>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "Layout",
computed: {
admin(){
return JSON.parse(window.localStorage.getItem('access-admin')) || { name: '未登录'};
}
},
methods: {
//下拉菜单命令
handleCommand(command){
if (command === 'logout') {
this.logout();
}
},
//退出
logout(){
request.post('/user/logout',this.admin).then(res => {
window.localStorage.clear();
this.$message.success(res.data);
this.$router.replace('/login');
})
}
}
}
</script>
<style lang="scss" scoped>
.container{
height: 100vh;
.header-area{
background-color: #4c535a;
.logo {
width: 40px;
position: relative;
top: 10px;
}
.title{
font-size: 20px;
margin-left: 15px;
color: white;
}
.admin-info{
float: right;
margin-right: 30px;
line-height: 60px;
.el-dropdown-link{
color: #cccccc;
}
}
}
.middle-area{
.left-aside{
overflow: hidden;
height: 100%;
/*background-color: #545c64;*/
width:230px !important;
.el-menu-vertical-demo{
height: 100%;
}
}
}
}
</style>
loginview.vue
<template>
<div class="register-area">
<h1 class="title">手牵手带小白做毕设</h1>
<el-form
:model="loginForm"
:rules="rules"
ref="loginForm"
class="form-demo"
label-width="100px;"
label-postion="left">
<el-form-item prop="name">
<el-input
v-model="loginForm.name"
placeholder="用户名"
clearable>
<template slot="prepend"><i class="el-icon-user-solid"></i></template>
</el-input>
</el-form-item>
<el-form-item prop="password">
<el-input
v-model="loginForm.password"
placeholder="密码"
show-password
clearable>
<template slot="prepend"><i class="el-icon-lock"></i></template>
</el-input>
</el-form-item>
<el-form-item prop="verCode">
<div style="display: flex;justify-content: center;">
<el-input
v-model="loginForm.verCode"
prefix-icon="el-icon-user"
style="width: 60%;margin-right: 10px;"
placeholder="请输入验证码"></el-input>
<img :src="captchaUrl" alt="" @click="getVerCode" style="width:140px;height: 33px;">
</div>
</el-form-item>
<el-button type="primary" @click="login" class="login-btn">登 录</el-button>
<el-button type="text" @click="toRegister" class="register-btn">没有账号,注册一下</el-button>
</el-form>
<div>
</div>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "LoginView",
data(){
return {
//验证码接口地址
verUrl:'http://localhost:8089/api/captcha',
//验证码图片地址
captchaUrl:'',
loginForm: {
name:'',
password:'',
verCode: '',
key:'',
},
rules: {
name: [{ required: true ,message: '请输入用户名', trigger: 'blur'}],
password: [{ required: true ,message: '请输入密码', trigger: 'blur'}],
verCode: [{ required: true ,message: '请输入验证码', trigger: 'blur'}],
}
}
},
methods: {
//验证码刷新
getVerCode(){
this.loginForm.key = Math.random();
this.captchaUrl = this.verUrl + '?key=' + this.loginForm.key;
},
//注册
toRegister(){
this.$router.replace('/register');
},
login(){
this.$refs.loginForm.validate((valid)=>{
if(valid){
request.post('/user/login',this.loginForm)
.then(res=>{
if(res.code === '200'){
this.$message.success(res.msg);
window.localStorage.setItem('access-admin',JSON.stringify(res.data));
this.$router.replace('/home');
}else {
this.$message.error(res.msg);
//重新获取验证码
this.getVerCode();
this.loginForm.verCode = '';
}
})
}
})
}
},
created(){
//获取验证码
this.getVerCode();
}
}
</script>
<style lang="scss" scoped>
.register-area{
width: 400px;
height: 360px;
border-radius: 15px;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-75%);
padding: 10px;
background-color: rgba(107,149,224,0.5);
.title{
text-align: center;
margin-bottom: 30px;
}
.form-demo{
width: 80%;
margin: 0 auto;
.login-btn{
width: 100%;
margin-top: 12px;
height: 40px;
}
.register-btn{
width: 100%;
margin-top: 8px;
text-align: center;
color: #ffffff;
}
}
}
</style>
homeview.vue
<template>
<div>
<h2>系统公告</h2>
<el-row style="margin-top: 15px;">
<el-col :span="12">
<el-collapse v-model="activeName" accordion>
<el-collapse-item
v-for="item in noticeData"
:title="item.name"
:name="item.id">
<div><strong>公告内容:</strong>{{ item.content }}</div>
<div><strong>发布时间:</strong>{{ item.pubDate }}</div>
</el-collapse-item>
</el-collapse>
</el-col>
<el-col :span="12">
</el-col>
</el-row>
</div>
</template>
<script>
import request from "@/utils/request";
export default {
name: "HomeView",
data() {
return {
activeName: '',
noticeData:[]
};
},
methods:{
getData(){
request.get('/notice/findTop').then(res=>{
if(res.code === '200'){
console.log(res)
this.noticeData = res.data.records;
//默认第一个新闻打开
this.activeName = res.data.records[0].id;
}
})
}
},
mounted(){
//获取数据
this.getData()
}
}
</script>
<style lang="scss" scoped>
</style>