springboot+vue小白升级之路12-实现酒店预订、学生选课、教室预订、图书借阅等功能

661 篇文章 3 订阅
112 篇文章 0 订阅

还是接着上一个的内容,我把新增加的代码贴出来,供大家学习参考。

数据库

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');









pom.xml

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>

        <!--swagger依赖-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--swagger ui-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>
        <!-- jwt验证       -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.10.3</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.7</version>
        </dependency>
        <!-- excel导出修复bug       -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.1.2</version>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.apache.commons</groupId>-->
<!--            <artifactId>commons-compress</artifactId>-->
<!--            <version>1.21</version>-->
<!--        </dependency>-->
    </dependencies>

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=UTC
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

hotel.java

package com.shrimpking.pojo;

import java.math.BigDecimal;
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-14
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("an_hotel")
@ApiModel(value="Hotel对象", description="酒店表")
public class Hotel 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 Double price;

    @ApiModelProperty(value = "酒店图片")
    private String img;

    @ApiModelProperty(value = "剩余房间数")
    private Integer roomNum;
}

reserve.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-14
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("an_reserve")
@ApiModel(value="Reserve对象", description="酒店预订记录表")
public class Reserve implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "主键id")
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;

    @ApiModelProperty(value = "酒店id")
    private Integer hotelId;

    @ApiModelProperty(value = "用户id")
    private Integer userId;

    @ApiModelProperty(value = "预订时间")
    private Date reserveDate;


}

mapper

hotelmapper.java

package com.shrimpking.mapper;

import com.shrimpking.pojo.Hotel;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * 酒店表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
public interface HotelMapper extends BaseMapper<Hotel> {

}

reserveMapper.java

package com.shrimpking.mapper;

import com.shrimpking.pojo.Reserve;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

