首页 > 其他分享 >springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能

springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能

时间:2023-12-13 13:37:58浏览次数:35  
标签:shrimpking vue return springboot 小白 import com id name


还是接着之前的内容,我把新增的功能代码贴出来,给大家参考学习。

数据库

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>

测试

验证码

springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能_spring boot

 首页公告

springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能_spring boot_02

 公告管理

springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能_vue.js_03

 新增公告

springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能_spring boot_04

 编辑公告

springboot+vue小白升级之路14-实现系统公告首页公告展示、springboot+vue小白升级之路15-实现登录图像验证码功能_主键_05

标签:shrimpking,vue,return,springboot,小白,import,com,id,name
From: https://blog.51cto.com/u_15356972/8800943

相关文章

  • springboot+vue小白升级之路13-AOP实现登录、增删改查操作日志管理
    还是接着上一个的内容,我把这个新增的关于日志的功能代码都贴出来,供大家学习参考。数据库数据库droptableifexistsan_log;createtablean_log( idintnotnullauto_incrementprimarykeycomment'主键id', namevarchar(255)notnullcomment'操作内容', log_dateda......
  • springboot+vue小白升级之路06-实现文件上传和下载
    接着上一个的内容,代码我就不全部贴了,有变化的部分发一下springboot后端pojobook.javapackagecom.shrimpking.pojo;importjava.math.BigDecimal;importcom.baomidou.mybatisplus.annotation.TableName;importcom.baomidou.mybatisplus.annotation.IdType;importcom.baomid......
  • springboot+vue小白升级之路07-快速实现批量删除、小白升级之路08-实现批量导入导出ex
    我们接着之前的内容,全部代码我贴一下,大家参考使用。数据库droptableifexistsan_user;createtablean_user( idintnotnullauto_incrementprimarykeycomment'主键id', namevarchar(255)notnulluniquecomment'姓名', `password`varchar(255)notnullcomment......
  • springboot+vue小白升级之路04-实现登录注册功能和springboot+vue小白升级之路05-实现
    我们接着上一课的内容继续我还是尽量把全部代码都贴出来,方便大家学习。项目结构截图springboot后端pom.xml<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>......
  • springboot+vue小白升级之路11-请假申请,请假审核功能
    这部分代码,我们接着上一个的,就不全部贴出来了。把与这个功能有关的代码贴出来,大家参考。pom.xml<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></de......
  • springboot+vue小白升级之路03-实现增删改查、分页查询、模糊查询功能
    我们接着上一课的内容继续springboot后端pom.xml<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>......
  • Vue3 setup 方法的一些基本使用总结
    官网介绍:https://cn.vuejs.org/api/composition-api-setup.html基本使用setup()钩子是在组件中使用组合式API的入口,通常只在以下情况下使用:需要在非单文件组件中使用组合式API时。需要在基于选项式API的组件中集成基于组合式API的代码时。setup方法返回值:返回一......
  • [Vue]el-radio想要传入全部类型时,label绑定空字符串
    记录一下,原本以为不可以这样绑的。这样就可以空查了。 <el-form-itemlabel="类型"prop="type"><el-radiolabel=""v-model='query.type'@change="handleQuery">全部</el-radio><el-radiolabel="1"v-mode......
  • SpringBoot3
    入门创建项目<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.1</version></parent>导入场景,选择对应的场景启动器<dependencies><d......
  • SpringBoot2
    概述SpringBoot是整合Spring技术栈的一站式框架。SpringBoot是简化Spring技术栈的快速开发脚手架。优点创建独立Spring应用内嵌web服务器自动starter依赖,简化构建配置自动配置Spring以及第三方功能提供生产级别的监控、健康检查及外部化配置无代码生成、无需编写XML入......