/**
 * <p>
 * 酒店预订记录表 Mapper 接口
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
public interface ReserveMapper extends BaseMapper<Reserve> {

}

Mapperxml

hotelMapper.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.HotelMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Hotel">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="price" property="price" />
        <result column="img" property="img" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, name, price, img
    </sql>

</mapper>

reserveMapper.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.ReserveMapper">

    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.shrimpking.pojo.Reserve">
        <id column="id" property="id" />
        <result column="hotel_id" property="hotelId" />
        <result column="user_id" property="userId" />
        <result column="reserve_date" property="reserveDate" />
    </resultMap>

    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, hotel_id, user_id, reserve_date
    </sql>

</mapper>

service

hotelServcie.java

package com.shrimpking.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Hotel;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shrimpking.req.QueryParams;

/**
 * <p>
 * 酒店表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
public interface HotelService extends IService<Hotel> {

    IPage<Hotel> findBySearchPage(QueryParams queryParams);
}

reserveService.java

package com.shrimpking.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Reserve;
import com.baomidou.mybatisplus.extension.service.IService;
import com.shrimpking.req.ReserveParams;

/**
 * <p>
 * 酒店预订记录表 服务类
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
public interface ReserveService extends IService<Reserve> {

    IPage<Reserve> findBySearchPage(ReserveParams reserveParams);
}

serviceImpl

hotelServiceImpl.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.Hotel;
import com.shrimpking.mapper.HotelMapper;
import com.shrimpking.req.QueryParams;
import com.shrimpking.service.HotelService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 酒店表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
@Service
public class HotelServiceImpl extends ServiceImpl<HotelMapper, Hotel> implements HotelService {

    @Override
    public IPage<Hotel> findBySearchPage(QueryParams queryParams)
    {
        //声明分页
        IPage<Hotel> page = new Page<>(queryParams.getCurrentPage(), queryParams.getPageSize());
        //声明查询条件
        LambdaQueryWrapper<Hotel> queryWrapper = new LambdaQueryWrapper<>();
        //酒店名称不为空,有条件值时,加入此条件
        queryWrapper.like(
                StringUtils.isNotBlank(queryParams.getName()),
                Hotel::getName, queryParams.getName())
                .orderByDesc(Hotel::getId);
        //返回结果
        return this.baseMapper.selectPage(page, queryWrapper);
    }
}

reserveServiceImpl.java

package com.shrimpking.service.impl;

import cn.hutool.core.util.ObjectUtil;
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.Audit;
import com.shrimpking.pojo.Book;
import com.shrimpking.pojo.Reserve;
import com.shrimpking.mapper.ReserveMapper;
import com.shrimpking.pojo.User;
import com.shrimpking.req.ReserveParams;
import com.shrimpking.service.ReserveService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shrimpking.utils.JwtUtils;
import org.springframework.stereotype.Service;

/**
 * <p>
 * 酒店预订记录表 服务实现类
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
@Service
public class ReserveServiceImpl extends ServiceImpl<ReserveMapper, Reserve> implements ReserveService {

    @Override
    public IPage<Reserve> findBySearchPage(ReserveParams reserveParams)
    {
        //声明分页
        IPage<Reserve> page = new Page<>(reserveParams.getCurrentPage(), reserveParams.getPageSize());
        //声明查询条件
        LambdaQueryWrapper<Reserve> queryWrapper = new LambdaQueryWrapper<>();
        //酒店不为空,有条件值时,加入此条件
        queryWrapper.eq(
                ObjectUtil.isNotNull(reserveParams.getHotelId()),
                Reserve::getHotelId, reserveParams.getHotelId());
        //获取当前用户
        User user = JwtUtils.getCurrentUser();
        if(user != null){
            //用户不为空,有条件值时,加入此条件
            //管理员看全部数据,其他权限只能看自己的
            queryWrapper.eq(!user.getRole().equals("ROLE_ADMIN"),
                            Reserve::getUserId, reserveParams.getUserId());
        } else {
            throw new CustomException("从token中未获取到用户信息,请重新登录!");
        }

        queryWrapper.orderByDesc(Reserve::getId);
        //返回结果
        return this.baseMapper.selectPage(page, queryWrapper);
    }
}

controller

hotelController.java

package com.shrimpking.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Book;
import com.shrimpking.pojo.Hotel;
import com.shrimpking.req.BookParams;
import com.shrimpking.req.QueryParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.HotelService;
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;

import java.util.List;

/**
 * <p>
 * 酒店表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
@RestController
@RequestMapping("/hotel")
public class HotelController {

    @Autowired
    private HotelService hotelService;

    /**
     * 有查询条件时,获取分页数据
     * @param queryParams
     * @return
     */
    @GetMapping("/searchPage")
    public Result findBySearchPage(QueryParams queryParams){
        IPage<Hotel> list = this.hotelService.findBySearchPage(queryParams);
        return Result.success(list);
    }

    @PostMapping("/save")
    public Result save(@RequestBody Hotel hotel){
        //先查询有无同名酒店
        LambdaQueryWrapper<Hotel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Hotel::getName,hotel.getName());
        int count = this.hotelService.count(queryWrapper);
        if(count > 0) return Result.error("此酒店已存在");

        boolean save = this.hotelService.save(hotel);
        if(!save) return Result.error("保存失败");
        return Result.success("保存成功");
    }

    @PostMapping("/update")
    public Result update(@RequestBody Hotel hotel){
        //先查询有无同名酒店
        LambdaQueryWrapper<Hotel> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Hotel::getName,hotel.getName());
        Hotel one = this.hotelService.getOne(queryWrapper);
        if(one != null && !one.getId().equals(hotel.getId())){
            return Result.error("此酒店已存在");
        }

        boolean save = this.hotelService.updateById(hotel);
        if(!save) return Result.error("更新失败");
        return Result.success("更新成功");
    }

    @DeleteMapping("/delete")
    public Result delete(@RequestParam("id") Integer id){
        boolean remove = this.hotelService.removeById(id);
        if(!remove) return Result.error("删除失败");
        return Result.success("删除成功");
    }

    @GetMapping("/list")
    public Result list(){
        List<Hotel> list = this.hotelService.list();
        return Result.success(list);
    }

}

reserveController.java

package com.shrimpking.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.shrimpking.pojo.Hotel;
import com.shrimpking.pojo.Reserve;
import com.shrimpking.req.QueryParams;
import com.shrimpking.req.ReserveParams;
import com.shrimpking.res.Result;
import com.shrimpking.service.HotelService;
import com.shrimpking.service.ReserveService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
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;

/**
 * <p>
 * 酒店预订记录表 前端控制器
 * </p>
 *
 * @author shrimpking
 * @since 2023-11-14
 */
@RestController
@RequestMapping("/reserve")
public class ReserveController {

    @Autowired
    private ReserveService reserveService;

    @Autowired
    private HotelService hotelService;

    /**
     * 有查询条件时,获取分页数据
     * @param queryParams
     * @return
     */
    @GetMapping("/searchPage")
    public Result findBySearchPage(ReserveParams reserveParams){
        IPage<Reserve> list = this.reserveService.findBySearchPage(reserveParams);
        return Result.success(list);
    }

    @PostMapping("/save")
    @Transactional
    public Result save(@RequestBody Reserve reserve){
        //先查询酒店剩余房间是否为零
        Hotel hotel = this.hotelService.getById(reserve.getHotelId());
        if(hotel.getRoomNum() <= 0){
            return  Result.error("酒店剩余房间已无,无法预订酒店!");
        }
        //再保存
        boolean save = this.reserveService.save(reserve);

        //对酒店剩余房间减一
        hotel.setRoomNum(hotel.getRoomNum()-1);
        boolean update = this.hotelService.updateById(hotel);

        if(!save) return Result.error("预订失败");
        return Result.success("预订成功");
    }

    @PostMapping("/update")
    public Result update(@RequestBody Reserve reserve){
        boolean save = this.reserveService.updateById(reserve);
        if(!save) return Result.error("更新失败");
        return Result.success("更新成功");
    }

    @PutMapping("/delete")
    @Transactional
    public Result delete(@RequestBody Reserve reserve){
        //先获取酒店,剩余房间+1
        Hotel hotel = this.hotelService.getById(reserve.getHotelId());
        if(hotel != null){
            hotel.setRoomNum(hotel.getRoomNum() + 1);
        }
        boolean update = this.hotelService.updateById(hotel);
        //再删除
        boolean remove = this.reserveService.removeById(reserve.getId());
        if(!remove) return Result.error("退订失败");
        return Result.success("退订成功");
    }
}

req

reserveParams.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 ReserveParams extends QueryParams
{
    private Integer hotelId;
    private Integer userId;
}

jwtutils.java

package com.shrimpking.utils;

import ch.qos.logback.classic.turbo.TurboFilter;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.shrimpking.exception.CustomException;
import com.shrimpking.pojo.User;
import com.shrimpking.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.resource.OAuth2ResourceServerProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Objects;

/**
 * Created by IntelliJ IDEA.
 *
 * @Author : Shrimpking
 * @create 2023/11/12 14:49
 */
@Slf4j
@Component
public class JwtUtils
{
    private static UserService staticUserService;

    @Autowired
    private UserService userService;

    @PostConstruct
    public void setUserService(){
        staticUserService = userService;
    }

    /**
     * 生成token
     * @param adminId
     * @param sign
     * @return
     */
    public static String createToken(String userId,String pwdToSign){
        return JWT.create()
                //将user id保存到里面,作为载荷
                .withAudience(userId)
                //2个小时以后过期
                .withExpiresAt(DateUtil.offsetHour(new Date(),2))
                //以password作为签名
                .sign(Algorithm.HMAC256(pwdToSign));
    }

    /**
     * 获取当前用户
     * @return
     */
    public static User getCurrentUser(){
        //声明token
        String token = null;
        try
        {
            //获取请求
            HttpServletRequest request
                    = ((ServletRequestAttributes)Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
            //从请求头部获取token
            token = request.getHeader("z-token");

            //如果头部没有,请请求参数获取token
            if(StringUtils.isBlank(token)){
                token = request.getParameter("token");
            }

            //如果token没有,返回null
            if(StringUtils.isBlank(token)){
                log.error("获取当前登录用户信息失败,token={}",token);
                return null;
            }
            //解析token
            String userId = JWT.decode(token).getAudience().get(0);
            //返回用户
            return staticUserService.getById(userId);
        }catch (Exception e){
            log.error("获取当前登录用户信息失败,token={}",token,e);
            return null;
        }
    }

    /**
     * 验证token
     * @param token
     * @return
     */
    public static Boolean verify(String token){

        //用户id
        String userId;
        //用户
        User user;
        try
        {
            //解析token,获取id
            userId = JWT.decode(token).getAudience().get(0);
            //根据id,获取用户
            user = staticUserService.getById(userId);
        }catch (Exception e){
            String errorMsg = "非法token,验证失败,请重新登录!";
            log.error(errorMsg + ",token=" + token ,e);
            throw  new CustomException(errorMsg);
        }
        //未查到用户
        if(user == null){
            throw new CustomException("用户不存在,请重新登录!");
        }

        try
        {
            //解析过程中,无异常,说明验证成功
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
            verifier.verify(token);
        }catch (JWTVerificationException e){
            throw new CustomException("token验证失败,请重新登录");
        }

        return true;
    }
}

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'),
      },
    ]
  },
]

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

request.js

import axios from 'axios'

const request  = axios.create({
    baseURL: 'http://localhost:8089/api',  //
    timeout: 5000,
});

//request 拦截器
request.interceptors.request.use( config =>{
    config.headers['Content-Type'] =  'application/json;charset=utf-8';
    //获取token
    const admin = JSON.parse(window.localStorage.getItem('access-admin'));
    if(admin){
        config.headers['z-token'] = admin.token;
    }
    return config;
},error => {
    return Promise.reject(error);
});

//respose 拦截器
request.interceptors.response.use( response => {
    //response.data即为后端返回的result, 也就是脱壳
    let res = response.data;

    //兼容服务端返回的字符串数据
    if(typeof res === 'string'){
        res = res ? JSON.parse(res) : res;
    }
    return res;
},error => {
    console.log('error:' + error);
    return Promise.reject(error);
});

export default request;

hotel.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-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"
                    v-if="admin.role === 'ROLE_ADMIN'">新增</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="酒店名称">
            </el-table-column>
            <el-table-column
                    prop="price"
                    label="入住价格">
            </el-table-column>
            <el-table-column
                    prop="img"
                    label="酒店图片">
                <template slot-scope="scope">
                    <el-image
                            :src="scope.row.img"
                            :preview-src-list="[scope.row.img]"
                            style="width:60px;height:60px;"></el-image>
                </template>
            </el-table-column>
            <el-table-column
                    prop="roomNum"
                    label="剩余房间数">
            </el-table-column>
            <el-table-column label="操作" width="360px">
                <template slot-scope="scope">
                    <el-button
                            type="primary"
                            icon="el-icon-edit"
                            @click="editBtn(scope.row)"
                            v-if="admin.role === 'ROLE_ADMIN'">编辑</el-button>
                    <el-button
                            type="danger"
                            icon="el-icon-delete"
                            @click="deleteBtn(scope.row)"
                            v-if="admin.role === 'ROLE_ADMIN'">删除</el-button>
                    <el-button
                            icon="el-icon-download"
                            @click="downloadBtn(scope.row)"
                            v-if="admin.role === 'ROLE_ADMIN'">下载</el-button>
                    <el-button
                            type="primary"
                            icon="el-icon-edit"
                            @click="reserveBtn(scope.row)"
                            v-if="admin.role !== 'ROLE_ADMIN'">预订</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="35%">
                <el-form
                        :model="addForm"
                        :rules="rules"
                        ref="addForm"
                        :label-width="formLabelWidth"
                        label-postion="left">
                    <el-form-item label="酒店名称" prop="name">
                        <el-input v-model="addForm.name" clearable></el-input>
                    </el-form-item>
                    <el-form-item label="价格" prop="price">
                        <el-input-number v-model="addForm.price" :max="9999" :min="99" :step="50"></el-input-number>
                    </el-form-item>
                    <el-form-item label="酒店图片" prop="img">
                        <el-upload :action="uploadPath" :on-success="successUpload">
                            <el-button size="small" type="primary">点击上传</el-button>
                        </el-upload>
                    </el-form-item>
                    <el-form-item label="剩余房间" prop="roomNum">
                        <el-input-number v-model="addForm.roomNum" :max="999" :min="1" :step="1"></el-input-number>
                    </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: "HotelView",
        computed: {
            admin(){
                return JSON.parse(window.localStorage.getItem('access-admin')) || { name: '未登录'};
            }
        },
        data() {
            return {
                //上传路径
                uploadPath:'http://localhost:8089/api/files/upload/',
                //下载路径
                downloadPath:'http://localhost:8089/api/files/down/',
                //添加表单
                addForm:{
                    name:'',
                    price:'',
                    img:'',
                    roomNum:'',
                },
                rules:{
                    name:[{required: true, message: '请输入酒店名称', trigger: 'blur'}],
                    price:[{required: true, message: '请输入入住价格', trigger: 'blur'}],
                    img:[{required: true, message: '请上传酒店图片', trigger: 'blur'}],
                    roomNum:[{required: true, message: '请输入剩余房间数', trigger: 'blur'}],
                },
                //表单标题宽度
                formLabelWidth:'80px',
                //对话框标题
                dialogTitle:'',
                //对话框
                dialogFormVisible: false,
                //搜索条件
                searchForm:{
                    name: '',
                    currentPage: 1,
                    pageSize: 5
                },
                tableData: [],
                total:0
            }
        },
        methods: {
            //预订
            reserveBtn(row){
                //封装对象
                let obj = {
                    hotelId: row.id,
                    userId: this.admin.id,
                    reserveDate: new Date()
                };
                request.post('/reserve/save',obj).then(res=>{
                    if(res.code === '200'){
                        this.$message.success(res.data);
                        this.doSearch();
                    }else {
                        this.$message.error(res.msg);
                        this.doSearch();
                    }
                })
            },
            //下载按钮
            downloadBtn(row){
                window.location.href = row.img;
            },
            //文件上传成功的回调
            successUpload(res){
                this.addForm.img = this.downloadPath + res.data;
            },
            //删除
            deleteBtn(row){
                this.$confirm(`您确定要删除【${row.name}】吗`,'删除提示',{
                    confirmButtonText:'删除',
                    cancelButtonText:'取消',
                    type:'warning',
                }).then(()=>{
                    request.delete('/hotel/delete',{
                        params:{ id : row.id}
                    }).then(res => {
                        if(res.code === '200'){
                            this.$message.success(res.data);
                            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 ? '/hotel/update':'/hotel/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.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('/hotel/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>

reserve.vue

<template>
    <div>
        <!-- 搜索区域       -->
        <div style="margin-bottom:15px;">
            <!-- 两个下拉框           -->
            <el-select
                    placeholder="请选择酒店"
                    v-model="searchForm.hotelId"
                    style="width: 200px;"
                    @clear="doSearch"
                    clearable>
                <el-option
                        v-for="item in hotelList"
                        :key="item.id"
                        :label="item.name"
                        :value="item.id"></el-option>
            </el-select>
            <el-select
                    placeholder="请选择用户"
                    v-model="searchForm.userId"
                    style="width: 200px;margin-left: 15px;"
                    @clear="doSearch"
                    :disabled="['ROLE_TEACHER','ROLE_STUDENT'].includes(admin.role)"
                    clearable>
                <el-option
                        v-for="item in userList"
                        :key="item.id"
                        :label="item.name"
                        :value="item.id"></el-option>
            </el-select>
            <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"-->
<!--                    v-if="admin.role === 'ROLE_ADMIN'">新增</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="hotelId"
                    label="酒店名称">
                <template slot-scope="scope">
                    <span> {{ hotelList.find((item) => item.id === scope.row.hotelId ).name }}</span>
                </template>
            </el-table-column>
            <el-table-column
                    prop="userId"
                    label="用户">
                <template slot-scope="scope">
                    <span> {{ userList.find( (item)=> item.id === scope.row.userId).name }}</span>
                </template>
            </el-table-column>
            <el-table-column
                    prop="reserveDate"
                    label="预订时间">
                <template slot-scope="scope">
                    <span>{{ scope.row.reserveDate != null ? scope.row.reserveDate.toString().substring(0,10):'' }}</span>
                </template>
            </el-table-column>
            <el-table-column label="操作" width="360px">
                <template slot-scope="scope">
<!--                    <el-button-->
<!--                            type="primary"-->
<!--                            icon="el-icon-edit"-->
<!--                            @click="editBtn(scope.row)"-->
<!--                            v-if="admin.role === 'ROLE_ADMIN'">编辑</el-button>-->
                    <el-button
                            type="danger"
                            icon="el-icon-delete"
                            @click="deleteBtn(scope.row)">退订</el-button>
<!--                    <el-button-->
<!--                            icon="el-icon-download"-->
<!--                            @click="downloadBtn(scope.row)"-->
<!--                            v-if="admin.role === 'ROLE_ADMIN'">下载</el-button>-->
<!--                    <el-button-->
<!--                            type="primary"-->
<!--                            icon="el-icon-edit"-->
<!--                            @click="(scope.row)"-->
<!--                            v-if="admin.role !== 'ROLE_ADMIN'">预订</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="35%">-->
<!--                <el-form-->
<!--                        :model="addForm"-->
<!--                        :rules="rules"-->
<!--                        ref="addForm"-->
<!--                        :label-width="formLabelWidth"-->
<!--                        label-postion="left">-->
<!--                    <el-form-item label="酒店名称" prop="name">-->
<!--                        <el-input v-model="addForm.name" clearable></el-input>-->
<!--                    </el-form-item>-->
<!--                    <el-form-item label="价格" prop="price">-->
<!--                        <el-input-number v-model="addForm.price" :max="9999" :min="99" :step="50"></el-input-number>-->
<!--                    </el-form-item>-->
<!--                    <el-form-item label="酒店图片" prop="img">-->
<!--                        <el-upload :action="uploadPath" :on-success="successUpload">-->
<!--                            <el-button size="small" type="primary">点击上传</el-button>-->
<!--                        </el-upload>-->
<!--                    </el-form-item>-->
<!--                    <el-form-item label="剩余房间" prop="roomNum">-->
<!--                        <el-input-number v-model="addForm.roomNum" :max="999" :min="1" :step="1"></el-input-number>-->
<!--                    </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: "ReserveView",
        computed: {
            admin(){
                return JSON.parse(window.localStorage.getItem('access-admin')) || { name: '未登录'};
            }
        },
        data() {
            return {
                //酒店列表
                hotelList:[],
                //用户列表
                userList:[],
                //上传路径
                uploadPath:'http://localhost:8089/api/files/upload/',
                //下载路径
                downloadPath:'http://localhost:8089/api/files/down/',
                //添加表单
                addForm:{
                    name:'',
                    price:'',
                    img:'',
                    roomNum:'',
                },
                rules:{
                    name:[{required: true, message: '请输入酒店名称', trigger: 'blur'}],
                    price:[{required: true, message: '请输入入住价格', trigger: 'blur'}],
                    img:[{required: true, message: '请上传酒店图片', trigger: 'blur'}],
                    roomNum:[{required: true, message: '请输入剩余房间数', trigger: 'blur'}],
                },
                //表单标题宽度
                formLabelWidth:'80px',
                //对话框标题
                dialogTitle:'',
                //对话框
                dialogFormVisible: false,
                //搜索条件
                searchForm:{
                    name: '',
                    currentPage: 1,
                    pageSize: 5
                },
                tableData: [],
                total:0
            }
        },
        methods: {
            getUserList(){
                request.get('/user/findAll').then(res=>{
                    if(res.code === '200'){
                        this.userList = res.data;
                    }
                })
            },
            //获取酒店列表
            getHotelList(){
                request.get('/hotel/list').then(res=>{
                    if(res.code === '200'){
                        this.hotelList = res.data;
                    }
                })
            },
            //下载按钮
            // downloadBtn(row){
            //     window.location.href = row.img;
            // },
            //文件上传成功的回调
            // successUpload(res){
            //     this.addForm.img = this.downloadPath + res.data;
            // },
            //删除
            deleteBtn(row){
                this.$confirm(`您确定要退订吗`,'删除提示',{
                    confirmButtonText:'退订',
                    cancelButtonText:'取消',
                    type:'warning',
                }).then(()=>{
                    request.put('/reserve/delete',row).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 ? '/hotel/update':'/hotel/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.hotelId = '';
                //仅有管理员可以
                if(['ROLE_ADMIN'].includes(this.admin.role)){
                    this.searchForm.userId = '';
                }
                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('/reserve/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(){
            //管理员可以看到全部数据,其他权限仅能看到自己数据
            if(['ROLE_TEACHER','ROLE_STUDENT'].includes(this.admin.role)){
                this.searchForm.userId = this.admin.id;
            }
            //获取数据
            this.getData();
            this.getUserList();
            this.getHotelList();
        }
    }
</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">
                        用户:&nbsp;&nbsp; <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-menu>
                </el-aside>
                <el-main>
                    <router-view/>
                </el-main>
            </el-container>
        </el-container>
    </div>
</template>

<script>
    export default {
        name: "Layout",
        computed: {
            admin(){
                return JSON.parse(window.localStorage.getItem('access-admin')) || { name: '未登录'};
            }
        },
        methods: {
            //下拉菜单命令
            handleCommand(command){
                if (command === 'logout') {
                    this.logout();
                }
            },
            //退出
            logout(){
                window.localStorage.clear();
                this.$message.success('退出成功!');
                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>

测试

酒店信息

 预订信息

教师登录

教师预订

学生登录

 学生预订

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虾米大王

有你的支持,我会更有动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值