├── src ├── main │ ├── resources │ │ ├── application-prod.properties │ │ ├── application-test.properties │ │ ├── application.properties │ │ ├── application-dev.properties │ │ ├── mapper │ │ │ ├── UserMapper.xml │ │ │ ├── SeatMapper.xml │ │ │ └── FootprintMapper.xml │ │ ├── banner.txt │ │ └── study_room.sql │ └── java │ │ └── com │ │ └── study │ │ └── room │ │ ├── dao │ │ ├── SeatMapper.java │ │ ├── UserMapper.java │ │ └── FootprintMapper.java │ │ ├── core │ │ ├── ServiceException.java │ │ ├── ResultCode.java │ │ ├── Mapper.java │ │ ├── Service.java │ │ ├── ResultGenerator.java │ │ ├── ProjectConstant.java │ │ ├── Result.java │ │ └── AbstractService.java │ │ ├── configurer │ │ ├── PassToken.java │ │ ├── UserLoginToken.java │ │ ├── MybatisConfigurer.java │ │ └── WebMvcConfigurer.java │ │ ├── service │ │ ├── UserService.java │ │ ├── SeatService.java │ │ ├── impl │ │ │ ├── UserServiceImpl.java │ │ │ ├── SeatServiceImpl.java │ │ │ └── FootprintServiceImpl.java │ │ └── FootprintService.java │ │ ├── dto │ │ ├── RoomsReportDTO.java │ │ ├── CreateUserDTO.java │ │ ├── UserDTO.java │ │ ├── BoardDTO.java │ │ └── FootprintDTO.java │ │ ├── utils │ │ ├── Tools.java │ │ ├── MD5Utils.java │ │ └── FileUtils.java │ │ ├── Application.java │ │ ├── model │ │ ├── Seat.java │ │ ├── User.java │ │ └── Footprint.java │ │ └── web │ │ ├── UserController.java │ │ ├── FootprintController.java │ │ └── SeatController.java └── test │ ├── resources │ ├── generator │ │ └── template │ │ │ ├── service.ftl │ │ │ ├── service-impl.ftl │ │ │ ├── controller-restful.ftl │ │ │ └── controller.ftl │ └── demo-user.sql │ └── java │ ├── com │ └── conpany │ │ └── project │ │ └── Tester.java │ └── CodeGenerator.java ├── .gitignore ├── README.md └── pom.xml /src/main/resources/application-prod.properties: -------------------------------------------------------------------------------- 1 | # 生产环境配置 2 | -------------------------------------------------------------------------------- /src/main/resources/application-test.properties: -------------------------------------------------------------------------------- 1 | # 测试环境配置 2 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | spring.profiles.active=dev 2 | # 所有环境通用的配置,放在这里 3 | 4 | # 404 交给异常处理器处理 5 | spring.mvc.throw-exception-if-no-handler-found=true 6 | spring.resources.add-mappings=false 7 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dao/SeatMapper.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dao; 2 | 3 | import com.study.room.core.Mapper; 4 | import com.study.room.model.Seat; 5 | 6 | public interface SeatMapper extends Mapper { 7 | } -------------------------------------------------------------------------------- /src/main/java/com/study/room/dao/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dao; 2 | 3 | import com.study.room.core.Mapper; 4 | import com.study.room.model.User; 5 | 6 | public interface UserMapper extends Mapper { 7 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | 3 | ### STS ### 4 | .apt_generated 5 | .classpath 6 | .factorypath 7 | .project 8 | .settings 9 | .springBeans 10 | 11 | ### IntelliJ IDEA ### 12 | .idea 13 | *.iws 14 | *.iml 15 | *.ipr 16 | 17 | ### NetBeans ### 18 | nbproject/private/ 19 | build/ 20 | nbbuild/ 21 | dist/ 22 | nbdist/ 23 | .nb-gradle/ -------------------------------------------------------------------------------- /src/test/resources/generator/template/service.ftl: -------------------------------------------------------------------------------- 1 | package ${basePackage}.service; 2 | import ${basePackage}.model.${modelNameUpperCamel}; 3 | import ${basePackage}.core.Service; 4 | 5 | 6 | /** 7 | * Created by ${author} on ${date}. 8 | */ 9 | public interface ${modelNameUpperCamel}Service extends Service<${modelNameUpperCamel}> { 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/application-dev.properties: -------------------------------------------------------------------------------- 1 | # 开发环境配置 2 | 3 | # 服务器端口配置 4 | server.port=8344 5 | 6 | # 数据源配置,请修改为你项目的实际配置 7 | spring.datasource.url=jdbc:mysql://hezijian6338.ddns.net:3306/study_room?useUnicode=true&characterEncoding=UTF8&useSSL=false 8 | spring.datasource.username=study_room 9 | spring.datasource.password=study_room 10 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 11 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/ServiceException.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | /** 4 | * 服务(业务)异常如“ 账号或密码错误 ”,该异常只做INFO级别的日志记录 @see WebMvcConfigurer 5 | */ 6 | public class ServiceException extends RuntimeException { 7 | public ServiceException() { 8 | } 9 | 10 | public ServiceException(String message) { 11 | super(message); 12 | } 13 | 14 | public ServiceException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/configurer/PassToken.java: -------------------------------------------------------------------------------- 1 | package com.study.room.configurer; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by Macbook on 2020/3/21. 10 | */ 11 | @Target({ElementType.METHOD, ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface PassToken { 14 | boolean required() default true; 15 | } -------------------------------------------------------------------------------- /src/main/java/com/study/room/configurer/UserLoginToken.java: -------------------------------------------------------------------------------- 1 | package com.study.room.configurer; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * Created by Macbook on 2020/3/21. 10 | */ 11 | @Target({ElementType.METHOD, ElementType.TYPE}) 12 | @Retention(RetentionPolicy.RUNTIME) 13 | public @interface UserLoginToken { 14 | boolean required() default true; 15 | } -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/ResultCode.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | /** 4 | * 响应码枚举,参考HTTP状态码的语义 5 | */ 6 | public enum ResultCode { 7 | SUCCESS(200),//成功 8 | FAIL(400),//失败 9 | UNAUTHORIZED(401),//未认证(签名错误) 10 | NOT_FOUND(404),//接口不存在 11 | INTERNAL_SERVER_ERROR(500);//服务器内部错误 12 | 13 | private final int code; 14 | 15 | ResultCode(int code) { 16 | this.code = code; 17 | } 18 | 19 | public int code() { 20 | return code; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/Mapper.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | import tk.mybatis.mapper.common.BaseMapper; 4 | import tk.mybatis.mapper.common.ConditionMapper; 5 | import tk.mybatis.mapper.common.IdsMapper; 6 | import tk.mybatis.mapper.common.special.InsertListMapper; 7 | 8 | /** 9 | * 定制版MyBatis Mapper插件接口,如需其他接口参考官方文档自行添加。 10 | */ 11 | public interface Mapper 12 | extends 13 | BaseMapper, 14 | ConditionMapper, 15 | IdsMapper, 16 | InsertListMapper { 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/generator/template/service-impl.ftl: -------------------------------------------------------------------------------- 1 | package ${basePackage}.service.impl; 2 | 3 | import ${basePackage}.dao.${modelNameUpperCamel}Mapper; 4 | import ${basePackage}.model.${modelNameUpperCamel}; 5 | import ${basePackage}.service.${modelNameUpperCamel}Service; 6 | import ${basePackage}.core.AbstractService; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | import javax.annotation.Resource; 11 | 12 | 13 | /** 14 | * Created by ${author} on ${date}. 15 | */ 16 | @Service 17 | @Transactional 18 | public class ${modelNameUpperCamel}ServiceImpl extends AbstractService<${modelNameUpperCamel}> implements ${modelNameUpperCamel}Service { 19 | @Resource 20 | private ${modelNameUpperCamel}Mapper ${modelNameLowerCamel}Mapper; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.study.room.service; 2 | import com.study.room.model.User; 3 | import com.study.room.core.Service; 4 | 5 | import java.util.List; 6 | 7 | 8 | /** 9 | * Created by CodeGenerator on 2020/03/21. 10 | */ 11 | public interface UserService extends Service { 12 | 13 | /** 14 | * @Method login 15 | * TODO: 登陆接口 16 | * @param username 17 | * @param password 18 | * @Return boolean 19 | * @Exception 20 | * @Date 2020/3/21 10:58 AM 21 | * @Author hezijian6338 22 | * @Version 1.0 23 | */ 24 | User login(String username, String password); 25 | 26 | /** 27 | * TODO: 查找管理员列表 28 | * @Return java.util.List 29 | * @Author hezijian6338 30 | */ 31 | List findAdminUsers(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/Service.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | import org.apache.ibatis.exceptions.TooManyResultsException; 4 | import tk.mybatis.mapper.entity.Condition; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Service 层 基础接口,其他Service 接口 请继承该接口 10 | */ 11 | public interface Service { 12 | void save(T model);//持久化 13 | void save(List models);//批量持久化 14 | void deleteById(String id);//通过主鍵刪除 15 | void deleteByIds(String ids);//批量刪除 eg:ids -> “1,2,3,4” 16 | void update(T model);//更新 17 | T findById(String id);//通过ID查找 18 | T findBy(String fieldName, Object value) throws TooManyResultsException; //通过Model中某个成员变量名称(非数据表中column的名称)查找,value需符合unique约束 19 | List findByIds(String ids);//通过多个ID查找//eg:ids -> “1,2,3,4” 20 | List findByCondition(Condition condition);//根据条件查找 21 | List findAll();//获取所有 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/ResultGenerator.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | /** 4 | * 响应结果生成工具 5 | */ 6 | public class ResultGenerator { 7 | private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS"; 8 | 9 | public static Result genSuccessResult() { 10 | return new Result() 11 | .setCode(ResultCode.SUCCESS) 12 | .setMessage(DEFAULT_SUCCESS_MESSAGE); 13 | } 14 | 15 | public static Result genSuccessResult(T data) { 16 | return new Result() 17 | .setCode(ResultCode.SUCCESS) 18 | .setMessage(DEFAULT_SUCCESS_MESSAGE) 19 | .setData(data); 20 | } 21 | 22 | public static Result genFailResult(String message) { 23 | return new Result() 24 | .setCode(ResultCode.FAIL) 25 | .setMessage(message); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/ProjectConstant.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | /** 4 | * 项目常量 5 | */ 6 | public final class ProjectConstant { 7 | public static final String BASE_PACKAGE = "com.study.room";//生成代码所在的基础包名称,可根据自己公司的项目修改(注意:这个配置修改之后需要手工修改src目录项目默认的包路径,使其保持一致,不然会找不到类) 8 | 9 | public static final String MODEL_PACKAGE = BASE_PACKAGE + ".model";//生成的Model所在包 10 | public static final String MAPPER_PACKAGE = BASE_PACKAGE + ".dao";//生成的Mapper所在包 11 | public static final String SERVICE_PACKAGE = BASE_PACKAGE + ".service";//生成的Service所在包 12 | public static final String SERVICE_IMPL_PACKAGE = SERVICE_PACKAGE + ".impl";//生成的ServiceImpl所在包 13 | public static final String CONTROLLER_PACKAGE = BASE_PACKAGE + ".web";//生成的Controller所在包 14 | 15 | public static final String MAPPER_INTERFACE_REFERENCE = BASE_PACKAGE + ".core.Mapper";//Mapper插件基础接口的完全限定名 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/Result.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | 5 | /** 6 | * 统一API响应结果封装 7 | */ 8 | public class Result { 9 | private int code; 10 | private String message; 11 | private T data; 12 | 13 | public Result setCode(ResultCode resultCode) { 14 | this.code = resultCode.code(); 15 | return this; 16 | } 17 | 18 | public int getCode() { 19 | return code; 20 | } 21 | 22 | public String getMessage() { 23 | return message; 24 | } 25 | 26 | public Result setMessage(String message) { 27 | this.message = message; 28 | return this; 29 | } 30 | 31 | public T getData() { 32 | return data; 33 | } 34 | 35 | public Result setData(T data) { 36 | this.data = data; 37 | return this; 38 | } 39 | 40 | @Override 41 | public String toString() { 42 | return JSON.toJSONString(this); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/com/conpany/project/Tester.java: -------------------------------------------------------------------------------- 1 | package com.conpany.project; 2 | 3 | 4 | import com.study.room.Application; 5 | import com.study.room.model.Seat; 6 | import org.junit.runner.RunWith; 7 | import org.springframework.boot.SpringApplication; 8 | import org.springframework.boot.test.context.SpringBootTest; 9 | import org.springframework.test.annotation.Rollback; 10 | import org.springframework.test.context.junit4.SpringRunner; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import java.util.List; 14 | 15 | /** 16 | * 单元测试继承该类即可 17 | */ 18 | @RunWith(SpringRunner.class) 19 | @SpringBootTest(classes = Application.class) 20 | @Transactional 21 | @Rollback 22 | public abstract class Tester { 23 | public static void main(String[] args) { 24 | String[] row = "[0000,0000,0000]".replace("[", "").replace("]", "").split(","); 25 | String seats = row[0]; 26 | char[] _seats = seats.toCharArray(); 27 | _seats[1] = Seat.SEAT.FULL; 28 | System.out.println(_seats); 29 | } 30 | } 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dto/RoomsReportDTO.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dto; 2 | 3 | public class RoomsReportDTO { 4 | 5 | private int roomsCount; 6 | private int seatsCount; 7 | private int availableSeats; 8 | private int unAvailableSeats; 9 | 10 | public int getAvailableSeats() { 11 | return availableSeats; 12 | } 13 | 14 | public int getRoomsCount() { 15 | return roomsCount; 16 | } 17 | 18 | public int getSeatsCount() { 19 | return seatsCount; 20 | } 21 | 22 | public int getUnAvailableSeats() { 23 | return unAvailableSeats; 24 | } 25 | 26 | public void setAvailableSeats(int availableSeats) { 27 | this.availableSeats = availableSeats; 28 | } 29 | 30 | public void setRoomsCount(int roomsCount) { 31 | this.roomsCount = roomsCount; 32 | } 33 | 34 | public void setSeatsCount(int seatsCount) { 35 | this.seatsCount = seatsCount; 36 | } 37 | 38 | public void setUnAvailableSeats(int unAvailableSeats) { 39 | this.unAvailableSeats = unAvailableSeats; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/resources/mapper/UserMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/resources/mapper/SeatMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dao/FootprintMapper.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dao; 2 | 3 | import com.study.room.core.Mapper; 4 | import com.study.room.model.Footprint; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.Date; 8 | import java.util.List; 9 | 10 | public interface FootprintMapper extends Mapper { 11 | /** 12 | * TODO: 根据用户 id和 当前状态筛选结果 13 | * @Date 2020/3/24 7:13 PM 14 | * @Author hezijian6338 15 | */ 16 | List checkTime(@Param("user_id") String user_id, @Param("status") int status); 17 | 18 | /** 19 | * TODO: 根据自习室房间号, 自习室座位号, 返回前5条使用记录 20 | * @Date 2020/4/5 8:28 PM 21 | * @Author hezijian6338 22 | */ 23 | List checkSeatStatus(@Param("room_number") String room_number, @Param("seats_number") String seats_number); 24 | 25 | /** 26 | * TODO: 根据用户 id返回历史记录前五条 27 | * @Date 2020/4/11 7:33 PM 28 | * @Author hezijian6338 29 | */ 30 | List checkHistoryByUser(@Param("user_id") String user_id); 31 | 32 | /** 33 | * TODO: 返回当天排行榜 34 | * @Date 2020-04-14 20:54 35 | * @Author hezijian6338 36 | */ 37 | List leaderBoard(@Param("updated_time") Date updated_time); 38 | 39 | /** 40 | * TODO: 返回年度使用列表 41 | * @Date 2020-04-25 11:43 42 | * @Author hezijian6338 43 | */ 44 | List counterBoard(@Param("roomNumber") String roomNumber, @Param("updated_time") Date updated_time); 45 | } -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////// 2 | // _ooOoo_ // 3 | // o8888888o // 4 | // 88" . "88 // 5 | // (| ^_^ |) // 6 | // O\ = /O // 7 | // ____/`---'\____ // 8 | // .' \\| |// `. // 9 | // / \\||| : |||// \ // 10 | // / _||||| -:- |||||- \ // 11 | // | | \\\ - /// | | // 12 | // | \_| ''\---/'' | | // 13 | // \ .-\__ `-` ___/-. / // 14 | // ___`. .' /--.--\ `. . ___ // 15 | // ."" '< `.___\_<|>_/___.' >'"". // 16 | // | | : `- \`.;`\ _ /`;.`/ - ` : | | // 17 | // \ \ `-. \_ __\ /__ _/ .-` / / // 18 | // ========`-.____`-.___\_____/___.-`____.-'======== // 19 | // `=---=' // 20 | // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // 21 | // 佛祖保佑 永不宕机 永无BUG // 22 | //////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /src/main/java/com/study/room/utils/Tools.java: -------------------------------------------------------------------------------- 1 | package com.study.room.utils; 2 | 3 | import com.auth0.jwt.JWT; 4 | import com.auth0.jwt.algorithms.Algorithm; 5 | import com.study.room.model.User; 6 | 7 | import java.sql.Timestamp; 8 | import java.util.Date; 9 | import java.util.UUID; 10 | 11 | /** 12 | * Created by Macbook on 2020/3/21. 13 | */ 14 | public class Tools { 15 | /** 16 | * @param 17 | * @Method getTimeStamp 18 | * TODO: 获取系统时间戳 19 | * @Return Timestamp 20 | * @Exception 21 | * @Date 2019/8/13 下午2:03 22 | * @Author hezijian6338 23 | * @Version 1.0 24 | */ 25 | public static Timestamp getTimeStamp() { 26 | return new Timestamp(new Date().getTime()); 27 | } 28 | 29 | public static long getLongTimeStamp() { 30 | return new Date().getTime(); 31 | } 32 | 33 | public static String getStringTimeStamp() { 34 | return getTimeStamp() + ""; 35 | } 36 | 37 | /** 38 | * @Method getToken 39 | * TODO: 根据 User生成 Token 40 | * @param user 41 | * @Return java.lang.String 42 | * @Exception 43 | * @Date 2020/3/21 9:39 PM 44 | * @Author hezijian6338 45 | * @Version 1.0 46 | */ 47 | public static String getToken(User user) { 48 | String token = "com.study.room"; 49 | token = JWT.create().withAudience(user.getId()) 50 | .sign(Algorithm.HMAC256(user.getPassword())); 51 | return token; 52 | } 53 | 54 | public static String getUUID() { 55 | String uuid = UUID.randomUUID().toString(); 56 | return uuid.replace("-", ""); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/service/SeatService.java: -------------------------------------------------------------------------------- 1 | package com.study.room.service; 2 | import com.study.room.model.Seat; 3 | import com.study.room.core.Service; 4 | 5 | 6 | /** 7 | * Created by CodeGenerator on 2020/03/21. 8 | */ 9 | public interface SeatService extends Service { 10 | 11 | /** 12 | * @Method checkSeat 13 | * TODO: 检查座位是否可以坐下, 返回不可以的原因 14 | * @param room_num 15 | * @param row 16 | * @param col 17 | * @Return int 18 | * @Exception 19 | * @Date 2020/3/22 11:53 AM 20 | * @Author hezijian6338 21 | * @Version 1.0 22 | */ 23 | int checkSeat(String room_num, int row, int col); 24 | 25 | /** 26 | * @Method haveSeat 27 | * TODO: 扫描传递参数坐下座位 28 | * @param row 29 | * @param col 30 | * @Return boolean 31 | * @Exception 32 | * @Date 2020/3/21 11:02 AM 33 | * @Author hezijian6338 34 | * @Version 1.0 35 | */ 36 | boolean haveSeat(String room_num, int row, int col); 37 | 38 | /** 39 | * @Method leaveSeat 40 | * TODO: 离开座位 41 | * @param room_num 42 | * @param row 43 | * @param col 44 | * @Return boolean 45 | * @Exception 46 | * @Date 2020/3/21 11:27 AM 47 | * @Author hezijian6338 48 | * @Version 1.0 49 | */ 50 | boolean leaveSeat(String room_num, int row, int col); 51 | 52 | /** 53 | * TODO: 离开座位 54 | * @Return boolean 55 | * @Author hezijian6338 56 | */ 57 | boolean leaveSeat(String userId); 58 | 59 | /** 60 | * TODO: 创建自习室 61 | * @Return java.lang.String 62 | * @Author hezijian6338 63 | */ 64 | String createRoom(String room_num, int row, int col); 65 | 66 | /** 67 | * TODO: 检查自习室是否还有座位正在使用 68 | * @Return boolean 69 | * @Author hezijian6338 70 | */ 71 | boolean checkRoom(String roomNumber); 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/utils/MD5Utils.java: -------------------------------------------------------------------------------- 1 | package com.study.room.utils; 2 | 3 | import java.math.BigInteger; 4 | import java.security.MessageDigest; 5 | 6 | public class MD5Utils { 7 | 8 | /** 9 | * @param str 需要加密的字符串 10 | * @return StringToMD5_digest加密后的字符串 11 | */ 12 | public static String StringToMD5_digest(String str) { 13 | try { 14 | MessageDigest md5 = MessageDigest.getInstance("MD5"); 15 | md5.update(str.getBytes()); 16 | return new BigInteger(1, md5.digest()).toString(16); 17 | } catch (Exception e) { 18 | e.printStackTrace(); 19 | return null; 20 | } 21 | } 22 | 23 | /** 24 | * 按固定字符加密 25 | * 26 | * @param str 需要加密的字符串 27 | * @return StringToMD5_hex加密后的字符串 28 | */ 29 | public static String StringToMD5_hex(String str) { 30 | char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 31 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 32 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; 33 | try { 34 | byte[] btInput = str.getBytes(); 35 | // 获得MD5摘要算法的 MessageDigest 对象 36 | MessageDigest mdInst = MessageDigest.getInstance("MD5"); 37 | // 使用指定的字节更新摘要 38 | mdInst.update(btInput); 39 | // 获得密文 40 | byte[] md = mdInst.digest(); 41 | // 把密文转换成十六进制的字符串形式 42 | int j = md.length; 43 | char s[] = new char[j * 2]; 44 | int k = 0; 45 | for (int i = 0; i < j; i++) { 46 | byte byte0 = md[i]; 47 | s[k++] = hexDigits[byte0 >>> 4 & 0xf]; 48 | s[k++] = hexDigits[byte0 & 0xf]; 49 | } 50 | return new String(s); 51 | } catch (Exception e) { 52 | e.printStackTrace(); 53 | return null; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.study.room.service.impl; 2 | 3 | import com.study.room.core.AbstractService; 4 | import com.study.room.dao.UserMapper; 5 | import com.study.room.model.User; 6 | import com.study.room.service.UserService; 7 | import com.study.room.utils.MD5Utils; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.stereotype.Service; 10 | import org.springframework.transaction.annotation.Transactional; 11 | import tk.mybatis.mapper.entity.Condition; 12 | import tk.mybatis.mapper.entity.Example; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.List; 16 | 17 | 18 | /** 19 | * Created by CodeGenerator on 2020/03/21. 20 | */ 21 | @Service 22 | @Transactional 23 | public class UserServiceImpl extends AbstractService implements UserService { 24 | private final org.slf4j.Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); 25 | 26 | @Resource 27 | private UserMapper userMapper; 28 | 29 | @Override 30 | public User login(String username, String password) { 31 | if (username == null && password == null) 32 | return null; 33 | User user = this.findBy("studentNum", username); 34 | 35 | String md5Password = MD5Utils.StringToMD5_hex(password); 36 | 37 | if (md5Password.equals(user.getPassword())) { 38 | logger.info("{} 用户登录成功~", user.getName()); 39 | return user; 40 | } else { 41 | logger.warn("{} 用户, {} 密码, 登录失败~", username, password); 42 | return null; 43 | } 44 | } 45 | 46 | @Override 47 | public List findAdminUsers() { 48 | Condition condition = new Condition(User.class); 49 | Example.Criteria criteria = condition.createCriteria(); 50 | criteria.orEqualTo("role", User.ROLE.ADMIN); 51 | criteria.orEqualTo("role", User.ROLE.SUPER); 52 | 53 | List user = this.findByCondition(condition); 54 | 55 | return user; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/test/resources/generator/template/controller-restful.ftl: -------------------------------------------------------------------------------- 1 | package ${basePackage}.web; 2 | 3 | import ${basePackage}.core.Result; 4 | import ${basePackage}.core.ResultGenerator; 5 | import ${basePackage}.model.${modelNameUpperCamel}; 6 | import ${basePackage}.service.${modelNameUpperCamel}Service; 7 | import com.github.pagehelper.PageHelper; 8 | import com.github.pagehelper.PageInfo; 9 | import org.springframework.web.bind.annotation.*; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by ${author} on ${date}. 16 | */ 17 | @RestController 18 | @RequestMapping("${baseRequestMapping}") 19 | public class ${modelNameUpperCamel}Controller { 20 | @Resource 21 | private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service; 22 | 23 | @PostMapping 24 | public Result add(@RequestBody ${modelNameUpperCamel} ${modelNameLowerCamel}) { 25 | ${modelNameLowerCamel}Service.save(${modelNameLowerCamel}); 26 | return ResultGenerator.genSuccessResult(); 27 | } 28 | 29 | @DeleteMapping("/{id}") 30 | public Result delete(@PathVariable Integer id) { 31 | ${modelNameLowerCamel}Service.deleteById(id); 32 | return ResultGenerator.genSuccessResult(); 33 | } 34 | 35 | @PutMapping 36 | public Result update(@RequestBody ${modelNameUpperCamel} ${modelNameLowerCamel}) { 37 | ${modelNameLowerCamel}Service.update(${modelNameLowerCamel}); 38 | return ResultGenerator.genSuccessResult(); 39 | } 40 | 41 | @GetMapping("/{id}") 42 | public Result detail(@PathVariable Integer id) { 43 | ${modelNameUpperCamel} ${modelNameLowerCamel} = ${modelNameLowerCamel}Service.findById(id); 44 | return ResultGenerator.genSuccessResult(${modelNameLowerCamel}); 45 | } 46 | 47 | @GetMapping 48 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) { 49 | PageHelper.startPage(page, size); 50 | List<${modelNameUpperCamel}> list = ${modelNameLowerCamel}Service.findAll(); 51 | PageInfo pageInfo = new PageInfo(list); 52 | return ResultGenerator.genSuccessResult(pageInfo); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/resources/demo-user.sql: -------------------------------------------------------------------------------- 1 | /* 2 | Navicat MySQL Data Transfer 3 | 4 | Source Server : Localhost 5 | Source Server Version : 50713 6 | Source Host : localhost:3306 7 | Source Database : test 8 | 9 | Target Server Type : MYSQL 10 | Target Server Version : 50713 11 | File Encoding : 65001 12 | 13 | Date: 2017-06-23 14:25:27 14 | */ 15 | 16 | SET FOREIGN_KEY_CHECKS=0; 17 | 18 | -- ---------------------------- 19 | -- Table structure for user 20 | -- ---------------------------- 21 | DROP TABLE IF EXISTS `user`; 22 | CREATE TABLE `user` ( 23 | `id` int(11) NOT NULL AUTO_INCREMENT, 24 | `username` varchar(255) NOT NULL, 25 | `password` varchar(255) NOT NULL, 26 | `nick_name` varchar(255) DEFAULT NULL, 27 | `sex` int(1) DEFAULT NULL, 28 | `register_date` datetime NOT NULL, 29 | PRIMARY KEY (`id`) 30 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 31 | 32 | -- ---------------------------- 33 | -- Records of user 34 | -- ---------------------------- 35 | INSERT INTO `user` VALUES ('1', '89921218@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆', '1', '2017-06-23 14:24:23'); 36 | INSERT INTO `user` VALUES ('2', '2@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-2', '1', '2017-06-23 14:24:23'); 37 | INSERT INTO `user` VALUES ('3', '3@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-3', '1', '2017-06-23 14:24:23'); 38 | INSERT INTO `user` VALUES ('4', '4@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-4', '1', '2017-06-23 14:24:23'); 39 | INSERT INTO `user` VALUES ('5', '5@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-5', '1', '2017-06-23 14:24:23'); 40 | INSERT INTO `user` VALUES ('6', '6@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-6', '1', '2017-06-23 14:24:23'); 41 | INSERT INTO `user` VALUES ('7', '7@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-7', '1', '2017-06-23 14:24:23'); 42 | INSERT INTO `user` VALUES ('8', '8@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-8', '1', '2017-06-23 14:24:23'); 43 | INSERT INTO `user` VALUES ('9', '9@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-9', '1', '2017-06-23 14:24:23'); 44 | INSERT INTO `user` VALUES ('10', '10@qq.com', '1ee04e0b1cb5af7367c80c22e42efd8b', '土豆-10', '1', '2017-06-23 14:24:23'); 45 | SET FOREIGN_KEY_CHECKS=1; 46 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/core/AbstractService.java: -------------------------------------------------------------------------------- 1 | package com.study.room.core; 2 | 3 | 4 | import org.apache.ibatis.exceptions.TooManyResultsException; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import tk.mybatis.mapper.entity.Condition; 7 | 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.ParameterizedType; 10 | import java.util.List; 11 | 12 | /** 13 | * 基于通用MyBatis Mapper插件的Service接口的实现 14 | */ 15 | public abstract class AbstractService implements Service { 16 | 17 | @Autowired 18 | protected Mapper mapper; 19 | 20 | private Class modelClass; // 当前泛型真实类型的Class 21 | 22 | public AbstractService() { 23 | ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); 24 | modelClass = (Class) pt.getActualTypeArguments()[0]; 25 | } 26 | 27 | public void save(T model) { 28 | mapper.insertSelective(model); 29 | } 30 | 31 | public void save(List models) { 32 | mapper.insertList(models); 33 | } 34 | 35 | public void deleteById(String id) { 36 | mapper.deleteByPrimaryKey(id); 37 | } 38 | 39 | public void deleteByIds(String ids) { 40 | mapper.deleteByIds(ids); 41 | } 42 | 43 | public void update(T model) { 44 | mapper.updateByPrimaryKeySelective(model); 45 | } 46 | 47 | public T findById(String id) { 48 | return mapper.selectByPrimaryKey(id); 49 | } 50 | 51 | @Override 52 | public T findBy(String fieldName, Object value) throws TooManyResultsException { 53 | try { 54 | T model = modelClass.newInstance(); 55 | Field field = modelClass.getDeclaredField(fieldName); 56 | field.setAccessible(true); 57 | field.set(model, value); 58 | return mapper.selectOne(model); 59 | } catch (ReflectiveOperationException e) { 60 | throw new ServiceException(e.getMessage(), e); 61 | } 62 | } 63 | 64 | public List findByIds(String ids) { 65 | return mapper.selectByIds(ids); 66 | } 67 | 68 | public List findByCondition(Condition condition) { 69 | return mapper.selectByCondition(condition); 70 | } 71 | 72 | public List findAll() { 73 | return mapper.selectAll(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/resources/generator/template/controller.ftl: -------------------------------------------------------------------------------- 1 | package ${basePackage}.web; 2 | import ${basePackage}.core.Result; 3 | import ${basePackage}.core.ResultGenerator; 4 | import ${basePackage}.model.${modelNameUpperCamel}; 5 | import ${basePackage}.service.${modelNameUpperCamel}Service; 6 | import com.github.pagehelper.PageHelper; 7 | import com.github.pagehelper.PageInfo; 8 | import org.springframework.web.bind.annotation.PostMapping; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestParam; 11 | import org.springframework.web.bind.annotation.RestController; 12 | 13 | import javax.annotation.Resource; 14 | import java.util.List; 15 | 16 | /** 17 | * Created by ${author} on ${date}. 18 | */ 19 | @RestController 20 | @RequestMapping("${baseRequestMapping}") 21 | public class ${modelNameUpperCamel}Controller { 22 | @Resource 23 | private ${modelNameUpperCamel}Service ${modelNameLowerCamel}Service; 24 | 25 | @PostMapping("/add") 26 | public Result add(${modelNameUpperCamel} ${modelNameLowerCamel}) { 27 | ${modelNameLowerCamel}Service.save(${modelNameLowerCamel}); 28 | return ResultGenerator.genSuccessResult(); 29 | } 30 | 31 | @PostMapping("/delete") 32 | public Result delete(@RequestParam Integer id) { 33 | ${modelNameLowerCamel}Service.deleteById(id); 34 | return ResultGenerator.genSuccessResult(); 35 | } 36 | 37 | @PostMapping("/update") 38 | public Result update(${modelNameUpperCamel} ${modelNameLowerCamel}) { 39 | ${modelNameLowerCamel}Service.update(${modelNameLowerCamel}); 40 | return ResultGenerator.genSuccessResult(); 41 | } 42 | 43 | @PostMapping("/detail") 44 | public Result detail(@RequestParam Integer id) { 45 | ${modelNameUpperCamel} ${modelNameLowerCamel} = ${modelNameLowerCamel}Service.findById(id); 46 | return ResultGenerator.genSuccessResult(${modelNameLowerCamel}); 47 | } 48 | 49 | @PostMapping("/list") 50 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) { 51 | PageHelper.startPage(page, size); 52 | List<${modelNameUpperCamel}> list = ${modelNameLowerCamel}Service.findAll(); 53 | PageInfo pageInfo = new PageInfo(list); 54 | return ResultGenerator.genSuccessResult(pageInfo); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/resources/mapper/FootprintMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | footprint 21 | 22 | 30 | 31 | 41 | 42 | 43 | 52 | 53 | 61 | 62 | 72 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/service/FootprintService.java: -------------------------------------------------------------------------------- 1 | package com.study.room.service; 2 | import com.study.room.dto.FootprintDTO; 3 | import com.study.room.model.Footprint; 4 | import com.study.room.core.Service; 5 | 6 | import java.util.List; 7 | 8 | 9 | /** 10 | * Created by CodeGenerator on 2020/03/21. 11 | */ 12 | public interface FootprintService extends Service { 13 | 14 | /** 15 | * @Method haveSeat 16 | * TODO: 扫描二维码坐下记录 17 | * @param footprint 18 | * @Return boolean 19 | * @Exception 20 | * @Date 2020/3/21 11:31 AM 21 | * @Author hezijian6338 22 | * @Version 1.0 23 | */ 24 | boolean haveSeat(FootprintDTO footprint); 25 | 26 | /** 27 | * @Method leaveSeat 28 | * TODO: 离开座位记录 29 | * @param userId 30 | * @Return boolean 31 | * @Exception 32 | * @Date 2020/3/21 11:52 AM 33 | * @Author hezijian6338 34 | * @Version 1.0 35 | */ 36 | boolean leaveSeat(String userId); 37 | 38 | /** 39 | * @Method pauseSeat 40 | * TODO: 暂时离开座位记录 41 | * @param footprint 42 | * @Return boolean 43 | * @Exception 44 | * @Date 2020/3/21 11:53 AM 45 | * @Author hezijian6338 46 | * @Version 1.0 47 | */ 48 | boolean pauseSeat(FootprintDTO footprint); 49 | 50 | boolean pauseSeat(String userId); 51 | 52 | /** 53 | * TODO: 检查该用户的座位剩余情况 (如果 没有坐下/已经过时间了 则返回 0) 54 | * @Return int 55 | * @Author hezijian6338 56 | */ 57 | int checkTime(String user_id); 58 | 59 | /** 60 | * TODO: 根据自习室编号, 座位编号返回当前的座位信息 61 | * @Return com.study.room.model.Footprint 62 | * @Author hezijian6338 63 | */ 64 | Footprint checkSeatStatus(String room_number, String seats_number); 65 | 66 | /** 67 | * TODO: 根据用户 id找到当前使用的足迹信息 68 | * @Return com.study.room.model.Footprint 69 | * @Author hezijian6338 70 | */ 71 | Footprint findUseSeatByUserId(String userId); 72 | 73 | /** 74 | * TODO: 根据用户 id返回前五条历史消息 75 | * @Date 2020/4/11 7:35 PM 76 | * @Author hezijian6338 77 | */ 78 | List checkHistoryByUser(String userId); 79 | 80 | /** 81 | * TODO: 根据自习室编号 82 | * @Date 2020-04-25 12:02 83 | * @Author hezijian6338 84 | */ 85 | List checkOnSeatListByRoomNumber(String roomNumber); 86 | 87 | /** 88 | * TODO: 根据用户 id查找入座信息 (作废 ==>> findUseSeatByUserId) 89 | * @Date 2020-04-26 18:33 90 | * @Author hezijian6338 91 | */ 92 | Footprint findInfoByUser(String userId); 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/configurer/MybatisConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.study.room.configurer; 2 | 3 | import com.github.pagehelper.PageHelper; 4 | import org.apache.ibatis.plugin.Interceptor; 5 | import org.apache.ibatis.session.SqlSessionFactory; 6 | import org.mybatis.spring.SqlSessionFactoryBean; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 10 | import org.springframework.core.io.support.ResourcePatternResolver; 11 | import tk.mybatis.spring.mapper.MapperScannerConfigurer; 12 | 13 | import javax.sql.DataSource; 14 | import java.util.Properties; 15 | 16 | import static com.study.room.core.ProjectConstant.MAPPER_INTERFACE_REFERENCE; 17 | import static com.study.room.core.ProjectConstant.MAPPER_PACKAGE; 18 | import static com.study.room.core.ProjectConstant.MODEL_PACKAGE; 19 | 20 | /** 21 | * Mybatis & Mapper & PageHelper 配置 22 | */ 23 | @Configuration 24 | public class MybatisConfigurer { 25 | 26 | @Bean 27 | public SqlSessionFactory sqlSessionFactoryBean(DataSource dataSource) throws Exception { 28 | SqlSessionFactoryBean factory = new SqlSessionFactoryBean(); 29 | factory.setDataSource(dataSource); 30 | factory.setTypeAliasesPackage(MODEL_PACKAGE); 31 | 32 | //配置分页插件,详情请查阅官方文档 33 | PageHelper pageHelper = new PageHelper(); 34 | Properties properties = new Properties(); 35 | properties.setProperty("pageSizeZero", "true");//分页尺寸为0时查询所有纪录不再执行分页 36 | properties.setProperty("reasonable", "true");//页码<=0 查询第一页,页码>=总页数查询最后一页 37 | properties.setProperty("supportMethodsArguments", "true");//支持通过 Mapper 接口参数来传递分页参数 38 | pageHelper.setProperties(properties); 39 | 40 | //添加插件 41 | factory.setPlugins(new Interceptor[]{pageHelper}); 42 | 43 | //添加XML目录 44 | ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); 45 | factory.setMapperLocations(resolver.getResources("classpath:mapper/*.xml")); 46 | return factory.getObject(); 47 | } 48 | 49 | @Bean 50 | public MapperScannerConfigurer mapperScannerConfigurer() { 51 | MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); 52 | mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactoryBean"); 53 | mapperScannerConfigurer.setBasePackage(MAPPER_PACKAGE); 54 | 55 | //配置通用Mapper,详情请查阅官方文档 56 | Properties properties = new Properties(); 57 | properties.setProperty("mappers", MAPPER_INTERFACE_REFERENCE); 58 | properties.setProperty("notEmpty", "false");//insert、update是否判断字符串类型!='' 即 test="str != null"表达式内是否追加 and str != '' 59 | properties.setProperty("IDENTITY", "MYSQL"); 60 | mapperScannerConfigurer.setProperties(properties); 61 | 62 | return mapperScannerConfigurer; 63 | } 64 | 65 | } 66 | 67 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/Application.java: -------------------------------------------------------------------------------- 1 | package com.study.room; 2 | 3 | import com.study.room.configurer.PassToken; 4 | import io.swagger.annotations.ApiOperation; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.RequestMethod; 11 | import org.springframework.web.bind.annotation.RestController; 12 | import org.springframework.web.servlet.ModelAndView; 13 | import springfox.documentation.annotations.ApiIgnore; 14 | import springfox.documentation.builders.ApiInfoBuilder; 15 | import springfox.documentation.builders.ParameterBuilder; 16 | import springfox.documentation.builders.PathSelectors; 17 | import springfox.documentation.builders.RequestHandlerSelectors; 18 | import springfox.documentation.schema.ModelRef; 19 | import springfox.documentation.service.ApiInfo; 20 | import springfox.documentation.service.Parameter; 21 | import springfox.documentation.spi.DocumentationType; 22 | import springfox.documentation.spring.web.plugins.Docket; 23 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | @Configuration 29 | @RestController 30 | @EnableSwagger2 31 | @SpringBootApplication 32 | public class Application { 33 | public static void main(String[] args) { 34 | SpringApplication.run(Application.class, args); 35 | } 36 | 37 | @PassToken 38 | @RequestMapping(value = "/", method = RequestMethod.GET) 39 | @ApiIgnore() 40 | @ApiOperation(value = "重定向到api首页") 41 | public ModelAndView index() { 42 | return new ModelAndView("redirect:/swagger-ui.html"); 43 | } 44 | 45 | @Bean 46 | public Docket createRestApi() { 47 | // 为 swagger添加 header参数输入 48 | ParameterBuilder userTokenHeader = new ParameterBuilder(); 49 | List pars = new ArrayList(); 50 | userTokenHeader.name("token").description("token") 51 | .modelRef(new ModelRef("string")).parameterType("header") 52 | .required(false).build(); 53 | pars.add(userTokenHeader.build()); 54 | 55 | return new Docket(DocumentationType.SWAGGER_2) 56 | .apiInfo(apiInfo()) 57 | .select() 58 | .apis(RequestHandlerSelectors.basePackage("com.study.room")) 59 | .paths(PathSelectors.any()) 60 | .build() 61 | .globalOperationParameters(pars); 62 | } 63 | 64 | private ApiInfo apiInfo() { 65 | return new ApiInfoBuilder() 66 | .title("study.room") 67 | .description("study.room") 68 | .termsOfServiceUrl("share.dragonsking.cn") 69 | .contact("hezijian6338") 70 | .version("1.0") 71 | .build(); 72 | } 73 | } 74 | 75 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dto/CreateUserDTO.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dto; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | 6 | /** 7 | * Created by Macbook on 2020/4/11. 8 | */ 9 | @ApiModel(value = "CreateUserDTO", description = "用户信息传输对象") 10 | public class CreateUserDTO { 11 | /** 12 | * 用户名称 13 | */ 14 | @ApiModelProperty(name = "name", value = "学生名称 (例子: 何子健)", example="何子健", required=true) 15 | private String name; 16 | 17 | 18 | /** 19 | * 学生学号 20 | */ 21 | @ApiModelProperty(name = "studentNum", value = "学生学号 (例子: 140202011031)", example="140202011031", required=true) 22 | private String studentNum; 23 | 24 | /** 25 | * 用户电话 26 | */ 27 | @ApiModelProperty(name = "phone", value = "学生电话 (例子: 13160666721)", example="13160666721", required=true) 28 | private String phone; 29 | 30 | /** 31 | * 0: 普通用户;1: 管理员; 2: 超级管理员 32 | */ 33 | @ApiModelProperty(name = "role", value = "0: 普通用户;1: 管理员; 2: 超级管理员", example="0", required=true) 34 | private Integer role; 35 | 36 | /** 37 | * 0: 停用; 1: 启用; -1: 黑名单 38 | */ 39 | @ApiModelProperty(value = "0: 停用; 1: 启用; -1: 黑名单", example="1", required=true) 40 | private Integer status; 41 | 42 | /** 43 | * 获取用户名称 44 | * 45 | * @return name - 用户名称 46 | */ 47 | public String getName() { 48 | return name; 49 | } 50 | 51 | /** 52 | * 设置用户名称 53 | * 54 | * @param name 用户名称 55 | */ 56 | public void setName(String name) { 57 | this.name = name; 58 | } 59 | 60 | 61 | /** 62 | * 获取学生学号 63 | * 64 | * @return student_num - 学生学号 65 | */ 66 | public String getStudentNum() { 67 | return studentNum; 68 | } 69 | 70 | /** 71 | * 设置学生学号 72 | * 73 | * @param studentNum 学生学号 74 | */ 75 | public void setStudentNum(String studentNum) { 76 | this.studentNum = studentNum; 77 | } 78 | 79 | /** 80 | * 获取用户电话 81 | * 82 | * @return phone - 用户电话 83 | */ 84 | public String getPhone() { 85 | return phone; 86 | } 87 | 88 | /** 89 | * 设置用户电话 90 | * 91 | * @param phone 用户电话 92 | */ 93 | public void setPhone(String phone) { 94 | this.phone = phone; 95 | } 96 | 97 | /** 98 | * 获取0: 普通用户;1: 管理员; 2: 超级管理员 99 | * 100 | * @return role - 0: 普通用户;1: 管理员; 2: 超级管理员 101 | */ 102 | public Integer getRole() { 103 | return role; 104 | } 105 | 106 | /** 107 | * 设置0: 普通用户;1: 管理员; 2: 超级管理员 108 | * 109 | * @param role 0: 普通用户;1: 管理员; 2: 超级管理员 110 | */ 111 | public void setRole(Integer role) { 112 | this.role = role; 113 | } 114 | 115 | /** 116 | * 获取0: 停用; 1: 启用; -1: 黑名单 117 | * 118 | * @return status - 0: 停用; 1: 启用; -1: 黑名单 119 | */ 120 | public Integer getStatus() { 121 | return status; 122 | } 123 | 124 | /** 125 | * 设置0: 停用; 1: 启用; -1: 黑名单 126 | * 127 | * @param status 0: 停用; 1: 启用; -1: 黑名单 128 | */ 129 | public void setStatus(Integer status) { 130 | this.status = status; 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 自习室座位管理系统 2 | 基于种子项目, 进行二次修改的 SpringBoot进行开发 3 | ## 项目路径 4 | ``` 5 | ├── README.md 6 | ├── pom.xml 7 | ├── seat-of-study-room.iml 8 | └── target 9 | src 10 | ├── main 11 | │ ├── java 12 | │ │ └── com 13 | │ │ └── study 14 | │ │ └── room 15 | │ │ ├── Application.java (主入口文件) 16 | │ │ ├── configurer (配置文件夹) 17 | │ │ │ ├── MybatisConfigurer.java (Mybatis工具的配置文件) 18 | │ │ │ ├── PassToken.java (注解开发判定用户请求是否需要携带 TOKEN) 19 | │ │ │ ├── UserLoginToken.java (需要携带 TOKEN) 20 | │ │ │ └── WebMvcConfigurer.java (SpringBoot拦截器等相关配置类) 21 | │ │ ├── core (核心基础类) 22 | │ │ │ ├── AbstractService.java (业务逻辑包基础操作抽象类) 23 | │ │ │ ├── Mapper.java (数据持久层的基础类) 24 | │ │ │ ├── ProjectConstant.java (项目路径相关配置 -- 代码生成器相关) 25 | │ │ │ ├── Result.java (返回前端数据结构的基础类) 26 | │ │ │ ├── ResultCode.java (返回状态码的基础类) 27 | │ │ │ ├── ResultGenerator.java (返回前端数据结构的构建类 -- 封装了基础的 成功/失败类型) 28 | │ │ │ ├── Service.java (业务逻辑层的基础接口类) 29 | │ │ │ └── ServiceException.java (业务逻辑异常定义类) 30 | │ │ ├── dao (DAO层) 31 | │ │ │ ├── FootprintMapper.java (足迹) 32 | │ │ │ ├── SeatMapper.java (座位) 33 | │ │ │ └── UserMapper.java (用户) 34 | │ │ ├── dto (Data Transfer Object) 35 | │ │ │ ├── BoardDTO.java (榜单) 36 | │ │ │ ├── CreateUserDTO.java (创建用户) 37 | │ │ │ ├── FootprintDTO.java (足迹) 38 | │ │ │ ├── RoomsReportDTO.java (自习室报告) 39 | │ │ │ └── UserDTO.java (用户操作) 40 | │ │ ├── model (实体类) 41 | │ │ │ ├── Footprint.java (足迹实体类) 42 | │ │ │ ├── Seat.java (座位实体类) 43 | │ │ │ └── User.java (用户实体类) 44 | │ │ ├── service (业务逻辑层 -- 接口(不含方法)) 45 | │ │ │ ├── FootprintService.java (足迹) 46 | │ │ │ ├── SeatService.java (座位) 47 | │ │ │ ├── UserService.java (用户) 48 | │ │ │ └── impl (-- 实际操作) 49 | │ │ │ ├── FootprintServiceImpl.java 50 | │ │ │ ├── SeatServiceImpl.java 51 | │ │ │ └── UserServiceImpl.java 52 | │ │ ├── utils (工具类) 53 | │ │ │ ├── FileUtils.java (文件操作 -- 好像没用到) 54 | │ │ │ ├── MD5Utils.java (MD5加密) 55 | │ │ │ └── Tools.java (杂项工具类) 56 | │ │ └── web (控制器) 57 | │ │ ├── FootprintController.java (足迹) 58 | │ │ ├── SeatController.java (座位) 59 | │ │ └── UserController.java (用户) 60 | │ └── resources (资源文件夹) 61 | │ ├── application-dev.properties (开发配置文件) 62 | │ ├── application-prod.properties (生产配置文件) 63 | │ ├── application-test.properties (测试配置文件) 64 | │ ├── application.properties (配置文件主入口) 65 | │ ├── banner.txt (有趣的东西) 66 | │ └── mapper (映射层 -- 数据库语句) 67 | │ ├── FootprintMapper.xml (足迹) 68 | │ ├── SeatMapper.xml (座位) 69 | │ └── UserMapper.xml (用户信息) 70 | └── test 71 | ├── java (测试调试类包) 72 | │ ├── CodeGenerator.java 73 | │ └── com 74 | │ └── conpany 75 | │ └── project 76 | │ └── Tester.java 77 | └── resources (代码自动生成相关) 78 | ├── demo-user.sql 79 | └── generator 80 | └── template 81 | ├── controller-restful.ftl 82 | ├── controller.ftl 83 | ├── service-impl.ftl 84 | └── service.ftl 85 | ``` 86 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dto/UserDTO.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dto; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | 6 | /** 7 | * Created by Macbook on 2020/3/21. 8 | */ 9 | @ApiModel(value = "UserDTO", description = "用户信息传输对象") 10 | public class UserDTO { 11 | 12 | @ApiModelProperty(value = "用户 id") 13 | private String id; 14 | 15 | /** 16 | * 用户名称 17 | */ 18 | @ApiModelProperty(value = "学生名称") 19 | private String name; 20 | 21 | 22 | /** 23 | * 学生学号 24 | */ 25 | @ApiModelProperty(value = "学生学号") 26 | private String studentNum; 27 | 28 | /** 29 | * 用户电话 30 | */ 31 | @ApiModelProperty(value = "学生电话") 32 | private String phone; 33 | 34 | /** 35 | * 0: 普通用户;1: 管理员; 2: 超级管理员 36 | */ 37 | @ApiModelProperty(value = "0: 普通用户;1: 管理员; 2: 超级管理员") 38 | private Integer role; 39 | 40 | /** 41 | * 0: 停用; 1: 启用; -1: 黑名单 42 | */ 43 | @ApiModelProperty(value = "0: 停用; 1: 启用; -1: 黑名单") 44 | private Integer status; 45 | 46 | /** 47 | * 默认0, 到3 自动转换黑名单 48 | */ 49 | @ApiModelProperty(value = "黑名单次数记录") 50 | private Integer badRecord; 51 | 52 | /** 53 | * 登陆必须携带的 token 54 | */ 55 | @ApiModelProperty(value = "登陆携带的 token") 56 | private String token; 57 | 58 | /** 59 | * @return id 60 | */ 61 | public String getId() { 62 | return id; 63 | } 64 | 65 | /** 66 | * @param id 67 | */ 68 | public void setId(String id) { 69 | this.id = id; 70 | } 71 | 72 | /** 73 | * 获取用户名称 74 | * 75 | * @return name - 用户名称 76 | */ 77 | public String getName() { 78 | return name; 79 | } 80 | 81 | /** 82 | * 设置用户名称 83 | * 84 | * @param name 用户名称 85 | */ 86 | public void setName(String name) { 87 | this.name = name; 88 | } 89 | 90 | 91 | /** 92 | * 获取学生学号 93 | * 94 | * @return student_num - 学生学号 95 | */ 96 | public String getStudentNum() { 97 | return studentNum; 98 | } 99 | 100 | /** 101 | * 设置学生学号 102 | * 103 | * @param studentNum 学生学号 104 | */ 105 | public void setStudentNum(String studentNum) { 106 | this.studentNum = studentNum; 107 | } 108 | 109 | /** 110 | * 获取用户电话 111 | * 112 | * @return phone - 用户电话 113 | */ 114 | public String getPhone() { 115 | return phone; 116 | } 117 | 118 | /** 119 | * 设置用户电话 120 | * 121 | * @param phone 用户电话 122 | */ 123 | public void setPhone(String phone) { 124 | this.phone = phone; 125 | } 126 | 127 | /** 128 | * 获取0: 普通用户;1: 管理员; 2: 超级管理员 129 | * 130 | * @return role - 0: 普通用户;1: 管理员; 2: 超级管理员 131 | */ 132 | public Integer getRole() { 133 | return role; 134 | } 135 | 136 | /** 137 | * 设置0: 普通用户;1: 管理员; 2: 超级管理员 138 | * 139 | * @param role 0: 普通用户;1: 管理员; 2: 超级管理员 140 | */ 141 | public void setRole(Integer role) { 142 | this.role = role; 143 | } 144 | 145 | /** 146 | * 获取0: 停用; 1: 启用; -1: 黑名单 147 | * 148 | * @return status - 0: 停用; 1: 启用; -1: 黑名单 149 | */ 150 | public Integer getStatus() { 151 | return status; 152 | } 153 | 154 | /** 155 | * 设置0: 停用; 1: 启用; -1: 黑名单 156 | * 157 | * @param status 0: 停用; 1: 启用; -1: 黑名单 158 | */ 159 | public void setStatus(Integer status) { 160 | this.status = status; 161 | } 162 | 163 | /** 164 | * 获取默认0, 到3 自动转换黑名单 165 | * 166 | * @return bad_record - 默认0, 到3 自动转换黑名单 167 | */ 168 | public Integer getBadRecord() { 169 | return badRecord; 170 | } 171 | 172 | /** 173 | * 设置默认0, 到3 自动转换黑名单 174 | * 175 | * @param badRecord 默认0, 到3 自动转换黑名单 176 | */ 177 | public void setBadRecord(Integer badRecord) { 178 | this.badRecord = badRecord; 179 | } 180 | 181 | public void setToken(String token) { 182 | this.token = token; 183 | } 184 | 185 | public String getToken() { 186 | return token; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dto/BoardDTO.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dto; 2 | 3 | import com.study.room.model.User; 4 | import io.swagger.annotations.ApiModelProperty; 5 | 6 | import java.util.Objects; 7 | 8 | /** 9 | * Created by Macbook on 2020/5/1. 10 | */ 11 | public class BoardDTO { 12 | @ApiModelProperty(value = "用户 id") 13 | private String userId; 14 | 15 | /** 16 | * 自习室编号 17 | */ 18 | @ApiModelProperty(value = "自习室编号", example = "za101", required = true) 19 | private String roomNumber; 20 | 21 | /** 22 | * 由 row + _ + col 组成 23 | */ 24 | @ApiModelProperty(value = "座位编号 (例子: 5, 6; 代表第五行第六列)", example = "1,3", required = true) 25 | private String seatsNumber; 26 | 27 | /** 28 | * 学生希望自习的时间 29 | */ 30 | @ApiModelProperty(value = "学生希望的自习时间 (60m/120m/180), 需要换算成 ms", example = "600000", required = true) 31 | private int wantedTime; 32 | 33 | /** 34 | * 存放时间戳差 35 | */ 36 | @ApiModelProperty(value = "已经自习的时间") 37 | private int stayTime; 38 | 39 | /** 40 | * 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 41 | */ 42 | @ApiModelProperty(value = "0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时)") 43 | private Integer status; 44 | 45 | /** 46 | * 心情标签 (数组, 用 ,分隔) 47 | */ 48 | @ApiModelProperty(value = "心情标签") 49 | private String momentTag; 50 | 51 | private User user; 52 | 53 | 54 | public User getUser() { 55 | return user; 56 | } 57 | 58 | public void setUser(User user) { 59 | this.user = user; 60 | } 61 | 62 | /** 63 | * @return user_id 64 | */ 65 | public String getUserId() { 66 | return userId; 67 | } 68 | 69 | /** 70 | * @param userId 71 | */ 72 | public void setUserId(String userId) { 73 | this.userId = userId; 74 | } 75 | 76 | /** 77 | * 获取自习室编号 78 | * 79 | * @return room_number - 自习室编号 80 | */ 81 | public String getRoomNumber() { 82 | return roomNumber; 83 | } 84 | 85 | /** 86 | * 设置自习室编号 87 | * 88 | * @param roomNumber 自习室编号 89 | */ 90 | public void setRoomNumber(String roomNumber) { 91 | this.roomNumber = roomNumber; 92 | } 93 | 94 | /** 95 | * 获取由 row + _ + col 组成 96 | * 97 | * @return seats_number - 由 row + _ + col 组成 98 | */ 99 | public String getSeatsNumber() { 100 | return seatsNumber; 101 | } 102 | 103 | /** 104 | * 设置由 row + _ + col 组成 105 | * 106 | * @param seatsNumber 由 row + _ + col 组成 107 | */ 108 | public void setSeatsNumber(String seatsNumber) { 109 | this.seatsNumber = seatsNumber; 110 | } 111 | 112 | /** 113 | * 获取存放时间戳差 114 | * 115 | * @return stay_time - 存放时间戳差 116 | */ 117 | public int getStayTime() { 118 | return stayTime; 119 | } 120 | 121 | /** 122 | * 设置存放时间戳差 123 | * 124 | * @param stayTime 存放时间戳差 125 | */ 126 | public void setStayTime(int stayTime) { 127 | this.stayTime = stayTime; 128 | } 129 | 130 | /** 131 | * 获取0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 132 | * 133 | * @return status - 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 134 | */ 135 | public Integer getStatus() { 136 | return status; 137 | } 138 | 139 | /** 140 | * 设置0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 141 | * 142 | * @param status 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 143 | */ 144 | public void setStatus(Integer status) { 145 | this.status = status; 146 | } 147 | 148 | /** 149 | * 获取心情标签 (数组, 用 ,分隔) 150 | * 151 | * @return montent_tag - 心情标签 (数组, 用 ,分隔) 152 | */ 153 | public String getMomentTag() { 154 | return momentTag; 155 | } 156 | 157 | /** 158 | * 设置心情标签 (数组, 用 ,分隔) 159 | * 160 | * @param montentTag 心情标签 (数组, 用 ,分隔) 161 | */ 162 | public void setMomentTag(String montentTag) { 163 | this.momentTag = montentTag; 164 | } 165 | 166 | 167 | public void setWantedTime(int wantedTime) { 168 | this.wantedTime = wantedTime; 169 | } 170 | 171 | public int getWantedTime() { 172 | return wantedTime; 173 | } 174 | 175 | @Override 176 | public boolean equals(Object o) { 177 | if (o == null) { 178 | return false; 179 | } 180 | if (o instanceof BoardDTO) { 181 | BoardDTO inItem = (BoardDTO) o; 182 | return Objects.equals(userId, inItem.getUserId()); 183 | } 184 | return false; 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/dto/FootprintDTO.java: -------------------------------------------------------------------------------- 1 | package com.study.room.dto; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import io.swagger.annotations.ApiModelProperty; 5 | 6 | /** 7 | * Created by Macbook on 2020/3/21. 8 | */ 9 | @ApiModel(value = "FootprintDTO", description = "足迹/日志 实体类") 10 | public class FootprintDTO { 11 | 12 | @ApiModelProperty(value = "用户 id") 13 | private String userId; 14 | 15 | /** 16 | * 自习室编号 17 | */ 18 | @ApiModelProperty(value = "自习室编号", example="za101", required=true) 19 | private String roomNumber; 20 | 21 | /** 22 | * 由 row + _ + col 组成 23 | */ 24 | @ApiModelProperty(value = "座位编号 (例子: 5, 6; 代表第五行第六列)", example="1,3", required=true) 25 | private String seatsNumber; 26 | 27 | /** 28 | * 学生希望自习的时间 29 | */ 30 | @ApiModelProperty(value = "学生希望的自习时间 (60m/120m/180), 需要换算成 ms", example="600000", required=true) 31 | private int wantedTime; 32 | 33 | /** 34 | * 存放时间戳差 35 | */ 36 | @ApiModelProperty(value = "已经自习的时间") 37 | private int stayTime; 38 | 39 | /** 40 | * 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 41 | */ 42 | @ApiModelProperty(value = "0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时)") 43 | private Integer status; 44 | 45 | /** 46 | * 心情标签 (数组, 用 ,分隔) 47 | */ 48 | @ApiModelProperty(value = "心情标签") 49 | private String momentTag; 50 | 51 | /** 52 | * 坐下时间 53 | */ 54 | // private String createdTime; 55 | 56 | /** 57 | * 更新时间 58 | */ 59 | // private String updatedTime; 60 | 61 | /** 62 | * @return id 63 | */ 64 | // public String getId() { 65 | // return id; 66 | // } 67 | 68 | /** 69 | * @param id 70 | */ 71 | // public void setId(String id) { 72 | // this.id = id; 73 | // } 74 | 75 | /** 76 | * @return user_id 77 | */ 78 | public String getUserId() { 79 | return userId; 80 | } 81 | 82 | /** 83 | * @param userId 84 | */ 85 | public void setUserId(String userId) { 86 | this.userId = userId; 87 | } 88 | 89 | /** 90 | * 获取自习室编号 91 | * 92 | * @return room_number - 自习室编号 93 | */ 94 | public String getRoomNumber() { 95 | return roomNumber; 96 | } 97 | 98 | /** 99 | * 设置自习室编号 100 | * 101 | * @param roomNumber 自习室编号 102 | */ 103 | public void setRoomNumber(String roomNumber) { 104 | this.roomNumber = roomNumber; 105 | } 106 | 107 | /** 108 | * 获取由 row + _ + col 组成 109 | * 110 | * @return seats_number - 由 row + _ + col 组成 111 | */ 112 | public String getSeatsNumber() { 113 | return seatsNumber; 114 | } 115 | 116 | /** 117 | * 设置由 row + _ + col 组成 118 | * 119 | * @param seatsNumber 由 row + _ + col 组成 120 | */ 121 | public void setSeatsNumber(String seatsNumber) { 122 | this.seatsNumber = seatsNumber; 123 | } 124 | 125 | /** 126 | * 获取存放时间戳差 127 | * 128 | * @return stay_time - 存放时间戳差 129 | */ 130 | public int getStayTime() { 131 | return stayTime; 132 | } 133 | 134 | /** 135 | * 设置存放时间戳差 136 | * 137 | * @param stayTime 存放时间戳差 138 | */ 139 | public void setStayTime(int stayTime) { 140 | this.stayTime = stayTime; 141 | } 142 | 143 | /** 144 | * 获取0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 145 | * 146 | * @return status - 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 147 | */ 148 | public Integer getStatus() { 149 | return status; 150 | } 151 | 152 | /** 153 | * 设置0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 154 | * 155 | * @param status 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 156 | */ 157 | public void setStatus(Integer status) { 158 | this.status = status; 159 | } 160 | 161 | /** 162 | * 获取心情标签 (数组, 用 ,分隔) 163 | * 164 | * @return montent_tag - 心情标签 (数组, 用 ,分隔) 165 | */ 166 | public String getMontentTag() { 167 | return momentTag; 168 | } 169 | 170 | /** 171 | * 设置心情标签 (数组, 用 ,分隔) 172 | * 173 | * @param montentTag 心情标签 (数组, 用 ,分隔) 174 | */ 175 | public void setMontentTag(String montentTag) { 176 | this.momentTag = montentTag; 177 | } 178 | 179 | /** 180 | * 获取坐下时间 181 | * 182 | * @return created_time - 坐下时间 183 | */ 184 | // public String getCreatedTime() { 185 | // return createdTime; 186 | // } 187 | 188 | /** 189 | * 设置坐下时间 190 | * 191 | * @param createdTime 坐下时间 192 | */ 193 | // public void setCreatedTime(String createdTime) { 194 | // this.createdTime = createdTime; 195 | // } 196 | 197 | /** 198 | * 获取更新时间 199 | * 200 | * @return updated_time - 更新时间 201 | */ 202 | // public String getUpdatedTime() { 203 | // return updatedTime; 204 | // } 205 | 206 | /** 207 | * 设置更新时间 208 | * 209 | * @param updatedTime 更新时间 210 | */ 211 | // public void setUpdatedTime(String updatedTime) { 212 | // this.updatedTime = updatedTime; 213 | // } 214 | 215 | 216 | public void setWantedTime(int wantedTime) { 217 | this.wantedTime = wantedTime; 218 | } 219 | 220 | public int getWantedTime() { 221 | return wantedTime; 222 | } 223 | } 224 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/model/Seat.java: -------------------------------------------------------------------------------- 1 | package com.study.room.model; 2 | 3 | import javax.persistence.*; 4 | import java.sql.Timestamp; 5 | 6 | public class Seat { 7 | 8 | public interface SEAT { 9 | /** 10 | * 座位为空 11 | */ 12 | char EMPTY = '0'; 13 | 14 | /** 15 | * 座位被坐下 16 | */ 17 | char FULL = '1'; 18 | } 19 | 20 | public interface STATUS { 21 | /** 22 | * 待用 23 | */ 24 | Integer WAIT = 0; 25 | /** 26 | * 启用 27 | */ 28 | Integer USE = 1; 29 | /** 30 | * 维护 31 | */ 32 | Integer STOP = -1; 33 | } 34 | 35 | @Id 36 | @GeneratedValue(strategy = GenerationType.IDENTITY) 37 | private String id; 38 | 39 | /** 40 | * 自习室名称 41 | */ 42 | private String name; 43 | 44 | /** 45 | * 自习室编号 46 | */ 47 | @Column(name = "room_number") 48 | private String roomNumber; 49 | 50 | /** 51 | * 座位位置和状态 52 | */ 53 | private String seats; 54 | 55 | /** 56 | * 座位总数 57 | */ 58 | @Column(name = "seats_count") 59 | private Integer seatsCount; 60 | 61 | /** 62 | * 剩余座位数量 63 | */ 64 | @Column(name = "seats_available") 65 | private Integer seatsAvailable; 66 | 67 | /** 68 | * 已使用座位数量 69 | */ 70 | @Column(name = "seats_unavailabe") 71 | private Integer seatsUnavailabe; 72 | 73 | /** 74 | * 0: 待用; 1: 启用; -1: 维护 75 | */ 76 | private Integer status; 77 | 78 | @Column(name = "created_time") 79 | private Timestamp createdTime; 80 | 81 | @Column(name = "updated_time") 82 | private Timestamp updatedTime; 83 | 84 | /** 85 | * @return id 86 | */ 87 | public String getId() { 88 | return id; 89 | } 90 | 91 | /** 92 | * @param id 93 | */ 94 | public void setId(String id) { 95 | this.id = id; 96 | } 97 | 98 | /** 99 | * 获取自习室名称 100 | * 101 | * @return name - 自习室名称 102 | */ 103 | public String getName() { 104 | return name; 105 | } 106 | 107 | /** 108 | * 设置自习室名称 109 | * 110 | * @param name 自习室名称 111 | */ 112 | public void setName(String name) { 113 | this.name = name; 114 | } 115 | 116 | /** 117 | * 获取自习室编号 118 | * 119 | * @return room_number - 自习室编号 120 | */ 121 | public String getRoomNumber() { 122 | return roomNumber; 123 | } 124 | 125 | /** 126 | * 设置自习室编号 127 | * 128 | * @param roomNumber 自习室编号 129 | */ 130 | public void setRoomNumber(String roomNumber) { 131 | this.roomNumber = roomNumber; 132 | } 133 | 134 | /** 135 | * 获取座位位置和状态 136 | * 137 | * @return seats - 座位位置和状态 138 | */ 139 | public String getSeats() { 140 | return seats; 141 | } 142 | 143 | /** 144 | * 设置座位位置和状态 145 | * 146 | * @param seats 座位位置和状态 147 | */ 148 | public void setSeats(String seats) { 149 | this.seats = seats; 150 | } 151 | 152 | /** 153 | * 获取座位总数 154 | * 155 | * @return seats_count - 座位总数 156 | */ 157 | public Integer getSeatsCount() { 158 | return seatsCount; 159 | } 160 | 161 | /** 162 | * 设置座位总数 163 | * 164 | * @param seatsCount 座位总数 165 | */ 166 | public void setSeatsCount(Integer seatsCount) { 167 | this.seatsCount = seatsCount; 168 | } 169 | 170 | /** 171 | * 获取剩余座位数量 172 | * 173 | * @return seats_available - 剩余座位数量 174 | */ 175 | public Integer getSeatsAvailable() { 176 | return seatsAvailable; 177 | } 178 | 179 | /** 180 | * 设置剩余座位数量 181 | * 182 | * @param seatsAvailable 剩余座位数量 183 | */ 184 | public void setSeatsAvailable(Integer seatsAvailable) { 185 | this.seatsAvailable = seatsAvailable; 186 | } 187 | 188 | /** 189 | * 获取已使用座位数量 190 | * 191 | * @return seats_unavailabe - 已使用座位数量 192 | */ 193 | public Integer getSeatsUnavailabe() { 194 | return seatsUnavailabe; 195 | } 196 | 197 | /** 198 | * 设置已使用座位数量 199 | * 200 | * @param seatsUnavailabe 已使用座位数量 201 | */ 202 | public void setSeatsUnavailabe(Integer seatsUnavailabe) { 203 | this.seatsUnavailabe = seatsUnavailabe; 204 | } 205 | 206 | /** 207 | * 获取0: 待用; 1: 启用; -1: 维护 208 | * 209 | * @return status - 0: 待用; 1: 启用; -1: 维护 210 | */ 211 | public Integer getStatus() { 212 | return status; 213 | } 214 | 215 | /** 216 | * 设置0: 待用; 1: 启用; -1: 维护 217 | * 218 | * @param status 0: 待用; 1: 启用; -1: 维护 219 | */ 220 | public void setStatus(Integer status) { 221 | this.status = status; 222 | } 223 | 224 | /** 225 | * @return created_time 226 | */ 227 | public Timestamp getCreatedTime() { 228 | return createdTime; 229 | } 230 | 231 | /** 232 | * @param createdTime 233 | */ 234 | public void setCreatedTime(Timestamp createdTime) { 235 | this.createdTime = createdTime; 236 | } 237 | 238 | /** 239 | * @return updated_time 240 | */ 241 | public Timestamp getUpdatedTime() { 242 | return updatedTime; 243 | } 244 | 245 | /** 246 | * @param updatedTime 247 | */ 248 | public void setUpdatedTime(Timestamp updatedTime) { 249 | this.updatedTime = updatedTime; 250 | } 251 | } -------------------------------------------------------------------------------- /src/main/java/com/study/room/model/User.java: -------------------------------------------------------------------------------- 1 | package com.study.room.model; 2 | 3 | import javax.persistence.*; 4 | import java.sql.Timestamp; 5 | 6 | public class User { 7 | 8 | /** 9 | * 进入黑名单次数 10 | */ 11 | public interface BAD { 12 | int BADCOUNT = 3; 13 | } 14 | 15 | /** 16 | * 用户角色区分 17 | */ 18 | public interface ROLE { 19 | /** 20 | * 普通用户 21 | */ 22 | int USER = 0; 23 | /** 24 | * 管理员 25 | */ 26 | int ADMIN = 1; 27 | /** 28 | * 超级管理员 29 | */ 30 | int SUPER = 2; 31 | } 32 | 33 | /** 34 | * 用户状态 35 | */ 36 | public interface STATUS { 37 | /** 38 | * 停用状态 39 | */ 40 | int STOP = 0; 41 | /** 42 | * 正常使用状态 43 | */ 44 | int NORMAL = 1; 45 | /** 46 | * 黑名单状态 47 | */ 48 | int BAD = -1; 49 | } 50 | 51 | @Id 52 | @GeneratedValue(strategy = GenerationType.IDENTITY) 53 | private String id; 54 | 55 | /** 56 | * 用户名称 57 | */ 58 | private String name; 59 | 60 | /** 61 | * 管理员/学生 62 | */ 63 | private String password; 64 | 65 | /** 66 | * 学生学号 67 | */ 68 | @Column(name = "student_num") 69 | private String studentNum; 70 | 71 | /** 72 | * 用户电话 73 | */ 74 | private String phone; 75 | 76 | /** 77 | * 0: 普通用户;1: 管理员; 2: 超级管理员 78 | */ 79 | private Integer role; 80 | 81 | /** 82 | * 0: 停用; 1: 启用; -1: 黑名单 83 | */ 84 | private Integer status; 85 | 86 | /** 87 | * 默认0, 到3 自动转换黑名单 88 | */ 89 | @Column(name = "bad_record") 90 | private Integer badRecord; 91 | 92 | @Column(name = "created_time") 93 | private Timestamp createdTime; 94 | 95 | @Column(name = "updated_time") 96 | private Timestamp updatedTime; 97 | 98 | /** 99 | * @return id 100 | */ 101 | public String getId() { 102 | return id; 103 | } 104 | 105 | /** 106 | * @param id 107 | */ 108 | public void setId(String id) { 109 | this.id = id; 110 | } 111 | 112 | /** 113 | * 获取用户名称 114 | * 115 | * @return name - 用户名称 116 | */ 117 | public String getName() { 118 | return name; 119 | } 120 | 121 | /** 122 | * 设置用户名称 123 | * 124 | * @param name 用户名称 125 | */ 126 | public void setName(String name) { 127 | this.name = name; 128 | } 129 | 130 | /** 131 | * 获取管理员/学生 132 | * 133 | * @return password - 管理员/学生 134 | */ 135 | public String getPassword() { 136 | return password; 137 | } 138 | 139 | /** 140 | * 设置管理员/学生 141 | * 142 | * @param password 管理员/学生 143 | */ 144 | public void setPassword(String password) { 145 | this.password = password; 146 | } 147 | 148 | /** 149 | * 获取学生学号 150 | * 151 | * @return student_num - 学生学号 152 | */ 153 | public String getStudentNum() { 154 | return studentNum; 155 | } 156 | 157 | /** 158 | * 设置学生学号 159 | * 160 | * @param studentNum 学生学号 161 | */ 162 | public void setStudentNum(String studentNum) { 163 | this.studentNum = studentNum; 164 | } 165 | 166 | /** 167 | * 获取用户电话 168 | * 169 | * @return phone - 用户电话 170 | */ 171 | public String getPhone() { 172 | return phone; 173 | } 174 | 175 | /** 176 | * 设置用户电话 177 | * 178 | * @param phone 用户电话 179 | */ 180 | public void setPhone(String phone) { 181 | this.phone = phone; 182 | } 183 | 184 | /** 185 | * 获取0: 普通用户;1: 管理员; 2: 超级管理员 186 | * 187 | * @return role - 0: 普通用户;1: 管理员; 2: 超级管理员 188 | */ 189 | public Integer getRole() { 190 | return role; 191 | } 192 | 193 | /** 194 | * 设置0: 普通用户;1: 管理员; 2: 超级管理员 195 | * 196 | * @param role 0: 普通用户;1: 管理员; 2: 超级管理员 197 | */ 198 | public void setRole(Integer role) { 199 | this.role = role; 200 | } 201 | 202 | /** 203 | * 获取0: 停用; 1: 启用; -1: 黑名单 204 | * 205 | * @return status - 0: 停用; 1: 启用; -1: 黑名单 206 | */ 207 | public Integer getStatus() { 208 | return status; 209 | } 210 | 211 | /** 212 | * 设置0: 停用; 1: 启用; -1: 黑名单 213 | * 214 | * @param status 0: 停用; 1: 启用; -1: 黑名单 215 | */ 216 | public void setStatus(Integer status) { 217 | this.status = status; 218 | } 219 | 220 | /** 221 | * 获取默认0, 到3 自动转换黑名单 222 | * 223 | * @return bad_record - 默认0, 到3 自动转换黑名单 224 | */ 225 | public Integer getBadRecord() { 226 | return badRecord; 227 | } 228 | 229 | /** 230 | * 设置默认0, 到3 自动转换黑名单 231 | * 232 | * @param badRecord 默认0, 到3 自动转换黑名单 233 | */ 234 | public void setBadRecord(Integer badRecord) { 235 | this.badRecord = badRecord; 236 | } 237 | 238 | /** 239 | * @return created_time 240 | */ 241 | public Timestamp getCreatedTime() { 242 | return createdTime; 243 | } 244 | 245 | /** 246 | * @param createdTime 247 | */ 248 | public void setCreatedTime(Timestamp createdTime) { 249 | this.createdTime = createdTime; 250 | } 251 | 252 | /** 253 | * @return updated_time 254 | */ 255 | public Timestamp getUpdatedTime() { 256 | return updatedTime; 257 | } 258 | 259 | /** 260 | * @param updatedTime 261 | */ 262 | public void setUpdatedTime(Timestamp updatedTime) { 263 | this.updatedTime = updatedTime; 264 | } 265 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.zhbit 8 | seat-of-study-room 9 | 1.0 10 | jar 11 | 12 | 13 | 1.8 14 | 2.4.0 15 | 16 | 17 | 18 | 19 | org.springframework.boot 20 | spring-boot-starter-parent 21 | 1.5.13.RELEASE 22 | 23 | 24 | 25 | 26 | 27 | org.springframework.boot 28 | spring-boot-starter-web 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-starter-jdbc 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-test 37 | test 38 | 39 | 40 | 41 | commons-codec 42 | commons-codec 43 | 44 | 45 | org.apache.commons 46 | commons-lang3 47 | 3.6 48 | 49 | 50 | com.google.guava 51 | guava 52 | 23.0 53 | 54 | 55 | 56 | mysql 57 | mysql-connector-java 58 | runtime 59 | 60 | 61 | 62 | org.mybatis 63 | mybatis-spring 64 | 1.3.1 65 | 66 | 67 | org.mybatis 68 | mybatis 69 | 3.4.5 70 | 71 | 72 | tk.mybatis 73 | mapper 74 | 3.4.2 75 | 76 | 77 | com.github.pagehelper 78 | pagehelper 79 | 4.2.1 80 | 81 | 82 | 83 | com.alibaba 84 | fastjson 85 | 1.2.47 86 | 87 | 88 | 89 | com.alibaba 90 | druid-spring-boot-starter 91 | 1.1.10 92 | 93 | 94 | 95 | org.freemarker 96 | freemarker 97 | 2.3.23 98 | test 99 | 100 | 101 | org.mybatis.generator 102 | mybatis-generator-core 103 | 1.3.5 104 | test 105 | 106 | 107 | 108 | io.springfox 109 | springfox-swagger-ui 110 | ${springfox-swagger-ui.version} 111 | 112 | 113 | 114 | io.springfox 115 | springfox-swagger2 116 | ${springfox-swagger-ui.version} 117 | 118 | 119 | 120 | 121 | com.auth0 122 | java-jwt 123 | 3.4.0 124 | 125 | 126 | 127 | 128 | 129 | 130 | org.springframework.boot 131 | spring-boot-maven-plugin 132 | 133 | 134 | maven-compiler-plugin 135 | 136 | ${java.version} 137 | ${java.version} 138 | UTF-8 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | aliyun-repos 147 | http://maven.aliyun.com/nexus/content/groups/public/ 148 | 149 | false 150 | 151 | 152 | 153 | 154 | 155 | 156 | aliyun-plugin 157 | http://maven.aliyun.com/nexus/content/groups/public/ 158 | 159 | false 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/web/UserController.java: -------------------------------------------------------------------------------- 1 | package com.study.room.web; 2 | 3 | import com.study.room.configurer.PassToken; 4 | import com.study.room.configurer.UserLoginToken; 5 | import com.study.room.configurer.WebMvcConfigurer; 6 | import com.study.room.core.Result; 7 | import com.study.room.core.ResultGenerator; 8 | import com.study.room.dto.CreateUserDTO; 9 | import com.study.room.dto.UserDTO; 10 | import com.study.room.model.User; 11 | import com.study.room.service.UserService; 12 | import com.github.pagehelper.PageHelper; 13 | import com.github.pagehelper.PageInfo; 14 | import com.study.room.utils.MD5Utils; 15 | import com.study.room.utils.Tools; 16 | import io.swagger.annotations.Api; 17 | import io.swagger.annotations.ApiImplicitParam; 18 | import io.swagger.annotations.ApiImplicitParams; 19 | import io.swagger.annotations.ApiOperation; 20 | import org.springframework.beans.BeanUtils; 21 | import org.springframework.web.bind.annotation.*; 22 | 23 | import javax.annotation.Resource; 24 | import java.util.List; 25 | 26 | /** 27 | * Created by CodeGenerator on 2020/03/21. 28 | */ 29 | @Api(value = "userController", tags = "用户操作接口") 30 | @RestController 31 | @RequestMapping("/user") 32 | public class UserController { 33 | @Resource 34 | private UserService userService; 35 | 36 | @ApiOperation(value = "login", notes = "用户登录接口") 37 | @PassToken 38 | @PostMapping("/login") 39 | public Result login(@RequestParam String username, @RequestParam String password) { 40 | User user = userService.login(username, password); 41 | 42 | if (user == null) { 43 | return ResultGenerator.genFailResult("登录失败~"); 44 | } else { 45 | String token = Tools.getToken(user); 46 | return ResultGenerator.genSuccessResult(token); 47 | } 48 | } 49 | 50 | // @UserLoginToken 51 | @PostMapping 52 | public Result add(@RequestBody CreateUserDTO userDTO) { 53 | User user = new User(); 54 | 55 | BeanUtils.copyProperties(userDTO, user); 56 | 57 | user.setId(Tools.getUUID()); 58 | 59 | user.setPassword(MD5Utils.StringToMD5_hex("admin")); 60 | 61 | user.setCreatedTime(Tools.getTimeStamp()); 62 | 63 | // 实体类里没有添加控制 64 | if (user.getBadRecord() == null) { 65 | user.setBadRecord(0); 66 | } 67 | userService.save(user); 68 | return ResultGenerator.genSuccessResult(); 69 | } 70 | 71 | @UserLoginToken 72 | @DeleteMapping("/{id}") 73 | public Result delete(@PathVariable String id) { 74 | userService.deleteById(id); 75 | return ResultGenerator.genSuccessResult(); 76 | } 77 | 78 | @UserLoginToken 79 | @PutMapping 80 | public Result update(@RequestBody User user) { 81 | userService.update(user); 82 | return ResultGenerator.genSuccessResult(); 83 | } 84 | 85 | @UserLoginToken 86 | @GetMapping("/info") 87 | public Result detail() { 88 | User user = WebMvcConfigurer.getLoginUser(); 89 | 90 | return ResultGenerator.genSuccessResult(user); 91 | } 92 | 93 | @ApiOperation(value = "getUserInfoById", notes = "根据 User id返回学生信息") 94 | @ApiImplicitParam(value = "id", name = "id", dataType = "String", paramType = "path") 95 | @UserLoginToken 96 | @GetMapping("/{id}") 97 | public Result getUserInfoById(@PathVariable String id) { 98 | // User user = WebMvcConfigurer.getLoginUser(); 99 | User user = userService.findById(id); 100 | return ResultGenerator.genSuccessResult(user); 101 | } 102 | 103 | @ApiOperation(value = "getUserInfoByNo", notes = "根据学号返回学生信息") 104 | @ApiImplicitParam(value = "学号", name = "studentNum", dataType = "String", paramType = "path") 105 | @UserLoginToken 106 | @GetMapping("/studentNum/{studentNum}") 107 | public Result getUserInfoByNo(@PathVariable String studentNum) { 108 | // User user = WebMvcConfigurer.getLoginUser(); 109 | User user = userService.findBy("studentNum", studentNum); 110 | return ResultGenerator.genSuccessResult(user); 111 | } 112 | 113 | @UserLoginToken 114 | @GetMapping 115 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) { 116 | PageHelper.startPage(page, size); 117 | List list = userService.findAll(); 118 | PageInfo pageInfo = new PageInfo(list); 119 | return ResultGenerator.genSuccessResult(pageInfo); 120 | } 121 | 122 | // @UserLoginToken 123 | @GetMapping("/admin/list") 124 | public Result getAdminUser() { 125 | List user = userService.findAdminUsers(); 126 | 127 | return ResultGenerator.genSuccessResult(user); 128 | } 129 | 130 | @ApiOperation(value = "getUserInfoByNo", notes = "用户重置密码") 131 | // @ApiImplicitParam(value = "学号", name = "studentNum", dataType = "String", paramType = "path") 132 | @UserLoginToken 133 | @PutMapping("/modification/password") 134 | public Result changePassword(@RequestParam String oldPass, @RequestParam String newPass) { 135 | User user = WebMvcConfigurer.getLoginUser(); 136 | 137 | if (user.getPassword().equals(MD5Utils.StringToMD5_hex(oldPass))) { 138 | user.setPassword(MD5Utils.StringToMD5_hex(newPass)); 139 | } else { 140 | return ResultGenerator.genFailResult("原密码错误, 请再次尝试~"); 141 | } 142 | 143 | this.update(user); 144 | 145 | return ResultGenerator.genSuccessResult(); 146 | } 147 | 148 | @ApiOperation(value = "resetPasswordByAdmin", notes = "根据学生学号重置学生密码") 149 | @ApiImplicitParam(value = "学号", name = "studentNum", dataType = "String", paramType = "path") 150 | @UserLoginToken 151 | @PostMapping("/admin/reset/studentNum/{studentNum}") 152 | public Result resetPasswordByAdmin(@PathVariable String studentNum) { 153 | User user = userService.findBy("studentNum", studentNum); 154 | if (user == null) { 155 | return ResultGenerator.genFailResult("用户不存在~"); 156 | } 157 | 158 | user.setPassword(MD5Utils.StringToMD5_hex("admin")); 159 | userService.update(user); 160 | 161 | return ResultGenerator.genSuccessResult(); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/model/Footprint.java: -------------------------------------------------------------------------------- 1 | package com.study.room.model; 2 | 3 | import javax.persistence.*; 4 | import java.sql.Timestamp; 5 | 6 | public class Footprint { 7 | 8 | public interface STATUS { 9 | /** 10 | * 正常坐下 11 | */ 12 | Integer IN = 1; 13 | 14 | /** 15 | * 正常离开 16 | */ 17 | Integer OUT = -1; 18 | 19 | /** 20 | * 暂时离开 21 | */ 22 | Integer TEMP = 0; 23 | } 24 | 25 | public interface TIME { 26 | /** 27 | * 暂离 28 | */ 29 | Integer TEMP = 20 * 60 * 1000; 30 | 31 | /** 32 | * 暂离 (test) 33 | */ 34 | Integer TEMP_TEST = 2 * 60 * 1000; 35 | 36 | /** 37 | * 抢座 38 | */ 39 | Integer GRAB = 20 * 60 * 1000; 40 | 41 | /** 42 | * 抢座 (test) 43 | */ 44 | Integer GRAB_TEST = 2 * 60 * 1000; 45 | } 46 | 47 | 48 | @Id 49 | @GeneratedValue(strategy = GenerationType.IDENTITY) 50 | private String id; 51 | 52 | @Column(name = "user_id") 53 | private String userId; 54 | 55 | /** 56 | * 自习室编号 57 | */ 58 | @Column(name = "room_number") 59 | private String roomNumber; 60 | 61 | /** 62 | * 由 row + _ + col 组成 63 | */ 64 | @Column(name = "seats_number") 65 | private String seatsNumber; 66 | 67 | /** 68 | * 学生希望自习的时间 69 | */ 70 | @Column(name = "wanted_time") 71 | private int wantedTime; 72 | 73 | /** 74 | * 存放时间戳差 75 | */ 76 | @Column(name = "stay_time") 77 | private int stayTime; 78 | 79 | /** 80 | * 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 81 | */ 82 | private Integer status; 83 | 84 | /** 85 | * 心情标签 (数组, 用 ,分隔) 86 | */ 87 | @Column(name = "moment_tag") 88 | private String momentTag; 89 | 90 | /** 91 | * 坐下时间 92 | */ 93 | @Column(name = "created_time") 94 | private Timestamp createdTime; 95 | 96 | /** 97 | * 更新时间 98 | */ 99 | @Column(name = "updated_time") 100 | private Timestamp updatedTime; 101 | 102 | /** 103 | * @return id 104 | */ 105 | public String getId() { 106 | return id; 107 | } 108 | 109 | /** 110 | * @param id 111 | */ 112 | public void setId(String id) { 113 | this.id = id; 114 | } 115 | 116 | /** 117 | * @return user_id 118 | */ 119 | public String getUserId() { 120 | return userId; 121 | } 122 | 123 | /** 124 | * @param userId 125 | */ 126 | public void setUserId(String userId) { 127 | this.userId = userId; 128 | } 129 | 130 | /** 131 | * 获取自习室编号 132 | * 133 | * @return room_number - 自习室编号 134 | */ 135 | public String getRoomNumber() { 136 | return roomNumber; 137 | } 138 | 139 | /** 140 | * 设置自习室编号 141 | * 142 | * @param roomNumber 自习室编号 143 | */ 144 | public void setRoomNumber(String roomNumber) { 145 | this.roomNumber = roomNumber; 146 | } 147 | 148 | /** 149 | * 获取由 row + _ + col 组成 150 | * 151 | * @return seats_number - 由 row + _ + col 组成 152 | */ 153 | public String getSeatsNumber() { 154 | return seatsNumber; 155 | } 156 | 157 | /** 158 | * 设置由 row + _ + col 组成 159 | * 160 | * @param seatsNumber 由 row + _ + col 组成 161 | */ 162 | public void setSeatsNumber(String seatsNumber) { 163 | this.seatsNumber = seatsNumber; 164 | } 165 | 166 | /** 167 | * 获取存放时间戳差 168 | * 169 | * @return stay_time - 存放时间戳差 170 | */ 171 | public int getStayTime() { 172 | return stayTime; 173 | } 174 | 175 | /** 176 | * 设置存放时间戳差 177 | * 178 | * @param stayTime 存放时间戳差 179 | */ 180 | public void setStayTime(int stayTime) { 181 | this.stayTime = stayTime; 182 | } 183 | 184 | /** 185 | * 获取0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 186 | * 187 | * @return status - 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 188 | */ 189 | public Integer getStatus() { 190 | return status; 191 | } 192 | 193 | /** 194 | * 设置0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 195 | * 196 | * @param status 0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时) 197 | */ 198 | public void setStatus(Integer status) { 199 | this.status = status; 200 | } 201 | 202 | /** 203 | * 获取心情标签 (数组, 用 ,分隔) 204 | * 205 | * @return montent_tag - 心情标签 (数组, 用 ,分隔) 206 | */ 207 | public String getMomentTag() { 208 | return momentTag; 209 | } 210 | 211 | /** 212 | * 设置心情标签 (数组, 用 ,分隔) 213 | * 214 | * @param momentTag 心情标签 (数组, 用 ,分隔) 215 | */ 216 | public void setMomentTag(String momentTag) { 217 | this.momentTag = momentTag; 218 | } 219 | 220 | /** 221 | * 获取坐下时间 222 | * 223 | * @return created_time - 坐下时间 224 | */ 225 | public Timestamp getCreatedTime() { 226 | return createdTime; 227 | } 228 | 229 | /** 230 | * 设置坐下时间 231 | * 232 | * @param createdTime 坐下时间 233 | */ 234 | public void setCreatedTime(Timestamp createdTime) { 235 | this.createdTime = createdTime; 236 | } 237 | 238 | /** 239 | * 获取更新时间 240 | * 241 | * @return updated_time - 更新时间 242 | */ 243 | public Timestamp getUpdatedTime() { 244 | return updatedTime; 245 | } 246 | 247 | /** 248 | * 设置更新时间 249 | * 250 | * @param updatedTime 更新时间 251 | */ 252 | public void setUpdatedTime(Timestamp updatedTime) { 253 | this.updatedTime = updatedTime; 254 | } 255 | 256 | /** 257 | * 设置学生希望自习的时间 258 | * 259 | * @param wantedTime 自习时间 260 | */ 261 | public void setWantedTime(int wantedTime) { 262 | this.wantedTime = wantedTime; 263 | } 264 | 265 | /** 266 | * 返回学生希望自习的时间 267 | * 268 | * @return wantedTime 自习时间 269 | */ 270 | public int getWantedTime() { 271 | return wantedTime; 272 | } 273 | 274 | /** 275 | * 座位的行列数组 276 | * 277 | * @return String[] 行列数组 278 | */ 279 | private String[] getSeatsOfRowCol() { 280 | return this.seatsNumber.split(","); 281 | } 282 | 283 | /** 284 | * 座位的行列 285 | * 286 | * @return row 行 287 | */ 288 | public int getRow() { 289 | return Integer.parseInt(this.getSeatsOfRowCol()[0]); 290 | } 291 | 292 | /** 293 | * 座位的行列 294 | * 295 | * @return col 列 296 | */ 297 | public int getCol() { 298 | return Integer.parseInt(this.getSeatsOfRowCol()[1]); 299 | } 300 | } -------------------------------------------------------------------------------- /src/main/java/com/study/room/web/FootprintController.java: -------------------------------------------------------------------------------- 1 | package com.study.room.web; 2 | 3 | import com.study.room.configurer.UserLoginToken; 4 | import com.study.room.configurer.WebMvcConfigurer; 5 | import com.study.room.core.Result; 6 | import com.study.room.core.ResultGenerator; 7 | import com.study.room.dao.FootprintMapper; 8 | import com.study.room.dto.BoardDTO; 9 | import com.study.room.dto.FootprintDTO; 10 | import com.study.room.model.Footprint; 11 | import com.study.room.model.User; 12 | import com.study.room.service.FootprintService; 13 | import com.github.pagehelper.PageHelper; 14 | import com.github.pagehelper.PageInfo; 15 | import com.study.room.service.UserService; 16 | import io.swagger.annotations.Api; 17 | import io.swagger.annotations.ApiImplicitParam; 18 | import io.swagger.annotations.ApiImplicitParams; 19 | import io.swagger.annotations.ApiOperation; 20 | import org.springframework.beans.BeanUtils; 21 | import org.springframework.web.bind.annotation.*; 22 | import springfox.documentation.annotations.ApiIgnore; 23 | 24 | import javax.annotation.Resource; 25 | import java.text.ParseException; 26 | import java.text.SimpleDateFormat; 27 | import java.util.*; 28 | 29 | /** 30 | * Created by CodeGenerator on 2020/03/21. 31 | */ 32 | @Api(value = "footprint", tags = "座位记录信息操作") 33 | @RestController 34 | @RequestMapping("/footprint") 35 | public class FootprintController { 36 | @Resource 37 | private FootprintService footprintService; 38 | 39 | @Resource 40 | private FootprintMapper footprintMapper; 41 | 42 | @Resource 43 | private UserService userService; 44 | 45 | @ApiOperation(value = "checkTime", notes = "查看用户的已用时间 (如果已经在自习室坐下了) (1: 在座; 0: 暂离)") 46 | @UserLoginToken 47 | @GetMapping("/check/time") 48 | public Result checkTime() { 49 | User user = WebMvcConfigurer.getLoginUser(); 50 | 51 | // TODO: 返回已用时间 52 | int time = footprintService.checkTime(user.getId()); 53 | Footprint footprint = footprintService.findUseSeatByUserId(user.getId()); 54 | 55 | if (footprint == null) 56 | return ResultGenerator.genFailResult("你好像没有进行自习的座位~"); 57 | 58 | HashMap map = new HashMap(); 59 | 60 | if (footprint.getStatus() == Footprint.STATUS.IN) { 61 | map.put("status", Footprint.STATUS.IN); 62 | map.put("studiedTime", time); 63 | } 64 | 65 | if (footprint.getStatus() == Footprint.STATUS.TEMP) { 66 | map.put("status", Footprint.STATUS.TEMP); 67 | map.put("tempLeaveTime", time); 68 | } 69 | 70 | map.put("wantedTime", footprint.getWantedTime()); 71 | map.put("momentTag", footprint.getMomentTag()); 72 | 73 | return ResultGenerator.genSuccessResult(map); 74 | } 75 | 76 | @ApiOperation(value = "history", notes = "查看用户的历史信息, 可用于检查上一个座位的位置情况 (时间降序)") 77 | @UserLoginToken 78 | @GetMapping("/history") 79 | public Result history() { 80 | User user = WebMvcConfigurer.getLoginUser(); 81 | 82 | // TODO: 返回历史借座信息 83 | List footprints = footprintService.checkHistoryByUser(user.getId()); 84 | 85 | return ResultGenerator.genSuccessResult(footprints); 86 | } 87 | 88 | @ApiOperation(value = "leaderBoard", notes = "选择日期展示排行榜 (例子: 2020/04/14)") 89 | @ApiImplicitParams({ 90 | @ApiImplicitParam(value = "年", name = "year", dataType = "String", paramType = "path"), 91 | @ApiImplicitParam(value = "月", name = "month", dataType = "String", paramType = "path"), 92 | @ApiImplicitParam(value = "日", name = "day", dataType = "String", paramType = "path") 93 | }) 94 | @UserLoginToken 95 | @GetMapping("/leader/board/{year}/{month}/{day}") 96 | public Result leaderBoard(@PathVariable String year, @PathVariable String month, @PathVariable String day) throws ParseException { 97 | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");//注意月份是MM 98 | Date date = simpleDateFormat.parse(year + "-" + month + "-" + day); 99 | 100 | List board = footprintMapper.leaderBoard(date); 101 | 102 | if (board.size() == 0) 103 | return ResultGenerator.genSuccessResult(); 104 | 105 | List boardsWithUser = new ArrayList<>(); 106 | 107 | for (Footprint fp: board) { 108 | User user = userService.findById(fp.getUserId()); 109 | BoardDTO boardDTO = new BoardDTO(); 110 | BeanUtils.copyProperties(fp, boardDTO); 111 | boardDTO.setUser(user); 112 | if (boardsWithUser.contains(boardDTO)) { 113 | int index = boardsWithUser.indexOf(boardDTO); 114 | BoardDTO boardDTO1 = boardsWithUser.get(index); 115 | boardDTO1.setStayTime(boardDTO.getStayTime() + boardDTO1.getStayTime()); 116 | } else { 117 | boardsWithUser.add(boardDTO); 118 | } 119 | } 120 | 121 | return ResultGenerator.genSuccessResult(boardsWithUser); 122 | } 123 | 124 | @ApiOperation(value = "counterBoard", notes = "选择日期返回自习室的统计列表 (例子: 2020)") 125 | @ApiImplicitParams({ 126 | @ApiImplicitParam(value = "自习室编号", name = "roomNumber", dataType = "String", paramType = "path"), 127 | @ApiImplicitParam(value = "年", name = "year", dataType = "String", paramType = "path") 128 | }) 129 | @UserLoginToken 130 | @GetMapping("/room/{roomNumber}/counter/board/{year}") 131 | public Result counterBoard(@PathVariable String roomNumber, @PathVariable String year) throws ParseException { 132 | SimpleDateFormat simpleDateFormatYear = new SimpleDateFormat("yyyy");//注意月份是MM 133 | Date dateYear = simpleDateFormatYear.parse(year); 134 | List count = footprintMapper.counterBoard(roomNumber, dateYear); 135 | 136 | return ResultGenerator.genSuccessResult(count); 137 | } 138 | 139 | @ApiOperation(value = "checkOnSeatListByRoomNumber", notes = "根据自习室编号返回在座人员列表") 140 | @ApiImplicitParam(value = "自习室编号", name = "roomNumber", dataType = "String", paramType = "path") 141 | @UserLoginToken 142 | @GetMapping("/room/{roomNumber}") 143 | public Result checkOnSeatListByRoomNumber(@PathVariable String roomNumber) { 144 | footprintService.checkOnSeatListByRoomNumber(roomNumber); 145 | 146 | return ResultGenerator.genSuccessResult(roomNumber); 147 | } 148 | 149 | @ApiIgnore 150 | @UserLoginToken 151 | @PostMapping 152 | public Result add(@RequestBody Footprint footprint) { 153 | footprintService.save(footprint); 154 | return ResultGenerator.genSuccessResult(); 155 | } 156 | 157 | @ApiIgnore 158 | @UserLoginToken 159 | @DeleteMapping("/{id}") 160 | public Result delete(@PathVariable String id) { 161 | footprintService.deleteById(id); 162 | return ResultGenerator.genSuccessResult(); 163 | } 164 | 165 | @ApiIgnore 166 | @UserLoginToken 167 | @PutMapping 168 | public Result update(@RequestBody Footprint footprint) { 169 | footprintService.update(footprint); 170 | return ResultGenerator.genSuccessResult(); 171 | } 172 | 173 | @ApiIgnore 174 | @UserLoginToken 175 | @GetMapping("/{id}") 176 | public Result detail(@PathVariable String id) { 177 | Footprint footprint = footprintService.findById(id); 178 | return ResultGenerator.genSuccessResult(footprint); 179 | } 180 | 181 | @ApiIgnore 182 | @UserLoginToken 183 | @GetMapping 184 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) { 185 | PageHelper.startPage(page, size); 186 | List list = footprintService.findAll(); 187 | PageInfo pageInfo = new PageInfo(list); 188 | return ResultGenerator.genSuccessResult(pageInfo); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package com.study.room.utils; 2 | 3 | import com.alibaba.fastjson.JSON; 4 | import org.springframework.util.StringUtils; 5 | import org.springframework.web.multipart.MultipartFile; 6 | 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.*; 9 | import java.text.DateFormat; 10 | import java.text.SimpleDateFormat; 11 | import java.util.Date; 12 | import java.util.UUID; 13 | 14 | /** 15 | * TODO: 文件工具类 16 | * @Date 2019/11/5 上午11:01 17 | * @Author cjr7399 18 | */ 19 | public class FileUtils { 20 | 21 | private FileUtils(){} 22 | //生成文件路径 23 | public static String json_path = "/var/file/";// 24 | // public static String json_path = "file/";// 25 | 26 | 27 | /** 28 | * @Method saveFile 29 | * TODO: 保存文件 30 | * @param filepath 文件名 31 | * @param content 内容 32 | * @Return boolean 33 | * @Exception 34 | * @Date 2019/11/5 上午11:04 35 | * @Author cjr7399 36 | */ 37 | public static boolean saveFile(String filepath, String content){ 38 | Boolean bool = false; 39 | 40 | File file = new File(filepath); 41 | 42 | try { 43 | if (!file.exists()) { 44 | file.createNewFile(); 45 | bool = true; 46 | } 47 | BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))); 48 | bufferedWriter.write(content); 49 | bufferedWriter.flush(); 50 | }catch (Exception e){ 51 | e.printStackTrace(); 52 | } 53 | return bool; 54 | } 55 | 56 | /** 57 | * @Method saveFile 58 | * TODO: 保存文件 59 | * @param filepath 文件名 60 | * @param inputStream 输入流 61 | * @Return file 62 | * @Exception 63 | * @Date 2019/11/5 上午11:06 64 | * @Author cjr7399 65 | */ 66 | public static File saveFile(String filepath, InputStream inputStream){ 67 | File file = new File(filepath); 68 | 69 | try { 70 | if (!file.exists()) { 71 | file.createNewFile(); 72 | BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))); 73 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 74 | String line = null; 75 | while ((line = bufferedReader.readLine()) != null){ 76 | bufferedWriter.write(line); 77 | bufferedWriter.flush(); 78 | bufferedWriter.newLine(); 79 | } 80 | return file; 81 | } 82 | }catch (Exception e){ 83 | e.printStackTrace(); 84 | } 85 | return null; 86 | } 87 | 88 | /** 89 | * @Method outputFile 90 | * TODO: CSV文件导出到输出流中 91 | * @param response 响应对象 92 | * @param fileName 文件名称 93 | * @param content 内容 94 | * @Return void 95 | * @Exception 96 | * @Date 2019/11/5 上午11:07 97 | * @Author cjr7399 98 | */ 99 | public static void outputFile(HttpServletResponse response, String fileName, String content) throws Exception{ 100 | saveFile(json_path + fileName, content); 101 | response.reset(); 102 | response.setContentType("application/octet-stream"); 103 | response.setHeader("Content-Disposition", "attchement;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1")); 104 | File file = new File(json_path + fileName); 105 | byte[] buffer = new byte[1024]; 106 | FileInputStream fis = null; 107 | BufferedInputStream bis = null; 108 | try { 109 | fis = new FileInputStream(file); 110 | bis = new BufferedInputStream(fis); 111 | OutputStream os = response.getOutputStream(); 112 | int i = bis.read(buffer); 113 | while (i != -1) { 114 | os.write(buffer, 0, i); 115 | i = bis.read(buffer); 116 | } 117 | System.out.println("success"); 118 | } catch (Exception e) { 119 | e.printStackTrace(); 120 | } finally { 121 | if (bis != null) { 122 | try { 123 | bis.close(); 124 | } catch (IOException e) { 125 | e.printStackTrace(); 126 | } 127 | } 128 | if (fis != null) { 129 | try { 130 | fis.close(); 131 | } catch (IOException e) { 132 | e.printStackTrace(); 133 | } 134 | } 135 | } 136 | } 137 | 138 | /** 139 | * @Method uploadFile 140 | * TODO: 保存上传的文件 141 | * @param file 142 | * @Return java.util.Map 143 | * @Exception 144 | * @Date 2019/11/5 上午11:10 145 | * @Author cjr7399 146 | */ 147 | public static File uploadFile(MultipartFile file) throws Exception{ 148 | String id = UUID.randomUUID().toString(); 149 | DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 150 | String times = dateFormat.format(new Date()); 151 | String randomStr = ((int) (Math.random() * 9000 + 1000)) + ""; 152 | String serverName = times + "_" + id + "_" + randomStr; 153 | serverName = serverName.replace("-","_"); 154 | 155 | String originalFilename = file.getOriginalFilename(); 156 | 157 | String[] split = originalFilename.split("\\."); 158 | String newName = serverName + "." + split[1]; 159 | return saveFile(json_path + newName, file.getInputStream()); 160 | 161 | /* Map map = new HashMap(); 162 | map.put("oldFileName", file.getName()); 163 | map.put("newFileNam", newName); 164 | map.put("src", json_path); 165 | map.put("uploadId", id);*/ 166 | // return fileDTO; 167 | } 168 | 169 | /** 170 | * @Method parseObject 171 | * TODO: 将CSV文件 办照 指定类型 解析 成实体 172 | * @param fileName 文件名 173 | * @param c 实体类型 174 | * @Return java.lang.Object JSONObject or JSONArrayu or null 175 | * @Exception 176 | * @Date 2019/11/5 上午11:11 177 | * @Author cjr7399 178 | */ 179 | public static Object parseObject(String fileName, Class c){ 180 | File file = new File(fileName); 181 | try { 182 | BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 183 | StringBuffer sb = new StringBuffer(); 184 | String line = null; 185 | while ((line = bufferedReader.readLine())!= null){ 186 | sb.append(line); 187 | } 188 | System.out.println(sb.toString()); 189 | Object parse = null; 190 | try { 191 | parse = JSON.parseObject(sb.toString(), c); 192 | return parse; 193 | } catch (Exception e) { 194 | e.printStackTrace(); 195 | } 196 | parse = JSON.parseArray(sb.toString(), c); 197 | return parse; 198 | } catch (IOException e) { 199 | e.printStackTrace(); 200 | } 201 | return null; 202 | } 203 | 204 | /*** 205 | * @Method readToString 206 | * TODO: 读取文本文件内容 已字符串返回 207 | * @param filename 208 | * @Return java.lang.String 209 | * @Exception 210 | * @Date 2019/11/7 上午10:00 211 | * @Author cjr7399 212 | */ 213 | public static String readToString(String filename){ 214 | String result = null; 215 | 216 | File file = new File(filename); 217 | try { 218 | BufferedReader bf = new BufferedReader(new InputStreamReader(new FileInputStream(file))); 219 | StringBuffer sb = new StringBuffer(); 220 | String line = null; 221 | while ((line = bf.readLine()) != null){ 222 | sb.append(line); 223 | } 224 | result = sb.toString(); 225 | } catch (FileNotFoundException e) { 226 | e.printStackTrace(); 227 | } catch (IOException e) { 228 | e.printStackTrace(); 229 | } 230 | 231 | return result; 232 | } 233 | 234 | public static Boolean copyFile(String oldFileName, String newFileName){ 235 | if(StringUtils.isEmpty(oldFileName) || StringUtils.isEmpty(newFileName))return Boolean.FALSE; 236 | File oldFile = new File(oldFileName); 237 | File newFile = new File(newFileName); 238 | if(oldFile.exists()){ 239 | try { 240 | System.out.println("开始复制文件: " + oldFileName); 241 | newFile.createNewFile(); 242 | InputStream is = new FileInputStream(oldFile); 243 | OutputStream os = new FileOutputStream(newFile); 244 | byte[] bytes = new byte[1024]; 245 | int index = -1; 246 | while ((index = is.read(bytes)) != -1){ 247 | os.write(bytes,0 , index); 248 | os.flush(); 249 | } 250 | is.close(); 251 | os.close(); 252 | System.out.println(oldFileName + "=复制完成。"); 253 | return Boolean.TRUE; 254 | } catch (IOException e) { 255 | e.printStackTrace(); 256 | } 257 | } 258 | 259 | return Boolean.FALSE; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/service/impl/SeatServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.study.room.service.impl; 2 | 3 | import com.study.room.dao.SeatMapper; 4 | import com.study.room.dto.FootprintDTO; 5 | import com.study.room.model.Footprint; 6 | import com.study.room.model.Seat; 7 | import com.study.room.service.FootprintService; 8 | import com.study.room.service.SeatService; 9 | import com.study.room.core.AbstractService; 10 | import com.study.room.utils.Tools; 11 | import org.slf4j.LoggerFactory; 12 | import org.springframework.beans.factory.annotation.Autowired; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import javax.annotation.Resource; 17 | import java.lang.reflect.Array; 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | 23 | /** 24 | * Created by CodeGenerator on 2020/03/21. 25 | */ 26 | @Service 27 | @Transactional 28 | public class SeatServiceImpl extends AbstractService implements SeatService { 29 | private final org.slf4j.Logger logger = LoggerFactory.getLogger(SeatServiceImpl.class); 30 | 31 | @Resource 32 | private SeatMapper seatMapper; 33 | 34 | @Autowired 35 | private FootprintService footprintService; 36 | 37 | public interface SEAT { 38 | int AVAILABLE = 0; 39 | int FULL = 1; 40 | int FULL_TEMP = -1; 41 | int ERROR = -2; 42 | 43 | } 44 | 45 | /** 46 | * @param room_num 47 | * @param row 48 | * @param col 49 | * @Method checkSeat 50 | * TODO: 联调各方面的数据, 确认是否能够坐下, 以及不可以的原因 (0: 可以坐下; 1: 不可以坐下 (有人); -1: 不可以坐下 (暂离); -2: 座位信息有误) 51 | * @Return int 52 | * @Exception 53 | * @Date 2020/3/22 11:56 AM 54 | * @Author hezijian6338 55 | * @Version 1.0 56 | */ 57 | public int checkSeat(String room_num, int row, int col) { 58 | // 传递的座位位置信息有误 59 | if (row == 0 || col == 0) 60 | return -2; 61 | Seat seats = this.findBy("roomNumber", room_num); 62 | String[] seat_list = seats.getSeats().replace(" ", "").replace("[", "").replace("]", "").split(","); 63 | 64 | // 判断获取座位的行数是否大于数组的大小 65 | if (row <= seat_list.length) { 66 | String seat_row = seat_list[row - 1]; 67 | char[] seat_col = seat_row.toCharArray(); 68 | 69 | // 判断获取座位的列数是否大于数组的大小 70 | if (col <= seat_col.length) { 71 | char status = seat_col[col - 1]; 72 | // 该座位有人, 但是不知道是暂离还是正在坐下但是人离开了 73 | if (status == Seat.SEAT.FULL) { 74 | // 组合座位的格式 75 | String seats_number = row + "," + col; 76 | // 检查返回的数据 77 | Footprint footprint = footprintService.checkSeatStatus(room_num, seats_number); 78 | 79 | // TODO: 存在一种情况就是: 游离数据, 座位坐下了, 但是没有该座位的足迹数据 (需要释放座位) 80 | if (footprint == null) { 81 | boolean result = this.leaveSeat(room_num, row, col); 82 | if (result) 83 | return SEAT.AVAILABLE; 84 | else 85 | return SEAT.ERROR; 86 | } 87 | 88 | // 只做了对数据进行检索的处理, 没有进行状态过期判断 √ 89 | // TODO: 根据返回的足迹信息进行对自己的状态进行检查 90 | int time = footprintService.checkTime(footprint.getUserId()); 91 | // 这两个状态都是足迹所在的用户会释放座位的状态或者是没有信息的状态 92 | if (time == footprint.getWantedTime() || time == 0) { 93 | return SEAT.AVAILABLE; 94 | } 95 | 96 | // 暂离 97 | if (footprint.getStatus() == Footprint.STATUS.TEMP) { 98 | return SEAT.FULL_TEMP; 99 | } 100 | // 正常坐着 (人不在了, 可以抢座) 101 | if (footprint.getStatus() == Footprint.STATUS.IN) { 102 | return SEAT.FULL; 103 | } 104 | } 105 | if (status == Seat.SEAT.EMPTY) { 106 | return SEAT.AVAILABLE; 107 | } 108 | } 109 | } 110 | return -2; 111 | } 112 | 113 | /** 114 | * @param room_num 115 | * @param row 116 | * @param col 117 | * @Method haveSeat 118 | * TODO: 进行正常座位坐下 119 | * @Return boolean 120 | * @Exception 121 | * @Date 2020/3/21 5:34 PM 122 | * @Author hezijian6338 123 | * @Version 1.0 124 | */ 125 | @Override 126 | public boolean haveSeat(String room_num, int row, int col) { 127 | // 传递的座位位置信息有误 128 | if (row == 0 || col == 0) 129 | return false; 130 | 131 | Seat seats = this.findBy("roomNumber", room_num); 132 | String[] seat_list = seats.getSeats().replace(" ", "").replace("[", "").replace("]", "").split(","); 133 | 134 | // 判断获取座位的行数是否大于数组的大小 135 | if (row <= seat_list.length) { 136 | String seat_row = seat_list[row - 1]; 137 | char[] seat_col = seat_row.toCharArray(); 138 | 139 | // 判断获取座位的列数是否大于数组的大小 140 | if (col <= seat_col.length) { 141 | char status = seat_col[col - 1]; 142 | if (status == Seat.SEAT.FULL) { 143 | return false; 144 | } 145 | if (status == Seat.SEAT.EMPTY) { 146 | // 返回可以坐下, 并且设置为坐下 147 | seat_col[col - 1] = Seat.SEAT.FULL; 148 | 149 | System.out.println("检查列表是否为引用类型相关的修改: " + seat_list); 150 | logger.info("{}", String.valueOf(seat_col)); 151 | seat_list[row - 1] = String.valueOf(seat_col); 152 | 153 | List seat = Arrays.asList(seat_list); 154 | 155 | seats.setSeats(seat.toString()); 156 | 157 | // TODO: 维护数据表可用座位和不可用座位的数量 158 | seats.setSeatsAvailable(seats.getSeatsAvailable() - 1); 159 | seats.setSeatsUnavailabe(seats.getSeatsUnavailabe() + 1); 160 | 161 | this.update(seats); 162 | 163 | return true; 164 | } 165 | } 166 | } 167 | return false; 168 | } 169 | 170 | /** 171 | * @param room_num 172 | * @param row 173 | * @param col 174 | * @Method leaveSeat 175 | * TODO: 进行正常的座位离开操作 176 | * @Return boolean 177 | * @Exception 178 | * @Date 2020/4/5 9:36 PM 179 | * @Author hezijian6338 180 | * @Version 1.0 181 | */ 182 | @Override 183 | public boolean leaveSeat(String room_num, int row, int col) { 184 | // 传递的座位位置信息有误 185 | if (row == 0 || col == 0) 186 | return false; 187 | 188 | Seat seats = this.findBy("roomNumber", room_num); 189 | String[] seat_list = seats.getSeats().replace(" ", "").replace("[", "").replace("]", "").split(","); 190 | 191 | // 判断获取座位的行数是否大于数组的大小 192 | if (row <= seat_list.length) { 193 | String seat_row = seat_list[row - 1]; 194 | char[] seat_col = seat_row.toCharArray(); 195 | 196 | // 判断获取座位的列数是否大于数组的大小 197 | if (col <= seat_col.length) { 198 | char status = seat_col[col - 1]; 199 | 200 | // 状态为 0, 证明本来就没人坐 201 | if (status == Seat.SEAT.EMPTY) { 202 | return false; 203 | } 204 | if (status == Seat.SEAT.FULL) { 205 | // 返回离开成功, 并修改状态为空 206 | seat_col[col - 1] = Seat.SEAT.EMPTY; 207 | 208 | System.out.println("检查列表是否为引用类型相关的修改: " + seat_list); 209 | seat_list[row - 1] = String.valueOf(seat_col); 210 | 211 | List seat = Arrays.asList(seat_list); 212 | 213 | seats.setSeats(seat.toString()); 214 | 215 | // TODO: 维护数据表可用座位和不可用座位的数量 216 | seats.setSeatsAvailable(seats.getSeatsAvailable() + 1); 217 | seats.setSeatsUnavailabe(seats.getSeatsUnavailabe() - 1); 218 | 219 | this.update(seats); 220 | 221 | return true; 222 | } 223 | } 224 | } 225 | return false; 226 | } 227 | 228 | @Override 229 | public boolean leaveSeat(String userId) { 230 | // TODO: 根据当前用户 id进行查找足迹 231 | Footprint footprint = footprintService.findUseSeatByUserId(userId); 232 | 233 | if (footprint == null) 234 | return false; 235 | 236 | // 解析座位行列信息 237 | String[] seats = footprint.getSeatsNumber().split(","); 238 | 239 | int row = Integer.parseInt(seats[0]); 240 | 241 | int col = Integer.parseInt(seats[1]); 242 | 243 | boolean seatResult = this.leaveSeat(footprint.getRoomNumber(), row, col); 244 | 245 | boolean fpResult = false; 246 | 247 | // TODO: 座位足迹离开 248 | if (seatResult) { 249 | fpResult = footprintService.leaveSeat(userId); 250 | } else { 251 | // FIXME: 缺失回滚 252 | return false; 253 | } 254 | 255 | if (fpResult && seatResult) 256 | return true; 257 | else 258 | return false; 259 | } 260 | 261 | /** 262 | * @param room_num 263 | * @param row 264 | * @param col 265 | * @Method createRoom 266 | * TODO: 创建自习室, 并返回 id 267 | * @Return java.lang.String 268 | * @Exception 269 | * @Date 2020/4/12 8:44 PM 270 | * @Author hezijian6338 271 | * @Version 1.0 272 | */ 273 | @Override 274 | public String createRoom(String room_num, int row, int col) { 275 | if (row == 0 && col == 0) 276 | return null; 277 | if (room_num == null) 278 | return null; 279 | 280 | // 构建空对象 281 | Seat seat = new Seat(); 282 | 283 | // 构建行数组 284 | ArrayList rowSeat = new ArrayList<>(); 285 | 286 | // 构建列数的数组 287 | // char[] colSeat = new char[col]; 288 | 289 | StringBuilder colSeatString = new StringBuilder(); 290 | 291 | // 填写列 292 | for (int i = 0; i < col; i++) { 293 | // colSeat[i] = Seat.SEAT.EMPTY; 294 | colSeatString.append(Seat.SEAT.EMPTY); 295 | } 296 | 297 | // 填写行 298 | for (int j = 0; j < row; j++) { 299 | rowSeat.add(j, colSeatString.toString()); 300 | } 301 | 302 | seat.setId(Tools.getUUID()); 303 | seat.setSeats(rowSeat.toString()); 304 | seat.setRoomNumber(room_num); 305 | seat.setName(room_num); 306 | seat.setStatus(Seat.STATUS.USE); 307 | 308 | seat.setSeatsCount(row * col); 309 | seat.setSeatsAvailable(row * col); 310 | seat.setSeatsUnavailabe(0); 311 | 312 | seat.setCreatedTime(Tools.getTimeStamp()); 313 | 314 | this.save(seat); 315 | 316 | return seat.getId(); 317 | } 318 | 319 | /** 320 | * @Method checkRoom 321 | * TODO: 根据自习室编号检查该自习室是否有正在使用的座位 322 | * @param roomNumber 323 | * @Return boolean 324 | * @Exception 325 | * @Date 2020-04-25 14:36 326 | * @Author hezijian6338 327 | * @Version 1.0 328 | */ 329 | @Override 330 | public boolean checkRoom(String roomNumber) { 331 | Seat seat = this.findBy("roomNumber", roomNumber); 332 | if (seat == null) 333 | return false; 334 | String[] seatList = seat.getSeats().replace(" ", "").replace("[", "").replace("]", "").split(","); 335 | 336 | // TODO: 获取行数 337 | for (String rows : seatList) { 338 | // 检查每行座位是否有包含在座的信息 (等于 -1就是找不到在座信息) 339 | if (rows.indexOf('1') != -1) { 340 | return false; 341 | } 342 | } 343 | 344 | return true; 345 | } 346 | } 347 | -------------------------------------------------------------------------------- /src/test/java/CodeGenerator.java: -------------------------------------------------------------------------------- 1 | import com.google.common.base.CaseFormat; 2 | import freemarker.template.TemplateExceptionHandler; 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.mybatis.generator.api.MyBatisGenerator; 5 | import org.mybatis.generator.config.*; 6 | import org.mybatis.generator.internal.DefaultShellCallback; 7 | 8 | import java.io.File; 9 | import java.io.FileWriter; 10 | import java.io.IOException; 11 | import java.text.SimpleDateFormat; 12 | import java.util.*; 13 | 14 | import static com.study.room.core.ProjectConstant.*; 15 | 16 | /** 17 | * 代码生成器,根据数据表名称生成对应的Model、Mapper、Service、Controller简化开发。 18 | */ 19 | public class CodeGenerator { 20 | //JDBC配置,请修改为你项目的实际配置 21 | private static final String JDBC_URL = "jdbc:mysql://hezijian6338.ddns.net:3306/study_room"; 22 | private static final String JDBC_USERNAME = "study_room"; 23 | private static final String JDBC_PASSWORD = "study_room"; 24 | private static final String JDBC_DIVER_CLASS_NAME = "com.mysql.jdbc.Driver"; 25 | 26 | private static final String PROJECT_PATH = System.getProperty("user.dir");//项目在硬盘上的基础路径 27 | private static final String TEMPLATE_FILE_PATH = PROJECT_PATH + "/src/test/resources/generator/template";//模板位置 28 | 29 | private static final String JAVA_PATH = "/src/main/java"; //java文件路径 30 | private static final String RESOURCES_PATH = "/src/main/resources";//资源文件路径 31 | 32 | private static final String PACKAGE_PATH_SERVICE = packageConvertPath(SERVICE_PACKAGE);//生成的Service存放路径 33 | private static final String PACKAGE_PATH_SERVICE_IMPL = packageConvertPath(SERVICE_IMPL_PACKAGE);//生成的Service实现存放路径 34 | private static final String PACKAGE_PATH_CONTROLLER = packageConvertPath(CONTROLLER_PACKAGE);//生成的Controller存放路径 35 | 36 | private static final String AUTHOR = "CodeGenerator";//@author 37 | private static final String DATE = new SimpleDateFormat("yyyy/MM/dd").format(new Date());//@date 38 | 39 | public static void main(String[] args) { 40 | genCodeByCustomModelName("user", "User"); 41 | genCodeByCustomModelName("seat", "Seat"); 42 | genCodeByCustomModelName("footprint", "Footprint"); 43 | //genCodeByCustomModelName("输入表名","输入自定义Model名称"); 44 | } 45 | 46 | /** 47 | * 通过数据表名称生成代码,Model 名称通过解析数据表名称获得,下划线转大驼峰的形式。 48 | * 如输入表名称 "t_user_detail" 将生成 TUserDetail、TUserDetailMapper、TUserDetailService ... 49 | * (推荐还是自定义把) 50 | * @param tableNames 数据表名称... 51 | */ 52 | public static void genCode(String... tableNames) { 53 | for (String tableName : tableNames) { 54 | genCodeByCustomModelName(tableName, null); 55 | } 56 | } 57 | 58 | /** 59 | * 通过数据表名称,和自定义的 Model 名称生成代码 60 | * 如输入表名称 "t_user_detail" 和自定义的 Model 名称 "User" 将生成 User、UserMapper、UserService ... 61 | * @param tableName 数据表名称 62 | * @param modelName 自定义的 Model 名称 63 | */ 64 | public static void genCodeByCustomModelName(String tableName, String modelName) { 65 | genModelAndMapper(tableName, modelName); 66 | genService(tableName, modelName); 67 | genController(tableName, modelName); 68 | } 69 | 70 | 71 | public static void genModelAndMapper(String tableName, String modelName) { 72 | Context context = new Context(ModelType.FLAT); 73 | context.setId("Potato"); 74 | context.setTargetRuntime("MyBatis3Simple"); 75 | context.addProperty(PropertyRegistry.CONTEXT_BEGINNING_DELIMITER, "`"); 76 | context.addProperty(PropertyRegistry.CONTEXT_ENDING_DELIMITER, "`"); 77 | 78 | JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration(); 79 | jdbcConnectionConfiguration.setConnectionURL(JDBC_URL); 80 | jdbcConnectionConfiguration.setUserId(JDBC_USERNAME); 81 | jdbcConnectionConfiguration.setPassword(JDBC_PASSWORD); 82 | jdbcConnectionConfiguration.setDriverClass(JDBC_DIVER_CLASS_NAME); 83 | context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration); 84 | 85 | PluginConfiguration pluginConfiguration = new PluginConfiguration(); 86 | pluginConfiguration.setConfigurationType("tk.mybatis.mapper.generator.MapperPlugin"); 87 | pluginConfiguration.addProperty("mappers", MAPPER_INTERFACE_REFERENCE); 88 | context.addPluginConfiguration(pluginConfiguration); 89 | 90 | JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration(); 91 | javaModelGeneratorConfiguration.setTargetProject(PROJECT_PATH + JAVA_PATH); 92 | javaModelGeneratorConfiguration.setTargetPackage(MODEL_PACKAGE); 93 | context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration); 94 | 95 | SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration(); 96 | sqlMapGeneratorConfiguration.setTargetProject(PROJECT_PATH + RESOURCES_PATH); 97 | sqlMapGeneratorConfiguration.setTargetPackage("mapper"); 98 | context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration); 99 | 100 | JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration(); 101 | javaClientGeneratorConfiguration.setTargetProject(PROJECT_PATH + JAVA_PATH); 102 | javaClientGeneratorConfiguration.setTargetPackage(MAPPER_PACKAGE); 103 | javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER"); 104 | context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration); 105 | 106 | TableConfiguration tableConfiguration = new TableConfiguration(context); 107 | tableConfiguration.setTableName(tableName); 108 | if (StringUtils.isNotEmpty(modelName))tableConfiguration.setDomainObjectName(modelName); 109 | tableConfiguration.setGeneratedKey(new GeneratedKey("id", "Mysql", true, null)); 110 | context.addTableConfiguration(tableConfiguration); 111 | 112 | List warnings; 113 | MyBatisGenerator generator; 114 | try { 115 | Configuration config = new Configuration(); 116 | config.addContext(context); 117 | config.validate(); 118 | 119 | boolean overwrite = true; 120 | DefaultShellCallback callback = new DefaultShellCallback(overwrite); 121 | warnings = new ArrayList(); 122 | generator = new MyBatisGenerator(config, callback, warnings); 123 | generator.generate(null); 124 | } catch (Exception e) { 125 | throw new RuntimeException("生成Model和Mapper失败", e); 126 | } 127 | 128 | if (generator.getGeneratedJavaFiles().isEmpty() || generator.getGeneratedXmlFiles().isEmpty()) { 129 | throw new RuntimeException("生成Model和Mapper失败:" + warnings); 130 | } 131 | if (StringUtils.isEmpty(modelName)) modelName = tableNameConvertUpperCamel(tableName); 132 | System.out.println(modelName + ".java 生成成功"); 133 | System.out.println(modelName + "Mapper.java 生成成功"); 134 | System.out.println(modelName + "Mapper.xml 生成成功"); 135 | } 136 | 137 | public static void genService(String tableName, String modelName) { 138 | try { 139 | freemarker.template.Configuration cfg = getConfiguration(); 140 | 141 | Map data = new HashMap<>(); 142 | data.put("date", DATE); 143 | data.put("author", AUTHOR); 144 | String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName; 145 | data.put("modelNameUpperCamel", modelNameUpperCamel); 146 | data.put("modelNameLowerCamel", tableNameConvertLowerCamel(tableName)); 147 | data.put("basePackage", BASE_PACKAGE); 148 | 149 | File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE + modelNameUpperCamel + "Service.java"); 150 | if (!file.getParentFile().exists()) { 151 | file.getParentFile().mkdirs(); 152 | } 153 | cfg.getTemplate("service.ftl").process(data, 154 | new FileWriter(file)); 155 | System.out.println(modelNameUpperCamel + "Service.java 生成成功"); 156 | 157 | File file1 = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_SERVICE_IMPL + modelNameUpperCamel + "ServiceImpl.java"); 158 | if (!file1.getParentFile().exists()) { 159 | file1.getParentFile().mkdirs(); 160 | } 161 | cfg.getTemplate("service-impl.ftl").process(data, 162 | new FileWriter(file1)); 163 | System.out.println(modelNameUpperCamel + "ServiceImpl.java 生成成功"); 164 | } catch (Exception e) { 165 | throw new RuntimeException("生成Service失败", e); 166 | } 167 | } 168 | 169 | public static void genController(String tableName, String modelName) { 170 | try { 171 | freemarker.template.Configuration cfg = getConfiguration(); 172 | 173 | Map data = new HashMap<>(); 174 | data.put("date", DATE); 175 | data.put("author", AUTHOR); 176 | String modelNameUpperCamel = StringUtils.isEmpty(modelName) ? tableNameConvertUpperCamel(tableName) : modelName; 177 | data.put("baseRequestMapping", modelNameConvertMappingPath(modelNameUpperCamel)); 178 | data.put("modelNameUpperCamel", modelNameUpperCamel); 179 | data.put("modelNameLowerCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, modelNameUpperCamel)); 180 | data.put("basePackage", BASE_PACKAGE); 181 | 182 | File file = new File(PROJECT_PATH + JAVA_PATH + PACKAGE_PATH_CONTROLLER + modelNameUpperCamel + "Controller.java"); 183 | if (!file.getParentFile().exists()) { 184 | file.getParentFile().mkdirs(); 185 | } 186 | 187 | /** 188 | * 这里选择是传统的 JSP/RESTFUL 前端构建~ 189 | */ 190 | cfg.getTemplate("controller-restful.ftl").process(data, new FileWriter(file)); 191 | //cfg.getTemplate("controller.ftl").process(data, new FileWriter(file)); 192 | 193 | System.out.println(modelNameUpperCamel + "Controller.java 生成成功"); 194 | } catch (Exception e) { 195 | throw new RuntimeException("生成Controller失败", e); 196 | } 197 | 198 | } 199 | 200 | private static freemarker.template.Configuration getConfiguration() throws IOException { 201 | freemarker.template.Configuration cfg = new freemarker.template.Configuration(freemarker.template.Configuration.VERSION_2_3_23); 202 | cfg.setDirectoryForTemplateLoading(new File(TEMPLATE_FILE_PATH)); 203 | cfg.setDefaultEncoding("UTF-8"); 204 | cfg.setTemplateExceptionHandler(TemplateExceptionHandler.IGNORE_HANDLER); 205 | return cfg; 206 | } 207 | 208 | private static String tableNameConvertLowerCamel(String tableName) { 209 | return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, tableName.toLowerCase()); 210 | } 211 | 212 | private static String tableNameConvertUpperCamel(String tableName) { 213 | return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, tableName.toLowerCase()); 214 | 215 | } 216 | 217 | private static String tableNameConvertMappingPath(String tableName) { 218 | tableName = tableName.toLowerCase();//兼容使用大写的表名 219 | return "/" + (tableName.contains("_") ? tableName.replaceAll("_", "/") : tableName); 220 | } 221 | 222 | private static String modelNameConvertMappingPath(String modelName) { 223 | String tableName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, modelName); 224 | return tableNameConvertMappingPath(tableName); 225 | } 226 | 227 | private static String packageConvertPath(String packageName) { 228 | return String.format("/%s/", packageName.contains(".") ? packageName.replaceAll("\\.", "/") : packageName); 229 | } 230 | 231 | } 232 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/configurer/WebMvcConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.study.room.configurer; 2 | 3 | import java.io.IOException; 4 | import java.lang.reflect.Method; 5 | import java.nio.charset.Charset; 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | import com.alibaba.fastjson.JSON; 16 | import com.alibaba.fastjson.serializer.SerializerFeature; 17 | import com.alibaba.fastjson.support.config.FastJsonConfig; 18 | import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; 19 | 20 | import com.auth0.jwt.JWT; 21 | import com.auth0.jwt.JWTVerifier; 22 | import com.auth0.jwt.algorithms.Algorithm; 23 | import com.auth0.jwt.exceptions.JWTDecodeException; 24 | import com.auth0.jwt.exceptions.JWTVerificationException; 25 | import com.study.room.core.Result; 26 | import com.study.room.core.ResultCode; 27 | import com.study.room.core.ServiceException; 28 | import com.study.room.model.User; 29 | import com.study.room.service.UserService; 30 | import org.apache.commons.codec.digest.DigestUtils; 31 | import org.apache.commons.lang3.StringUtils; 32 | import org.slf4j.Logger; 33 | import org.slf4j.LoggerFactory; 34 | import org.springframework.beans.factory.annotation.Autowired; 35 | import org.springframework.beans.factory.annotation.Value; 36 | import org.springframework.context.annotation.Configuration; 37 | import org.springframework.http.MediaType; 38 | import org.springframework.http.converter.HttpMessageConverter; 39 | import org.springframework.web.method.HandlerMethod; 40 | import org.springframework.web.servlet.HandlerExceptionResolver; 41 | import org.springframework.web.servlet.ModelAndView; 42 | import org.springframework.web.servlet.NoHandlerFoundException; 43 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 44 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 45 | import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; 46 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 47 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 48 | 49 | /** 50 | * Spring MVC 配置 51 | */ 52 | @Configuration 53 | public class WebMvcConfigurer extends WebMvcConfigurerAdapter { 54 | 55 | private final Logger logger = LoggerFactory.getLogger(WebMvcConfigurer.class); 56 | 57 | @Autowired 58 | private UserService userService; 59 | 60 | 61 | // 定义一个线程域,存放登录用户 62 | private static final ThreadLocal thread = new ThreadLocal<>(); 63 | 64 | @Value("${spring.profiles.active}") 65 | private String env;//当前激活的配置文件 66 | 67 | //使用阿里 FastJson 作为JSON MessageConverter 68 | @Override 69 | public void configureMessageConverters(List> converters) { 70 | FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); 71 | FastJsonConfig config = new FastJsonConfig(); 72 | config.setSerializerFeatures(SerializerFeature.WriteMapNullValue);//保留空的字段 73 | //SerializerFeature.WriteNullStringAsEmpty,//String null -> "" 74 | //SerializerFeature.WriteNullNumberAsZero//Number null -> 0 75 | // 按需配置,更多参考FastJson文档哈 76 | 77 | converter.setFastJsonConfig(config); 78 | converter.setDefaultCharset(Charset.forName("UTF-8")); 79 | converter.setSupportedMediaTypes(Arrays.asList(MediaType.APPLICATION_JSON_UTF8)); 80 | converters.add(converter); 81 | } 82 | 83 | 84 | //统一异常处理 85 | @Override 86 | public void configureHandlerExceptionResolvers(List exceptionResolvers) { 87 | exceptionResolvers.add(new HandlerExceptionResolver() { 88 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) { 89 | Result result = new Result(); 90 | if (e instanceof ServiceException) {//业务失败的异常,如“账号或密码错误” 91 | result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); 92 | logger.info(e.getMessage()); 93 | } else if (e instanceof NoHandlerFoundException) { 94 | result.setCode(ResultCode.NOT_FOUND).setMessage("接口 [" + request.getRequestURI() + "] 不存在"); 95 | } else if (e instanceof ServletException) { 96 | result.setCode(ResultCode.FAIL).setMessage(e.getMessage()); 97 | } else { 98 | result.setCode(ResultCode.INTERNAL_SERVER_ERROR).setMessage("接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员"); 99 | String message; 100 | if (handler instanceof HandlerMethod) { 101 | HandlerMethod handlerMethod = (HandlerMethod) handler; 102 | message = String.format("接口 [%s] 出现异常,方法:%s.%s,异常摘要:%s", 103 | request.getRequestURI(), 104 | handlerMethod.getBean().getClass().getName(), 105 | handlerMethod.getMethod().getName(), 106 | e.getMessage()); 107 | } else { 108 | message = e.getMessage(); 109 | } 110 | logger.error(message, e); 111 | } 112 | responseResult(response, result); 113 | return new ModelAndView(); 114 | } 115 | 116 | }); 117 | } 118 | 119 | //解决跨域问题 120 | @Override 121 | public void addCorsMappings(CorsRegistry registry) { 122 | registry.addMapping("/**")//设置允许跨域的路径 123 | .allowedOrigins("*")//设置允许跨域请求的域名 124 | .allowCredentials(true)//是否允许证书 不再默认开启 125 | .allowedMethods("GET", "POST", "PUT", "DELETE")//设置允许的方法 126 | .maxAge(3600);//跨域允许时间 127 | } 128 | 129 | @Override 130 | public void addResourceHandlers(ResourceHandlerRegistry registry) { 131 | registry.addResourceHandler("/**").addResourceLocations("classpath:/static/"); 132 | registry.addResourceHandler("swagger-ui.html") 133 | .addResourceLocations("classpath:/META-INF/resources/"); 134 | registry.addResourceHandler("/webjars/**") 135 | .addResourceLocations("classpath:/META-INF/resources/webjars/"); 136 | super.addResourceHandlers(registry); 137 | 138 | } 139 | 140 | 141 | //添加拦截器 142 | @Override 143 | public void addInterceptors(InterceptorRegistry registry) { 144 | //接口签名认证拦截器,该签名认证比较简单,实际项目中可以使用Json Web Token或其他更好的方式替代。 145 | if ("dev".equals(env)) { //开发环境忽略签名认证 146 | registry.addInterceptor(new HandlerInterceptorAdapter() { 147 | @Override 148 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 149 | //验证签名 150 | // boolean pass = validateSign(request); 151 | // if (pass) { 152 | // return true; 153 | // } else { 154 | // logger.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}", 155 | // request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap())); 156 | // 157 | // Result result = new Result(); 158 | // result.setCode(ResultCode.UNAUTHORIZED).setMessage("签名认证失败"); 159 | // responseResult(response, result); 160 | // return false; 161 | // } 162 | Result result = new Result(); 163 | // logger.warn("签名认证失败,请求接口:{},请求IP:{},请求参数:{}", 164 | // request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap())); 165 | String token = request.getHeader("token");// 从 http 请求头中取出 token 166 | // 如果不是映射到方法直接通过 167 | if (!(handler instanceof HandlerMethod)) { 168 | return true; 169 | } 170 | HandlerMethod handlerMethod = (HandlerMethod) handler; 171 | Method method = handlerMethod.getMethod(); 172 | //检查是否有passtoken注释,有则跳过认证 173 | if (method.isAnnotationPresent(PassToken.class)) { 174 | PassToken passToken = method.getAnnotation(PassToken.class); 175 | if (passToken.required()) { 176 | return true; 177 | } 178 | } 179 | //检查有没有需要用户权限的注解 180 | if (method.isAnnotationPresent(UserLoginToken.class)) { 181 | logger.info("进入检查 token登陆拦截器, 请求接口:{},请求IP:{},请求参数:{}", 182 | request.getRequestURI(), getIpAddress(request), JSON.toJSONString(request.getParameterMap())); 183 | UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class); 184 | if (userLoginToken.required()) { 185 | // 执行认证 186 | if (token == null) { 187 | result.setCode(ResultCode.UNAUTHORIZED).setMessage("无token,请重新登录"); 188 | responseResult(response, result); 189 | return false; 190 | // throw new RuntimeException("无token,请重新登录"); 191 | } 192 | // 获取 token 中的 user id 193 | String userId; 194 | try { 195 | userId = JWT.decode(token).getAudience().get(0); 196 | } catch (JWTDecodeException j) { 197 | result.setCode(ResultCode.UNAUTHORIZED).setMessage("401"); 198 | responseResult(response, result); 199 | return false; 200 | // throw new RuntimeException("401"); 201 | } 202 | User user = userService.findById(userId); 203 | if (user == null) { 204 | result.setCode(ResultCode.NOT_FOUND).setMessage("用户不存在,请重新登录"); 205 | responseResult(response, result); 206 | return false; 207 | // throw new RuntimeException("用户不存在,请重新登录"); 208 | } 209 | // 验证 token 210 | JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build(); 211 | try { 212 | jwtVerifier.verify(token); 213 | 214 | // 存放到线程中 215 | thread.set(user); 216 | } catch (JWTVerificationException e) { 217 | result.setCode(ResultCode.UNAUTHORIZED).setMessage("401"); 218 | responseResult(response, result); 219 | return false; 220 | // throw new RuntimeException("401"); 221 | } 222 | 223 | logger.info("登陆用户为: {}", user.getStudentNum()); 224 | return true; 225 | } 226 | } 227 | return true; 228 | } 229 | 230 | @Override 231 | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 232 | //程序运行结束之后,删除线程 233 | thread.remove(); 234 | } 235 | }); 236 | } 237 | } 238 | 239 | 240 | public static User getLoginUser() { 241 | return thread.get(); 242 | } 243 | 244 | 245 | private void responseResult(HttpServletResponse response, Result result) { 246 | response.setCharacterEncoding("UTF-8"); 247 | response.setHeader("Content-type", "application/json;charset=UTF-8"); 248 | response.setStatus(200); 249 | try { 250 | response.getWriter().write(JSON.toJSONString(result)); 251 | } catch (IOException ex) { 252 | logger.error(ex.getMessage()); 253 | } 254 | } 255 | 256 | /** 257 | * 一个简单的签名认证,规则: 258 | * 1. 将请求参数按ascii码排序 259 | * 2. 拼接为a=value&b=value...这样的字符串(不包含sign) 260 | * 3. 混合密钥(secret)进行md5获得签名,与请求的签名进行比较 261 | */ 262 | private boolean validateSign(HttpServletRequest request) { 263 | String requestSign = request.getParameter("sign");//获得请求签名,如sign=19e907700db7ad91318424a97c54ed57 264 | if (StringUtils.isEmpty(requestSign)) { 265 | return false; 266 | } 267 | List keys = new ArrayList(request.getParameterMap().keySet()); 268 | keys.remove("sign");//排除sign参数 269 | Collections.sort(keys);//排序 270 | 271 | StringBuilder sb = new StringBuilder(); 272 | for (String key : keys) { 273 | sb.append(key).append("=").append(request.getParameter(key)).append("&");//拼接字符串 274 | } 275 | String linkString = sb.toString(); 276 | linkString = StringUtils.substring(linkString, 0, linkString.length() - 1);//去除最后一个'&' 277 | 278 | String secret = "Potato";//密钥,自己修改 279 | String sign = DigestUtils.md5Hex(linkString + secret);//混合密钥md5 280 | 281 | return StringUtils.equals(sign, requestSign);//比较 282 | } 283 | 284 | private String getIpAddress(HttpServletRequest request) { 285 | String ip = request.getHeader("x-forwarded-for"); 286 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 287 | ip = request.getHeader("Proxy-Client-IP"); 288 | } 289 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 290 | ip = request.getHeader("WL-Proxy-Client-IP"); 291 | } 292 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 293 | ip = request.getHeader("HTTP_CLIENT_IP"); 294 | } 295 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 296 | ip = request.getHeader("HTTP_X_FORWARDED_FOR"); 297 | } 298 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 299 | ip = request.getRemoteAddr(); 300 | } 301 | // 如果是多级代理,那么取第一个ip为客户端ip 302 | if (ip != null && ip.indexOf(",") != -1) { 303 | ip = ip.substring(0, ip.indexOf(",")).trim(); 304 | } 305 | 306 | return ip; 307 | } 308 | } 309 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/web/SeatController.java: -------------------------------------------------------------------------------- 1 | package com.study.room.web; 2 | 3 | import com.study.room.configurer.UserLoginToken; 4 | import com.study.room.configurer.WebMvcConfigurer; 5 | import com.study.room.core.Result; 6 | import com.study.room.core.ResultGenerator; 7 | import com.study.room.dto.FootprintDTO; 8 | import com.study.room.dto.RoomsReportDTO; 9 | import com.study.room.model.Footprint; 10 | import com.study.room.model.Seat; 11 | import com.study.room.model.User; 12 | import com.study.room.service.FootprintService; 13 | import com.study.room.service.SeatService; 14 | import com.github.pagehelper.PageHelper; 15 | import com.github.pagehelper.PageInfo; 16 | import com.study.room.service.UserService; 17 | import com.study.room.service.impl.SeatServiceImpl; 18 | import com.study.room.utils.Tools; 19 | import io.swagger.annotations.Api; 20 | import io.swagger.annotations.ApiImplicitParam; 21 | import io.swagger.annotations.ApiImplicitParams; 22 | import io.swagger.annotations.ApiOperation; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.web.bind.annotation.*; 26 | import springfox.documentation.annotations.ApiIgnore; 27 | 28 | import javax.annotation.Resource; 29 | import java.sql.Timestamp; 30 | import java.util.HashMap; 31 | import java.util.List; 32 | 33 | /** 34 | * Created by CodeGenerator on 2020/03/21. 35 | */ 36 | @Api(value = "seat", tags = "座位管理接口") 37 | @RestController 38 | @RequestMapping("/seat") 39 | public class SeatController { 40 | private final Logger logger = LoggerFactory.getLogger(SeatController.class); 41 | 42 | @Resource 43 | private SeatService seatService; 44 | 45 | @Resource 46 | private FootprintService footprintService; 47 | 48 | @Resource 49 | private UserService userService; 50 | 51 | // 记录被抢座的信息 (userId, 当前的时间戳) 52 | private static HashMap grabSeatMap = new HashMap<>(); 53 | 54 | @ApiOperation(value = "checkSeat", notes = "检查座位信息 (是否可坐下)") 55 | @ApiImplicitParams({ 56 | @ApiImplicitParam(value = "自习室编号", name = "room_num", dataType = "String", paramType = "path"), 57 | @ApiImplicitParam(value = "座位行", name = "row", dataType = "int", paramType = "path"), 58 | @ApiImplicitParam(value = "座位列", name = "col", dataType = "int", paramType = "path") 59 | }) 60 | @UserLoginToken 61 | @PostMapping("/check/room/{room_num}/row/{row}/col/{col}") 62 | public Result checkSeat(@PathVariable String room_num, @PathVariable int row, @PathVariable int col) { 63 | User user = WebMvcConfigurer.getLoginUser(); 64 | 65 | // TODO: 检查用户的黑名单次数是否超过控制次数 66 | if (user.getBadRecord() > User.BAD.BADCOUNT) { 67 | 68 | // 如果该用户状态超过黑名单录入次数, 但是状态不是黑名单状态, 手动更新状态 69 | if (user.getStatus() != User.STATUS.BAD) { 70 | user.setStatus(User.STATUS.BAD); 71 | userService.update(user); 72 | } 73 | return ResultGenerator.genFailResult("已列入黑名单, 无法进行座位查阅与借座~"); 74 | } 75 | 76 | int status = seatService.checkSeat(room_num, row, col); 77 | if (status == SeatServiceImpl.SEAT.AVAILABLE) 78 | return ResultGenerator.genSuccessResult("座位可以坐下"); 79 | if (status == SeatServiceImpl.SEAT.FULL) 80 | return ResultGenerator.genFailResult("座位已有人做"); 81 | if (status == SeatServiceImpl.SEAT.FULL_TEMP) 82 | return ResultGenerator.genFailResult("正在使用座位保护"); 83 | if (status == SeatServiceImpl.SEAT.ERROR) 84 | return ResultGenerator.genFailResult("座位信息有误"); 85 | return ResultGenerator.genFailResult("座位信息有误"); 86 | } 87 | 88 | @ApiOperation(value = "seatAnyway", notes = "抢座位 (座位已经被坐下, 20分钟的抢座时间)") 89 | @ApiImplicitParams({ 90 | @ApiImplicitParam(value = "自习室编号", name = "room_num", dataType = "String", paramType = "path"), 91 | @ApiImplicitParam(value = "座位行", name = "row", dataType = "int", paramType = "path"), 92 | @ApiImplicitParam(value = "座位列", name = "col", dataType = "int", paramType = "path") 93 | }) 94 | @UserLoginToken 95 | @PostMapping("/anyway/{room_num}/row/{row}/col/{col}") 96 | public Result seatAnyway(@PathVariable String room_num, @PathVariable int row, @PathVariable int col) { 97 | User user = WebMvcConfigurer.getLoginUser(); 98 | 99 | String seats_number = row + "," + col; 100 | Footprint footprint = footprintService.checkSeatStatus(room_num, seats_number); 101 | 102 | if (user.getId().equals(footprint.getUserId())) 103 | return ResultGenerator.genFailResult("自己抢自己?"); 104 | 105 | logger.info("正在进行抢座, 自习室编号: {}, 行: {}, 列: {}", room_num, row, col); 106 | 107 | // TODO: 检查是否已经在抢座了 108 | if (grabSeatMap.containsKey(footprint.getId())) { 109 | // 当前时间减去记录的时间, 看看大不大与 20min 110 | long time = Tools.getLongTimeStamp() - grabSeatMap.get(footprint.getId()).getTime(); 111 | 112 | logger.info("现在已经抢座了 {}ms ~", time); 113 | 114 | if (time <= 0) { 115 | return ResultGenerator.genFailResult("系统错误~"); 116 | } 117 | 118 | // 检查时间是否已经超过 20分钟了 119 | if (time >= Footprint.TIME.GRAB_TEST) { 120 | // TODO: 这里需要手动把足迹状态更新为离开, 并且记录黑名单次数 121 | footprint.setStatus(Footprint.STATUS.OUT); 122 | 123 | // 找到被抢座的用户 124 | User badUser = userService.findById(footprint.getUserId()); 125 | 126 | // 黑名单次数加一 127 | badUser.setBadRecord(badUser.getBadRecord() + 1); 128 | 129 | // 黑名单次数大于3, 黑名单状态开启 130 | if (badUser.getBadRecord() >= 3) { 131 | badUser.setStatus(User.STATUS.BAD); 132 | } 133 | // 跟新被抢座的人的数据 134 | userService.update(badUser); 135 | 136 | // 设置座位离开, 空出来 (不与 footprint冲突) 137 | seatService.leaveSeat(room_num, row, col); 138 | 139 | // 更新被抢座座位的足迹信息 140 | footprintService.update(footprint); 141 | 142 | return ResultGenerator.genSuccessResult("你可以进行坐下了~"); 143 | } else { 144 | return ResultGenerator.genSuccessResult("已经抢座了 " + time + "ms"); 145 | } 146 | } 147 | 148 | if (footprint.getStatus() == Footprint.STATUS.TEMP) { 149 | return ResultGenerator.genFailResult("用户已经使用暂离, 不允许抢座~"); 150 | } 151 | 152 | if (footprint.getStatus() == Footprint.STATUS.IN) { 153 | // 当前被抢座的用户 id, 和当前的时间戳 154 | grabSeatMap.put(footprint.getId(), Tools.getTimeStamp()); 155 | return ResultGenerator.genSuccessResult("开始抢座~"); 156 | } 157 | 158 | return ResultGenerator.genFailResult("系统错误~"); 159 | } 160 | 161 | @ApiOperation(value = "haveSeat", notes = "正常坐下 (座位为空, 不为空会返回错误信息)") 162 | // @ApiImplicitParam(value = "足迹对象", name = "footprintDTO", dataType = "com.study.room.dto.FootprintDTO", paramType = "body") 163 | @UserLoginToken 164 | @PostMapping("/down") 165 | public Result haveSeat(@RequestBody FootprintDTO footprintDTO) { 166 | User user = WebMvcConfigurer.getLoginUser(); 167 | 168 | // TODO: 检查用户的黑名单次数是否超过控制次数 169 | if (user.getBadRecord() > User.BAD.BADCOUNT) { 170 | 171 | // 如果该用户状态超过黑名单录入次数, 但是状态不是黑名单状态, 手动更新状态 172 | if (user.getStatus() != User.STATUS.BAD) { 173 | user.setStatus(User.STATUS.BAD); 174 | userService.update(user); 175 | } 176 | return ResultGenerator.genFailResult("已列入黑名单, 无法进行座位查阅与借座~"); 177 | } 178 | 179 | 180 | String room_num = null; 181 | int row = 0; 182 | int col = 0; 183 | 184 | // 检查自习室编号是否为空 185 | if (footprintDTO.getRoomNumber() != null) { 186 | room_num = footprintDTO.getRoomNumber(); 187 | } else { 188 | return ResultGenerator.genFailResult("自习室编号为空~"); 189 | } 190 | 191 | // 检查自习室座位编号 192 | if (footprintDTO.getSeatsNumber() != null) { 193 | String seats_number = footprintDTO.getSeatsNumber(); 194 | String[] seats = seats_number.split(","); 195 | 196 | // 行, 列 197 | row = Integer.parseInt(seats[0]); 198 | col = Integer.parseInt(seats[1]); 199 | } else { 200 | return ResultGenerator.genFailResult("自习室座位编号为空~"); 201 | } 202 | 203 | // TODO: 修改有可能回滚的情况 204 | int status = seatService.checkSeat(room_num, row, col); 205 | 206 | // 座位能够坐下, 业务逻辑上不存在错误回滚, 除非是代码执行上 207 | if (status == SeatServiceImpl.SEAT.AVAILABLE) { 208 | // 检查该座位是否能够坐下 209 | Boolean isAvailable = seatService.haveSeat(room_num, row, col); 210 | Boolean isSeat = false; 211 | 212 | // 如果可以, 则留下足迹 213 | if (isAvailable) { 214 | if (footprintDTO.getUserId() == null) 215 | footprintDTO.setUserId(WebMvcConfigurer.getLoginUser().getId()); 216 | isSeat = footprintService.haveSeat(footprintDTO); 217 | } else { 218 | // 不可以坐下, 返回信息 219 | // FIXME: 这里应该缺失一个回滚... 220 | return ResultGenerator.genFailResult("该座位无法坐下, 请稍后再试~"); 221 | } 222 | if (isAvailable && isSeat) { 223 | return ResultGenerator.genSuccessResult(); 224 | } else { 225 | return ResultGenerator.genFailResult("系统错误, 无法留下足迹~"); 226 | } 227 | } else { 228 | return ResultGenerator.genFailResult("系统错误"); 229 | } 230 | } 231 | 232 | @ApiOperation(value = "tempLeaveSeat", notes = "暂时离开座位 (默认拥有一个暂离时间)") 233 | @UserLoginToken 234 | @PostMapping("/temp/leave") 235 | public Result tempLeaveSeat() { 236 | // 因为需要登录 token, 所以不存在找不到用户的情况 237 | User user = WebMvcConfigurer.getLoginUser(); 238 | 239 | // TODO: 根据用户 id 240 | Boolean result = footprintService.pauseSeat(user.getId()); 241 | 242 | if (result) { 243 | return ResultGenerator.genSuccessResult(); 244 | } else { 245 | return ResultGenerator.genFailResult("暂停座位失败~"); 246 | } 247 | } 248 | 249 | @ApiOperation(value = "leaveSeat", notes = "离开座位 (释放座位为空)") 250 | @UserLoginToken 251 | @PostMapping("/leave") 252 | public Result leaveSeat() { 253 | // 因为需要登录 token, 所以不存在找不到用户的情况 254 | User user = WebMvcConfigurer.getLoginUser(); 255 | 256 | // TODO: 离开座位 257 | Boolean result = seatService.leaveSeat(user.getId()); 258 | 259 | if (result) { 260 | return ResultGenerator.genSuccessResult(); 261 | } else { 262 | return ResultGenerator.genFailResult("离开座位失败~"); 263 | } 264 | 265 | } 266 | 267 | @ApiOperation(value = "createRoom", notes = "创建自习室") 268 | @ApiImplicitParams({ 269 | @ApiImplicitParam(value = "自习室编号", name = "room_num", dataType = "String", paramType = "path"), 270 | @ApiImplicitParam(value = "座位行", name = "row", dataType = "int", paramType = "path"), 271 | @ApiImplicitParam(value = "座位列", name = "col", dataType = "int", paramType = "path") 272 | }) 273 | @UserLoginToken 274 | @PostMapping("/room/{room_num}/row/{row}/col/{col}") 275 | public Result createRoom(@PathVariable String room_num, @PathVariable int row, @PathVariable int col) { 276 | String roomId = seatService.createRoom(room_num, row, col); 277 | if (roomId == null) 278 | return ResultGenerator.genFailResult("创建失败~"); 279 | else 280 | return ResultGenerator.genSuccessResult(roomId); 281 | } 282 | 283 | @UserLoginToken 284 | @PostMapping("/report") 285 | public Result checkRoomRep() { 286 | List list = seatService.findAll(); 287 | RoomsReportDTO rep = new RoomsReportDTO(); 288 | rep.setRoomsCount(list.size()); 289 | 290 | int availableSeat = 0; 291 | int unAvailableSeat = 0; 292 | int seatsCount = 0; 293 | 294 | 295 | for (Seat seat : list) { 296 | availableSeat = seat.getSeatsAvailable() + availableSeat; 297 | unAvailableSeat = seat.getSeatsUnavailabe() + unAvailableSeat; 298 | seatsCount = seat.getSeatsCount() + seatsCount; 299 | } 300 | 301 | rep.setAvailableSeats(availableSeat); 302 | rep.setSeatsCount(seatsCount); 303 | rep.setUnAvailableSeats(unAvailableSeat); 304 | 305 | return ResultGenerator.genSuccessResult(rep); 306 | } 307 | 308 | @ApiOperation(value = "deleteRoom", notes = "根据自习室编号进行删除自习室") 309 | @ApiImplicitParam(value = "自习室编号", name = "roomNumber", dataType = "String", paramType = "path") 310 | @UserLoginToken 311 | @DeleteMapping("/roomNum/{roomNumber}") 312 | public Result deleteRoom(@PathVariable String roomNumber) { 313 | Seat seat = seatService.findBy("roomNumber", roomNumber); 314 | if (seat == null) { 315 | return ResultGenerator.genFailResult("自习室不存在"); 316 | } 317 | 318 | // TODO: 检查自习室是否存在正在自习的人员或者信息 319 | if (seatService.checkRoom(roomNumber)) { 320 | seatService.deleteById(seat.getId()); 321 | return ResultGenerator.genSuccessResult(); 322 | } else { 323 | return ResultGenerator.genFailResult("自习室有人正在使用, 无法删除~"); 324 | } 325 | 326 | } 327 | 328 | @ApiIgnore 329 | @UserLoginToken 330 | @PostMapping 331 | public Result add(@RequestBody Seat seat) { 332 | seatService.save(seat); 333 | return ResultGenerator.genSuccessResult(); 334 | } 335 | 336 | @ApiIgnore 337 | @UserLoginToken 338 | @DeleteMapping("/{id}") 339 | public Result delete(@PathVariable String id) { 340 | seatService.deleteById(id); 341 | return ResultGenerator.genSuccessResult(); 342 | } 343 | 344 | @ApiIgnore 345 | @UserLoginToken 346 | @PutMapping 347 | public Result update(@RequestBody Seat seat) { 348 | seatService.update(seat); 349 | return ResultGenerator.genSuccessResult(); 350 | } 351 | 352 | // @ApiIgnore 353 | @ApiOperation(value = "getSeatByRoomNumber", notes = "根据自习室编号查找自习室信息") 354 | @ApiImplicitParam(value = "自习室编号", name = "roomNumber", dataType = "String", paramType = "path") 355 | @UserLoginToken 356 | @GetMapping("/roomNumber/{roomNumber}") 357 | public Result getSeatByRoomNumber(@PathVariable String roomNumber) { 358 | Seat seat = seatService.findBy("roomNumber", roomNumber); 359 | return ResultGenerator.genSuccessResult(seat); 360 | } 361 | 362 | @ApiOperation(value = "detail", notes = "根据 id查找自习室信息") 363 | @ApiImplicitParam(value = "id", name = "id", dataType = "String", paramType = "path") 364 | @UserLoginToken 365 | @GetMapping("/{id}") 366 | public Result detail(@PathVariable String id) { 367 | Seat seat = seatService.findById(id); 368 | return ResultGenerator.genSuccessResult(seat); 369 | } 370 | 371 | @ApiIgnore 372 | @UserLoginToken 373 | @GetMapping 374 | public Result list(@RequestParam(defaultValue = "0") Integer page, @RequestParam(defaultValue = "0") Integer size) { 375 | PageHelper.startPage(page, size); 376 | List list = seatService.findAll(); 377 | PageInfo pageInfo = new PageInfo(list); 378 | return ResultGenerator.genSuccessResult(pageInfo); 379 | } 380 | } 381 | -------------------------------------------------------------------------------- /src/main/java/com/study/room/service/impl/FootprintServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.study.room.service.impl; 2 | 3 | import com.study.room.dao.FootprintMapper; 4 | import com.study.room.dao.SeatMapper; 5 | import com.study.room.dto.FootprintDTO; 6 | import com.study.room.model.Footprint; 7 | import com.study.room.service.FootprintService; 8 | import com.study.room.core.AbstractService; 9 | import com.study.room.service.SeatService; 10 | import com.study.room.utils.Tools; 11 | import org.springframework.beans.BeanUtils; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | import tk.mybatis.mapper.entity.Condition; 15 | import tk.mybatis.mapper.entity.Example; 16 | 17 | import javax.annotation.Resource; 18 | import java.sql.Timestamp; 19 | import java.util.List; 20 | 21 | 22 | /** 23 | * Created by CodeGenerator on 2020/03/21. 24 | */ 25 | @Service 26 | @Transactional 27 | public class FootprintServiceImpl extends AbstractService implements FootprintService { 28 | @Resource 29 | private FootprintMapper footprintMapper; 30 | 31 | @Resource 32 | private SeatService seatService; 33 | 34 | /** 35 | * @param footprintDTO 36 | * @Method haveSeat 37 | * TODO: 找到座位坐下 38 | * @Return boolean 39 | * @Exception 40 | * @Date 2020/4/5 8:03 PM 41 | * @Author hezijian6338 42 | * @Version 1.0 43 | */ 44 | @Override 45 | public boolean haveSeat(FootprintDTO footprintDTO) { 46 | // TODO: 检查该用户之前是否有借座, 但是忘记离开座位的记录 (手动触发, 结束状态, 并且自动计算选择的自习时长) 47 | int time = 0; 48 | if (footprintDTO.getUserId() != null) 49 | // 直接调用检查时间的方法 (有类似的逻辑) 50 | time = this.checkTime(footprintDTO.getUserId()); 51 | else 52 | return false; 53 | 54 | // 还有剩余时间 (上一次借座还在继续) 55 | if (time > 0) 56 | return false; 57 | 58 | // TODO: 完成基础逻辑 59 | Footprint footprint = new Footprint(); 60 | 61 | // 直接映射过去, 填充完整 62 | BeanUtils.copyProperties(footprintDTO, footprint); 63 | 64 | // 构建新记录, 所以需要 id 65 | if (footprint.getId() == null) 66 | footprint.setId(Tools.getUUID()); 67 | 68 | // 初始化学习时间 69 | footprint.setStayTime(0); 70 | 71 | // 如果没有填写学习时间, 默认一个小时 (其实是必填的) 72 | if (footprint.getWantedTime() == 0) 73 | footprint.setWantedTime(60 * 60 * 1000); 74 | 75 | // 设置状态为 坐下 76 | footprint.setStatus(Footprint.STATUS.IN); 77 | 78 | // 时间填充需要补充 (√) 79 | footprint.setCreatedTime(Tools.getTimeStamp()); 80 | // footprint.setUpdatedTime(Tools.getTimeStamp()); 81 | 82 | this.save(footprint); 83 | 84 | return true; 85 | } 86 | 87 | /** 88 | * @param userId 89 | * @Method leaveSeat 90 | * TODO: 离开正在使用的座位 91 | * @Return boolean 92 | * @Exception 93 | * @Date 2020/4/5 8:04 PM 94 | * @Author hezijian6338 95 | * @Version 1.0 96 | */ 97 | @Override 98 | public boolean leaveSeat(String userId) { 99 | // 需要添加一个方法, 根据状态和当前自习室编号座位号进行查询现有的座位足迹信息 (√) 100 | 101 | // TODO: 根据新增加的方法, 返回找到的座位足迹信息 102 | Footprint footprint = this.findUseSeatByUserId(userId); 103 | 104 | Timestamp current_time = Tools.getTimeStamp(); 105 | 106 | // 判断状态是否从正常坐下状态 107 | if (footprint.getStatus() == Footprint.STATUS.IN) { 108 | 109 | // 状态修改为离开 110 | footprint.setStatus(Footprint.STATUS.OUT); 111 | 112 | // TODO: 填充一共总自习时间 113 | 114 | // 存在过暂离的情况, 自习时间本不为空 115 | int staty_time = footprint.getStayTime(); 116 | // 如果暂离不为空, 即是曾经暂离过 117 | if (staty_time != 0) { 118 | // 计算当次自习时间 119 | 120 | // TODO: 以下的代码参考 checkTime方法, 取消一次记录可以多次续时 121 | // staty_time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 122 | // // 小于自定义时间 123 | // < footprint.getWantedTime() 124 | // // 当前时间 - 更新时间 + 已经自习时间 125 | // ? (current_time.getTime() - footprint.getUpdatedTime().getTime() + footprint.getStayTime()) 126 | // // 最大自习时间 + 已经自习时间 127 | // : footprint.getWantedTime() + footprint.getStayTime()); 128 | 129 | // TODO: 单次记录, 单次时间 130 | staty_time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 131 | // 小于自定义时间 132 | < footprint.getWantedTime() 133 | // 当前时间 - 更新时间 + 已经自习时间 134 | ? (current_time.getTime() - footprint.getUpdatedTime().getTime() + footprint.getStayTime()) 135 | // 最大自习时间 136 | : footprint.getWantedTime()); 137 | 138 | footprint.setStayTime(staty_time); 139 | } else { 140 | // 没有进行过暂离 (自习时间为空) 141 | staty_time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 142 | // 小于自定义时间 143 | < footprint.getWantedTime() 144 | // 当前时间 - 更新时间 145 | ? (current_time.getTime() - footprint.getUpdatedTime().getTime()) 146 | // 最大自习时间 147 | : footprint.getWantedTime()); 148 | footprint.setStayTime(staty_time); 149 | } 150 | 151 | // 跟新足迹内容 152 | this.update(footprint); 153 | 154 | return true; 155 | } 156 | 157 | // 判断状态是否从暂离状态离开 158 | if (footprint.getStatus() == Footprint.STATUS.TEMP) { 159 | // 更新当前时间为离开时间 160 | footprint.setUpdatedTime(Tools.getTimeStamp()); 161 | 162 | // 状态修改为离开 163 | footprint.setStatus(Footprint.STATUS.OUT); 164 | 165 | // TODO: 填充一共总自习时间 166 | 167 | // 存在过暂离的情况, 自习时间本不为空 168 | int staty_time = footprint.getStayTime(); 169 | // 曾经多次暂离 170 | if (staty_time != 0) { 171 | 172 | // TODO: 暂离的也一样, 参照上面离开的注释 173 | // 计算当次自习时间 174 | staty_time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 175 | // 小于自定义时间 176 | < footprint.getWantedTime() 177 | // 当前时间 - 更新时间 + 已经自习时间 178 | ? (current_time.getTime() - footprint.getUpdatedTime().getTime() + footprint.getStayTime()) 179 | // 最大自习时间 + 已经自习时间 180 | : footprint.getWantedTime()); 181 | footprint.setStayTime(staty_time); 182 | } else { 183 | // 没有进行过暂离 (自习时间为空) 184 | staty_time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 185 | // 小于自定义时间 186 | < footprint.getWantedTime() 187 | // 当前时间 - 更新时间 188 | ? (current_time.getTime() - footprint.getUpdatedTime().getTime()) 189 | // 最大自习时间 190 | : footprint.getWantedTime()); 191 | footprint.setStayTime(staty_time); 192 | } 193 | 194 | // 跟新足迹内容 195 | this.update(footprint); 196 | 197 | return true; 198 | } 199 | 200 | return false; 201 | } 202 | 203 | /** 204 | * @param footprintDTO 205 | * @Method pauseSeat 206 | * TODO: 根据完整的足迹实体来进行暂时离开座位的操作 (但其实可以直接根据 user_id来进行操作) 207 | * @Return boolean 208 | * @Exception 209 | * @Date 2020/4/6 8:48 PM 210 | * @Author hezijian6338 211 | * @Version 1.0 212 | */ 213 | @Override 214 | public boolean pauseSeat(FootprintDTO footprintDTO) { 215 | // 先判断状态是否为正常坐下 216 | if (footprintDTO.getStatus() == Footprint.STATUS.IN) { 217 | Footprint footprint = new Footprint(); 218 | 219 | // 直接映射过去, 填充完整 220 | BeanUtils.copyProperties(footprintDTO, footprint); 221 | 222 | // 更新当前时间为暂停时间 223 | footprint.setUpdatedTime(Tools.getTimeStamp()); 224 | 225 | // 状态修改为暂时离开 226 | footprint.setStatus(Footprint.STATUS.TEMP); 227 | 228 | // 跟新足迹内容 229 | this.update(footprint); 230 | 231 | return true; 232 | } else { 233 | // 状态不正确, 返回错误 234 | return false; 235 | } 236 | } 237 | 238 | /** 239 | * @param userId 240 | * @Method pauseSeat 241 | * TODO: (新) 暂停座位方法 242 | * @Return boolean 243 | * @Exception 244 | * @Date 2020/4/8 7:52 PM 245 | * @Author hezijian6338 246 | * @Version 1.0 247 | */ 248 | @Override 249 | public boolean pauseSeat(String userId) { 250 | // TODO: 构建 orm查询条件 (在座 ==> 暂离) 251 | tk.mybatis.mapper.entity.Condition conditionIn = new tk.mybatis.mapper.entity.Condition(Footprint.class); 252 | conditionIn.createCriteria().andEqualTo("userId", userId).andEqualTo("status", Footprint.STATUS.IN); 253 | 254 | List listIn = this.findByCondition(conditionIn); 255 | 256 | // TODO: 构建 orm查询条件 (暂离 ==> 在座) 257 | tk.mybatis.mapper.entity.Condition conditionTemp = new tk.mybatis.mapper.entity.Condition(Footprint.class); 258 | conditionTemp.createCriteria().andEqualTo("userId", userId).andEqualTo("status", Footprint.STATUS.TEMP); 259 | 260 | List listTemp = this.findByCondition(conditionTemp); 261 | 262 | Footprint footprint = null; 263 | 264 | if (listIn.size() == 0 && listTemp.size() == 0) { 265 | return false; 266 | } else if (listIn.size() != 0) { 267 | // TODO: 在座 ==> 暂离 268 | footprint = listIn.get(0); 269 | 270 | // 更新当前时间为暂停时间 271 | footprint.setUpdatedTime(Tools.getTimeStamp()); 272 | 273 | // 增加已经自习时间 √ (下列函数已经包含计算已有自习时间了) 274 | int time = this.checkTime(userId); 275 | 276 | footprint.setStayTime(time); 277 | 278 | // 状态修改为暂时离开 279 | footprint.setStatus(Footprint.STATUS.TEMP); 280 | 281 | // 跟新足迹内容 282 | this.update(footprint); 283 | 284 | return true; 285 | } else if (listTemp.size() != 0) { 286 | // TODO: 暂离 ==> 在座 287 | footprint = listTemp.get(0); 288 | 289 | // 更新当前时间为暂停时间 290 | footprint.setUpdatedTime(Tools.getTimeStamp()); 291 | 292 | // 状态修改为在座 293 | footprint.setStatus(Footprint.STATUS.IN); 294 | 295 | // 跟新足迹内容 296 | this.update(footprint); 297 | 298 | return true; 299 | } 300 | 301 | return false; 302 | } 303 | 304 | /** 305 | * @param user_id 306 | * @Method checkTime 307 | * TODO: 根据现在的用户, 检查现在状态为在坐的的数据, 返回已经使用的时间 308 | * @Return int 309 | * @Exception 310 | * @Date 2020/3/24 7:49 PM 311 | * @Author hezijian6338 312 | * @Version 1.0 313 | */ 314 | @Override 315 | public int checkTime(String user_id) { 316 | // 检查当前用户在坐的数据 317 | List footprintListIn = footprintMapper.checkTime(user_id, Footprint.STATUS.IN); 318 | 319 | List footprintListTemp = footprintMapper.checkTime(user_id, Footprint.STATUS.TEMP); 320 | 321 | Footprint footprint = null; 322 | 323 | // 用户第一次借座, 数组就为 0 324 | if (footprintListIn.size() == 0 && footprintListTemp.size() == 0) 325 | return 0; 326 | else if (footprintListIn.size() != 0) { 327 | // TODO: 在座情况 328 | 329 | footprint = footprintListIn.get(0); 330 | if (footprint == null) 331 | return 0; 332 | else { 333 | int time = 0; 334 | 335 | Timestamp current_time = Tools.getTimeStamp(); 336 | 337 | // 如果没有记录已经坐下的时间, 证明他没有离开过, 直接算就可以了 338 | if (footprint.getStayTime() == 0) { 339 | 340 | // TODO: 如果 (当前时间 - 上次更新时间) < 选择自习时间, 返回 (当前时间 - 上次更新时间); 如果不是, 返回 最大自习时间 (因为已经用完自习时间了) 341 | time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 342 | < footprint.getWantedTime() 343 | ? (current_time.getTime() - footprint.getUpdatedTime().getTime()) 344 | : footprint.getWantedTime()); 345 | 346 | // 时间已经用完, 修改状态为离开座位 347 | if (time >= footprint.getWantedTime()) { 348 | footprint.setUpdatedTime(current_time); 349 | //究竟要不要更新自习时间? 要√ 350 | footprint.setStayTime(time); 351 | // 用完时间, 更新选择的自习时间 352 | footprint.setStatus(Footprint.STATUS.OUT); 353 | 354 | // TODO: 同时设置座位状态空出来 355 | // leaveSeat(String userId) 会把 footprint再操作一次, 所以不采用 √ 356 | // seatService.leaveSeat(user_id); 357 | int row = footprint.getRow(); 358 | int col = footprint.getCol(); 359 | seatService.leaveSeat(footprint.getRoomNumber(), row, col); 360 | 361 | this.update(footprint); 362 | } 363 | 364 | return time; 365 | } else { 366 | // 已经有坐下时间, 证明状态已经修改过 367 | 368 | // FIXME: 这里有一个歧义: 无法判断是暂离回来, 还是时间片用完了, 再补充时间 (还是说补充时间直接新增一条记录 (但是好像往后统计不太好操作)) 369 | 370 | // TODO: 这一段代码的逻辑: 默认当前的期望自习时间是新的, 所以会出现 实际自习时间 > 期望自习时间 的情况 (因为加上了之前的自习时间) 371 | // time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) 372 | // < footprint.getWantedTime() 373 | // ? (current_time.getTime() - footprint.getUpdatedTime().getTime() + footprint.getStayTime()) 374 | // : footprint.getStayTime() + footprint.getWantedTime()); 375 | 376 | // TODO: 这一段代码的逻辑: 默认一条 Footprint记录即为一次坐下, 一次确认自习时间 (无法自主延长, 延长即为第二条记录) 377 | time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime() + footprint.getStayTime()) 378 | < footprint.getWantedTime() 379 | ? (current_time.getTime() - footprint.getUpdatedTime().getTime() + footprint.getStayTime()) 380 | : footprint.getWantedTime()); 381 | 382 | 383 | // 时间已经用完, 修改状态为离开座位 384 | if (time >= footprint.getWantedTime()) { 385 | footprint.setUpdatedTime(current_time); 386 | // 究竟要不要更新自习时间? 要√ 387 | footprint.setStayTime(time); 388 | // 用完时间, 更新选择的自习时间 389 | footprint.setStatus(Footprint.STATUS.OUT); 390 | 391 | // TODO: 同时设置座位状态空出来 392 | // leaveSeat(String userId) 会把 footprint再操作一次, 所以不采用 √ 393 | int row = footprint.getRow(); 394 | int col = footprint.getCol(); 395 | seatService.leaveSeat(footprint.getRoomNumber(), row, col); 396 | 397 | this.update(footprint); 398 | } 399 | 400 | return time; 401 | } 402 | } 403 | } else if (footprintListTemp.size() != 0) { 404 | // TODO: 暂离状态 405 | footprint = footprintListTemp.get(0); 406 | 407 | Timestamp current_time = Tools.getTimeStamp(); 408 | 409 | int time = 0; 410 | 411 | time = Math.toIntExact((current_time.getTime() - footprint.getUpdatedTime().getTime()) > Footprint.TIME.TEMP_TEST ? 0 : (current_time.getTime() - footprint.getUpdatedTime().getTime())); 412 | 413 | // 如果时间返回为 0, 代表时间已经用完了, 设置离开, 释放座位 414 | if (time == 0) { 415 | footprint.setStatus(Footprint.STATUS.OUT); 416 | 417 | this.update(footprint); 418 | 419 | int row = footprint.getRow(); 420 | int col = footprint.getCol(); 421 | seatService.leaveSeat(footprint.getRoomNumber(), row, col); 422 | 423 | return 0; 424 | }else { 425 | return time; 426 | } 427 | } 428 | 429 | return 0; 430 | } 431 | 432 | /** 433 | * @param room_number 434 | * @param seats_number 435 | * @Method checkSeatStatus 436 | * TODO: 根据自习室编号, 座位编号, 寻找当前的座位信息 437 | * @Return com.study.room.model.Footprint 438 | * @Exception 439 | * @Date 2020/4/5 8:36 PM 440 | * @Author hezijian6338 441 | * @Version 1.0 442 | */ 443 | @Override 444 | public Footprint checkSeatStatus(String room_number, String seats_number) { 445 | // TODO: 根据返回的前五列表, 抽取第一座位现阶段的状态返回 446 | 447 | // 获得前五列表 448 | List footprints = footprintMapper.checkSeatStatus(room_number, seats_number); 449 | 450 | // 如果该座位信息存在历史记录的 451 | if (footprints != null) { 452 | 453 | // 不等于 null也有可能是空对象 454 | if (footprints.size() != 0) { 455 | // 取第一条并返回 456 | Footprint footprint = footprints.get(0); 457 | 458 | return footprint; 459 | } else { 460 | return null; 461 | } 462 | } else { 463 | // 如果不存在记录, 返回空值 464 | return null; 465 | } 466 | 467 | } 468 | 469 | /** 470 | * @param userId 471 | * @Method findUseSeatByUserId 472 | * TODO: 根据用户 id信息, 返回正在用的座位信息 473 | * @Return com.study.room.model.Footprint 474 | * @Exception 475 | * @Date 2020/4/11 7:37 PM 476 | * @Author hezijian6338 477 | * @Version 1.0 478 | */ 479 | @Override 480 | public Footprint findUseSeatByUserId(String userId) { 481 | // 检查在座的情况 482 | tk.mybatis.mapper.entity.Condition conditionStateIn = new tk.mybatis.mapper.entity.Condition(Footprint.class); 483 | Example.Criteria criteriaStateIn = conditionStateIn.createCriteria(); 484 | criteriaStateIn.andEqualTo("userId", userId); 485 | criteriaStateIn.andEqualTo("status", Footprint.STATUS.IN); 486 | List footprintsStateIn = this.findByCondition(conditionStateIn); 487 | 488 | if (footprintsStateIn.size() != 0) 489 | return footprintsStateIn.get(0); 490 | 491 | // 检查暂离情况 492 | tk.mybatis.mapper.entity.Condition conditionStateTemp = new tk.mybatis.mapper.entity.Condition(Footprint.class); 493 | Example.Criteria criteriaStateTemp = conditionStateTemp.createCriteria(); 494 | criteriaStateTemp.andEqualTo("userId", userId); 495 | criteriaStateTemp.andEqualTo("status", Footprint.STATUS.TEMP); 496 | List footprintsStateTemp = this.findByCondition(conditionStateTemp); 497 | 498 | if (footprintsStateTemp.size() != 0) { 499 | return footprintsStateTemp.get(0); 500 | } 501 | 502 | return null; 503 | } 504 | 505 | /** 506 | * @param userId 507 | * @Method checkHistoryByUser 508 | * TODO: 根据用户 id信息, 返回前五条历史记录 509 | * @Return java.util.List 510 | * @Exception 511 | * @Date 2020/4/11 7:37 PM 512 | * @Author hezijian6338 513 | * @Version 1.0 514 | */ 515 | @Override 516 | public List checkHistoryByUser(String userId) { 517 | List footprints = footprintMapper.checkHistoryByUser(userId); 518 | return footprints; 519 | } 520 | 521 | /** 522 | * @Method checkOnSeatListByRoomNumber 523 | * TODO: 根据自习室编号, 返回当前在使用的用户列表 524 | * @param roomNumber 525 | * @Return java.util.List 526 | * @Exception 527 | * @Date 2020-04-25 12:08 528 | * @Author hezijian6338 529 | * @Version 1.0 530 | */ 531 | @Override 532 | public List checkOnSeatListByRoomNumber(String roomNumber) { 533 | Condition condition = new Condition(Footprint.class); 534 | Example.Criteria criteria = condition.createCriteria(); 535 | criteria.andEqualTo("roomNumber", roomNumber); 536 | criteria.andEqualTo("status", Footprint.STATUS.IN); 537 | List footprints = this.findByCondition(condition); 538 | 539 | return footprints; 540 | } 541 | 542 | /** 543 | * @Method findInfoByUser 544 | * TODO: 根据用户 id查找入座的信息, 返回给前端 (作废 ==>> findUseSeatByUserId) 545 | * @param userId 546 | * @Return com.study.room.model.Footprint 547 | * @Exception 548 | * @Date 2020-04-26 18:34 549 | * @Author hezijian6338 550 | * @Version 1.0 551 | */ 552 | @Override 553 | public Footprint findInfoByUser(String userId) { 554 | // 检查当前用户在坐的数据 555 | List footprintListIn = footprintMapper.checkTime(userId, Footprint.STATUS.IN); 556 | 557 | List footprintListTemp = footprintMapper.checkTime(userId, Footprint.STATUS.TEMP); 558 | 559 | if (footprintListIn.size() == 0 && footprintListTemp.size() == 0) 560 | return null; 561 | else if (footprintListIn.size() != 0) { 562 | return footprintListIn.get(0); 563 | } 564 | else if (footprintListTemp.size() != 0) { 565 | return footprintListTemp.get(0); 566 | } 567 | 568 | return null; 569 | } 570 | 571 | } 572 | -------------------------------------------------------------------------------- /src/main/resources/study_room.sql: -------------------------------------------------------------------------------- 1 | -- MySQL dump 10.13 Distrib 5.7.27, for Linux (x86_64) 2 | -- 3 | -- Host: hezijian6338.ddns.net Database: study_room 4 | -- ------------------------------------------------------ 5 | -- Server version 5.7.27-0ubuntu0.18.04.1 6 | 7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; 8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; 9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; 10 | /*!40101 SET NAMES utf8 */; 11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; 12 | /*!40103 SET TIME_ZONE='+00:00' */; 13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; 14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; 15 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; 16 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; 17 | 18 | -- 19 | -- Table structure for table `footprint` 20 | -- 21 | 22 | DROP TABLE IF EXISTS `footprint`; 23 | /*!40101 SET @saved_cs_client = @@character_set_client */; 24 | /*!40101 SET character_set_client = utf8 */; 25 | CREATE TABLE `footprint` ( 26 | `id` varchar(255) NOT NULL, 27 | `user_id` varchar(255) NOT NULL, 28 | `room_number` varchar(255) NOT NULL COMMENT '自习室编号', 29 | `seats_number` varchar(255) NOT NULL COMMENT '由 row + _ + col 组成', 30 | `stay_time` varchar(255) NOT NULL COMMENT '存放时间戳差', 31 | `status` int(11) NOT NULL COMMENT '0: 暂时离开(保留90分钟); 1: 正常坐下(时间选择); -1: 正常离开(结束计时)', 32 | `moment_tag` varchar(255) DEFAULT NULL COMMENT '心情标签 (数组, 用 ,分隔)', 33 | `created_time` datetime DEFAULT NULL COMMENT '坐下时间', 34 | `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', 35 | `wanted_time` varchar(255) DEFAULT NULL COMMENT '学生希望自习的时间', 36 | PRIMARY KEY (`id`), 37 | KEY `user_id` (`user_id`), 38 | CONSTRAINT `footprint_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) 39 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 40 | /*!40101 SET character_set_client = @saved_cs_client */; 41 | 42 | -- 43 | -- Dumping data for table `footprint` 44 | -- 45 | 46 | LOCK TABLES `footprint` WRITE; 47 | /*!40000 ALTER TABLE `footprint` DISABLE KEYS */; 48 | INSERT INTO `footprint` VALUES ('00681ab727e24c218ba958c225e3f2c0','899b2bd680c14c9d8f2653a45cd37246','tc203','1,1','48285',-1,NULL,'2020-05-14 19:04:49','2020-05-14 11:05:44','600000'),('02c3edaa55854cf2b1cf86c1e4e9e208','439c4a05b7764e2c918708fc9ca02ce9','za101','1,3','60000',-1,NULL,'2020-05-14 14:00:27','2020-05-14 06:02:04','60000'),('058a48494d12459a8949b0ef4e161a6c','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','11960',-1,NULL,'2020-05-15 15:55:20','2020-05-15 07:55:30','5400000'),('07eed9918bcc47179e301dfced9438e5','4f3d5e95eac24550b8eb3df7f3258dbb','za302','1,2','161339',-1,NULL,'2020-05-14 18:16:03','2020-05-14 10:21:32','1500000'),('0cee2554639443ddb3d08b91f8a5b481','4450852b3307432ebe80239708941880','za302','10,1','0',-1,NULL,'2020-05-15 11:12:21','2020-05-15 03:12:20','600000'),('0f79706f45ae40ca89db59e02d7acb52','439c4a05b7764e2c918708fc9ca02ce9','t38','1,1','4693',-1,NULL,'2020-05-23 14:27:49','2020-05-23 06:27:48','600000'),('0fe2ce21c1fb40d897f0a1dadeb0de2a','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 09:52:22','2020-05-15 01:52:22','2700000'),('1086aae0709f429ab21b96f4cfd99989','1a2a621a06aa4fb59ef95e629bad2958','za101','1,1','22073',-1,NULL,'2020-05-14 17:19:05','2020-05-14 09:19:05','1500000'),('13de24c41bb84d248647d7e89c50a1ae','4450852b3307432ebe80239708941880','za302','10,1','0',-1,NULL,'2020-05-15 11:19:24','2020-05-15 03:19:24','600000'),('1692237081864e56a6201d77b589bc9e','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','60000',-1,NULL,'2020-05-15 10:08:19','2020-05-15 02:09:37','60000'),('19e1743dcc144d5fa0436fcf7393da4a','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','74619',-1,NULL,'2020-05-15 10:11:54','2020-05-15 02:13:29','600000'),('1c363f12ac8d42e0afb3f332690d4159','4da9a3165e6545ddb7051ce6ea9c7904','za302','4,4','203570',-1,NULL,'2020-05-23 20:38:12','2020-05-23 06:13:46','600000'),('1d9fdf072b2449289df9803f6dadd0e4','4450852b3307432ebe80239708941880','za302','6,5','17667',-1,NULL,'2020-05-14 20:45:33','2020-05-14 12:45:32','60000'),('2028fc54d7f94cddae4a333e0c351789','439c4a05b7764e2c918708fc9ca02ce9','za101','8,7','60000',-1,NULL,'2020-05-14 13:45:03','2020-05-14 05:47:07','60000'),('2031359e6827448aba82622d4caa5b0a','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 10:49:04','2020-05-15 02:49:03','600000'),('2b0b548ef10a4f50957179a7a6d8c6ef','899b2bd680c14c9d8f2653a45cd37246','tc203','1,1','15546',-1,NULL,'2020-05-14 19:04:10','2020-05-14 11:04:10','600000'),('2ce9e600489a46c69f4689bd71441671','4450852b3307432ebe80239708941880','za302','10,1','18221',-1,NULL,'2020-05-15 10:10:02','2020-05-15 02:10:19','3600000'),('2d743864798c4f6c9ef237a5a66f8866','4da9a3165e6545ddb7051ce6ea9c7904','textroom','1,1','282942',-1,NULL,'2020-05-23 15:38:55','2020-05-23 06:13:33','5400000'),('2ea652b63a3f426dadedff3a80d40ee5','4da9a3165e6545ddb7051ce6ea9c7904','textroom','1,1','0',-1,NULL,'2020-05-15 15:02:58','2020-05-15 07:02:57','5400000'),('318ea4c564854e0e9bb5b6c5921d929d','4da9a3165e6545ddb7051ce6ea9c7904','textroom','1,1','535359',-1,NULL,'2020-05-23 15:29:31','2020-05-23 06:13:36','5400000'),('355fed85aeb14e799b327e73d81ac675','899b2bd680c14c9d8f2653a45cd37246','tc203','1,1','600000',-1,NULL,'2020-05-14 18:44:14','2020-05-14 10:44:13','600000'),('37d15eb4dff04964b09975d7bbee5916','4450852b3307432ebe80239708941880','za302','10,9','60000',-1,NULL,'2020-05-14 23:06:09','2020-05-14 15:07:31','60000'),('3c7d8d2f7feb48a9a0db5fcc4304fa12','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,9','0',-1,NULL,'2020-05-14 23:08:06','2020-05-14 15:08:06','2700000'),('3df6af93250c4aba98ba8c82ce1f0459','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 11:15:49','2020-05-15 03:15:49','600000'),('42a0377c1a764892a20414429eb9babc','439c4a05b7764e2c918708fc9ca02ce9','za101','4,4','15639',-1,NULL,'2020-05-14 14:35:14','2020-05-14 06:35:14','60000'),('42d551e371414f2ca594ab3750468655','439c4a05b7764e2c918708fc9ca02ce9','za101','1,2','60000',-1,NULL,'2020-05-14 13:57:41','2020-05-14 06:00:03','60000'),('46d51c8fa37746a0b284290c80f6f47b','439c4a05b7764e2c918708fc9ca02ce9','za101','4,3','6680',-1,NULL,'2020-05-14 15:19:14','2020-05-14 07:19:13','600000'),('4a8d059b4cb34e1d80ccc2ec3e6b9663','4f3d5e95eac24550b8eb3df7f3258dbb','za302','5,5','60000',-1,NULL,'2020-05-14 19:48:13','2020-05-14 11:49:29','60000'),('4adcf9f23f5d4636895d8c1f0e6dae8d','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','11047',-1,NULL,'2020-05-23 16:00:00','2020-05-23 06:13:19','5400000'),('4b10aaff757b432fb732517191850553','f8e60123f662473a8e09ff68c14c4462','za302','5,5','84539',-1,NULL,'2020-05-14 19:41:33','2020-05-14 11:45:53','600000'),('4d54921c39a44951a9dde87c842431b2','4da9a3165e6545ddb7051ce6ea9c7904','za101','1,1','13566',-1,NULL,'2020-05-14 16:23:24','2020-05-14 08:23:23','600000'),('4dfed769332f4ceca770646e93648fa4','4f3d5e95eac24550b8eb3df7f3258dbb','za302','5,5','17525',-1,NULL,'2020-05-14 19:57:15','2020-05-14 11:57:32','1500000'),('500641d71f074a2f89c394f1fd9f4a8d','439c4a05b7764e2c918708fc9ca02ce9','za101','4,4','20239',-1,NULL,'2020-05-14 14:35:52','2020-05-14 06:36:57','60000'),('50831cd6997b407baeb5d86f3328500d','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,3','11222',-1,NULL,'2020-05-15 14:28:40','2020-05-15 06:28:48','600000'),('52feefb3b0744afe8719febbf4c70a18','4f3d5e95eac24550b8eb3df7f3258dbb','za302','6,5','60000',-1,NULL,'2020-05-14 20:43:26','2020-05-14 12:44:44','60000'),('57207055712b4a2384a79109715a7081','4f3d5e95eac24550b8eb3df7f3258dbb','za302','2,2','79783',-1,NULL,'2020-05-14 18:29:33','2020-05-14 10:36:03','600000'),('5920affa57504eacbe1b5e8d4c656683','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','600000',-1,NULL,'2020-05-15 11:21:51','2020-05-15 04:08:19','600000'),('5cedaf5a6cf14449bdc60243b5ab9ca7','439c4a05b7764e2c918708fc9ca02ce9','za101','1,1','26241',-1,NULL,'2020-05-14 17:21:09','2020-05-14 09:21:09','1500000'),('62488238a15e47a4996f5deccaba1729','4450852b3307432ebe80239708941880','za302','6,5','60000',-1,NULL,'2020-05-14 21:18:33','2020-05-14 13:22:27','60000'),('705b5398b91140918702d14b4c55fdcb','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','12939',-1,NULL,'2020-05-15 14:59:41','2020-05-15 06:59:53','5400000'),('738464d0017442b2ab8599bb68f1d6ac','4f3d5e95eac24550b8eb3df7f3258dbb','za302','4,5','60000',-1,NULL,'2020-05-14 22:17:26','2020-05-14 14:18:39','60000'),('75a7e0a1c3554733973c0b77e9d815f0','439c4a05b7764e2c918708fc9ca02ce9','za101','8,7','300000',-1,NULL,'2020-05-14 13:26:38','2020-05-14 05:31:47','300000'),('77f064b980714d38899b4b61597a0c08','439c4a05b7764e2c918708fc9ca02ce9','za302','1,1','300000',-1,NULL,'2020-05-14 13:19:12','2020-05-14 05:24:47','300000'),('78275cb36ccf457f911f36bda2a56f9e','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','3498',-1,NULL,'2020-05-15 09:57:18','2020-05-15 01:57:21','3600000'),('7983209ed46247d499dc69f7e222c49b','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','9178',-1,NULL,'2020-05-15 15:23:01','2020-05-15 07:23:13','3600000'),('7a5b57bd7d12497bacf6d7e4957268c2','4f3d5e95eac24550b8eb3df7f3258dbb','za302','6,5','5522',-1,NULL,'2020-05-14 21:27:58','2020-05-14 13:28:02','600000'),('82ccfd79ef6948a69736b6b9f28b0782','4f3d5e95eac24550b8eb3df7f3258dbb','za302','5,5','60000',-1,NULL,'2020-05-14 19:51:18','2020-05-14 11:54:35','60000'),('86275a96b5344be7bac8591c2722a574','439c4a05b7764e2c918708fc9ca02ce9','za101','8,7','60000',-1,NULL,'2020-05-14 13:32:36','2020-05-14 05:35:56','60000'),('88c06abce4b943deb25a66e4a4493f41','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,10','4576',-1,NULL,'2020-05-14 22:42:42','2020-05-14 14:42:46','1500000'),('88c35d4476884784aee6793566c95e04','439c4a05b7764e2c918708fc9ca02ce9','t38','1,1','8015',-1,NULL,'2020-05-23 10:03:37','2020-05-23 02:03:46','5400000'),('8a76d59513cc4dddb08a7343c852a5df','439c4a05b7764e2c918708fc9ca02ce9','za101','1,1','47701',-1,NULL,'2020-05-14 17:27:49','2020-05-14 09:27:48','2700000'),('8d294da0ac1d49a39ae27087a5360b7f','4f3d5e95eac24550b8eb3df7f3258dbb','za302','4,5','60000',-1,NULL,'2020-05-14 21:21:10','2020-05-14 13:22:34','60000'),('8f235b3c0173459f9d353ecb88723168','439c4a05b7764e2c918708fc9ca02ce9','za101','1,1','1518820',-1,NULL,'2020-05-14 16:55:12','2020-05-14 08:55:12','2700000'),('90edfe7cab0f4c87a8bc280103fb8277','4f3d5e95eac24550b8eb3df7f3258dbb','za302','5,6','60000',-1,NULL,'2020-05-14 20:47:53','2020-05-14 12:49:10','60000'),('93e2d6ed4cf540c290dbf66c84d311d2','4450852b3307432ebe80239708941880','za302','4,5','3013',-1,NULL,'2020-05-14 22:19:04','2020-05-14 14:19:07','3600000'),('95a3df779de14044b0f47d21071c342f','4f3d5e95eac24550b8eb3df7f3258dbb','za302','5,6','60000',-1,NULL,'2020-05-14 20:26:21','2020-05-14 12:32:44','60000'),('9627756282094a7895557b578d1e4718','1a2a621a06aa4fb59ef95e629bad2958','za302','10,10','108074',-1,NULL,'2020-05-23 19:15:29','2020-05-23 06:13:53','600000'),('9edabe9d99114424b002332acd794cb2','4f3d5e95eac24550b8eb3df7f3258dbb','za302','1,2','245669',-1,NULL,'2020-05-14 18:22:02','2020-05-14 10:27:41','600000'),('a081a30e985d43e4baab5979c3d90b98','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 09:41:17','2020-05-15 01:41:16','2700000'),('a1c9c117dcaf460da7d1485dbb373348','f8e60123f662473a8e09ff68c14c4462','za302','5,5','442922',-1,NULL,'2020-05-14 19:33:06','2020-05-14 11:33:54','600000'),('ab66fff8a46d4ad9bd6e95c9083ad8af','297427a24a9f44bab2e49128a62b897b','textroom','1,1','10907',-1,NULL,'2020-05-15 12:13:34','2020-05-15 04:13:43','600000'),('ac030bf292eb4e268f828d3597ca34f0','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','12702',-1,NULL,'2020-05-15 10:10:59','2020-05-15 02:10:58','5400000'),('ac24e68eeccc4416be7cfd1e266515b0','439c4a05b7764e2c918708fc9ca02ce9','za230','1,1','24199',-1,NULL,'2020-05-23 15:08:35','2020-05-23 07:08:34','3600000'),('b0959be4fd0549a3ba12432de95ef50d','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','15109',-1,NULL,'2020-05-15 15:33:33','2020-05-15 07:33:44','5400000'),('b32e0646e038435b8971cf302afd3f8a','4da9a3165e6545ddb7051ce6ea9c7904','textroom','1,1','604882',-1,NULL,'2020-05-23 15:50:47','2020-05-23 06:13:27','5400000'),('b39c730d3dff4c68ab25adb9eb815192','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 10:22:22','2020-05-15 02:22:21','1500000'),('b413d81f1c124aa0bfcc5141bdb9c41e','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 11:05:41','2020-05-15 03:05:41','600000'),('b4713f0924fc485c99bf31b2fb4f5e1e','439c4a05b7764e2c918708fc9ca02ce9','za101','8,7','60000',-1,NULL,'2020-05-14 13:52:44','2020-05-14 05:57:00','60000'),('b6df76605321429d9575d3c5e66cd7dc','4da9a3165e6545ddb7051ce6ea9c7904','textroom','1,1','0',-1,NULL,'2020-05-15 13:53:22','2020-05-15 05:53:22','5400000'),('b789ae1dd90a478aaf8324d82112adbc','4450852b3307432ebe80239708941880','za302','5,6','14963',-1,NULL,'2020-05-14 20:51:50','2020-05-14 12:51:50','60000'),('bb8e90ede50a44db988121cee9be9558','4450852b3307432ebe80239708941880','za302','10,1','0',-1,NULL,'2020-05-15 11:02:28','2020-05-15 03:02:28','600000'),('bc146c5fffbd4883ae11cd3b773a0bb2','1a2a621a06aa4fb59ef95e629bad2958','za101','4,3','68021',-1,NULL,'2020-05-14 16:18:51','2020-05-14 08:18:51','600000'),('bcfb7856dd624126a2055e752961c2a2','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,9','60000',-1,NULL,'2020-05-14 23:04:54','2020-05-14 15:06:06','60000'),('bf59f58783734cd7bf8ec0640b7a49b0','8b1f786c4871428e97b2c5dbeb32a1f9','textroom','1,2','13165',-1,NULL,'2020-05-15 14:18:06','2020-05-15 06:18:21','600000'),('bf5c746282d647fd897ca358d0962ab8','4da9a3165e6545ddb7051ce6ea9c7904','za302','1,1','300000',-1,NULL,'2020-05-14 13:06:15','2020-05-14 05:11:58','300000'),('c0253aa3b6f544d3ab98b061073a2ac5','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','4503',-1,NULL,'2020-05-15 10:03:37','2020-05-15 02:03:41','600000'),('c1d934d3e1b5460587b263e214552d12','439c4a05b7764e2c918708fc9ca02ce9','za101','4,4','50307',-1,NULL,'2020-05-14 14:37:40','2020-05-14 06:38:31','2700000'),('c1fcc2b4e19449b09a0274aef8b7ab37','4f3d5e95eac24550b8eb3df7f3258dbb','za302','1,2','41260',-1,NULL,'2020-05-14 19:04:51','2020-05-14 11:06:18','1500000'),('c563c41f522a4fba99f826ad4d0e5541','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','10479',-1,NULL,'2020-05-15 15:42:37','2020-05-15 07:42:47','5400000'),('c6195d8f08734ca5bac1a8743bfd8888','439c4a05b7764e2c918708fc9ca02ce9','za101','4,3','3600000',-1,NULL,'2020-05-14 15:19:29','2020-05-14 08:54:17','3600000'),('c8576e8449a74fa59f13a2de6b63ea19','4450852b3307432ebe80239708941880','za302','10,9','60000',-1,NULL,'2020-05-14 23:35:29','2020-05-15 01:37:44','60000'),('c9f10c86a3fb4cb39d04ff2c5a032345','439c4a05b7764e2c918708fc9ca02ce9','za101','1,3','60000',-1,NULL,'2020-05-14 14:21:15','2020-05-14 06:23:13','60000'),('d10e45b84df641dc9870606bdb892beb','1a2a621a06aa4fb59ef95e629bad2958','za101','8,3','5287',-1,NULL,'2020-05-14 15:20:57','2020-05-14 07:20:56','60000'),('d1f628a4a291444e8f6fa09ee810b24a','4f3d5e95eac24550b8eb3df7f3258dbb','textroom','1,2','9161',-1,NULL,'2020-05-15 15:26:48','2020-05-15 07:26:59','1500000'),('da8bb8515d034d6a929c117aa80e7826','439c4a05b7764e2c918708fc9ca02ce9','za101','8,7','24804',-1,NULL,'2020-05-14 13:47:40','2020-05-14 05:47:40','60000'),('e2fc4c0ebfc848adaa3ead4ac8d0d74c','4f3d5e95eac24550b8eb3df7f3258dbb','za302','10,1','0',-1,NULL,'2020-05-15 10:53:17','2020-05-15 02:53:16','600000'),('e49611b9f38147b9baa360900a87608c','439c4a05b7764e2c918708fc9ca02ce9','za101','1,4','60000',-1,NULL,'2020-05-14 14:33:08','2020-05-14 06:34:25','60000'),('e9d9f71ec9d744ca8606079303394830','4450852b3307432ebe80239708941880','za302','10,1','20645',-1,NULL,'2020-05-15 10:55:52','2020-05-15 02:55:52','600000'),('f0851f83966d467db59f4af664f1c7ef','1a2a621a06aa4fb59ef95e629bad2958','za101','1,1','24598',-1,NULL,'2020-05-14 16:49:43','2020-05-14 08:49:42','600000'),('f384f0a9d4e8411ba47cae39f3f9088f','4f3d5e95eac24550b8eb3df7f3258dbb','za302','4,5','0',-1,NULL,'2020-05-14 21:53:41','2020-05-14 13:53:40','1500000'),('f41a69ace48249db9b87e938a40bc5a4','4450852b3307432ebe80239708941880','za302','10,1','0',-1,NULL,'2020-05-15 10:56:33','2020-05-15 02:56:33','600000'),('f848fae5dbff46299d2c8529fdf36adb','439c4a05b7764e2c918708fc9ca02ce9','za101','1,3','60000',-1,NULL,'2020-05-14 14:23:54','2020-05-14 06:31:21','60000'),('fa9da772d0a642c594d1d98aae42fcdb','4f3d5e95eac24550b8eb3df7f3258dbb','za302','6,5','0',-1,NULL,'2020-05-14 20:54:46','2020-05-14 12:54:46','2700000'),('fdc354f107e645a788c0643eb324d90b','439c4a05b7764e2c918708fc9ca02ce9','za101','1,1','34330',-1,NULL,'2020-05-14 17:22:40','2020-05-14 09:22:39','600000'),('fdda23f68d084538a015e259289abb5d','4450852b3307432ebe80239708941880','za302','10,1','0',-1,NULL,'2020-05-15 10:38:53','2020-05-15 02:38:52','600000'),('ff6ed939512d49c584402962d5666a23','439c4a05b7764e2c918708fc9ca02ce9','za101','4,3','198873',-1,NULL,'2020-05-14 15:11:07','2020-05-14 07:16:09','600000'); 49 | /*!40000 ALTER TABLE `footprint` ENABLE KEYS */; 50 | UNLOCK TABLES; 51 | 52 | -- 53 | -- Table structure for table `seat` 54 | -- 55 | 56 | DROP TABLE IF EXISTS `seat`; 57 | /*!40101 SET @saved_cs_client = @@character_set_client */; 58 | /*!40101 SET character_set_client = utf8 */; 59 | CREATE TABLE `seat` ( 60 | `id` varchar(255) NOT NULL, 61 | `name` varchar(255) NOT NULL COMMENT '自习室名称', 62 | `room_number` varchar(255) NOT NULL COMMENT '自习室编号', 63 | `seats` varchar(255) NOT NULL COMMENT '座位位置和状态', 64 | `seats_count` int(11) NOT NULL COMMENT '座位总数', 65 | `seats_available` int(11) NOT NULL COMMENT '剩余座位数量', 66 | `seats_unavailabe` int(11) NOT NULL COMMENT '已使用座位数量', 67 | `status` int(11) NOT NULL COMMENT '0: 待用; 1: 启用; -1: 维护', 68 | `created_time` datetime DEFAULT NULL, 69 | `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 70 | PRIMARY KEY (`id`), 71 | UNIQUE KEY `seat_room_number_IDX` (`room_number`) USING BTREE 72 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 73 | /*!40101 SET character_set_client = @saved_cs_client */; 74 | 75 | -- 76 | -- Dumping data for table `seat` 77 | -- 78 | 79 | LOCK TABLES `seat` WRITE; 80 | /*!40000 ALTER TABLE `seat` DISABLE KEYS */; 81 | INSERT INTO `seat` VALUES ('1a92589e6e084cd584fd15aedc7da251','t38','t38','[0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000]',100,100,0,1,'2020-05-14 12:15:43','2020-05-14 04:15:42'),('265b766295fc499585ed3c7cce3a895f','za230','za230','[00, 00]',4,4,0,1,'2020-05-15 14:52:19','2020-05-15 06:52:19'),('33c1b65ceb4c40b396f6449068e84427','za203','za203','[0000, 0000, 0000, 0000]',16,16,0,1,'2020-05-15 14:40:40','2020-05-15 06:40:40'),('4f05ba43e0e54fa599fc03a3622adc0a','za563','za563','[00000, 00000, 00000, 00000, 00000]',25,25,0,1,'2020-05-15 14:49:41','2020-05-15 06:49:41'),('5767ca837e914019bca6daa1b59878b9','tsg301','tsg301','[00000000, 00000000, 00000000, 00000000, 00000000, 00000000, 00000000, 00000000]',64,64,0,1,'2020-05-14 12:17:34','2020-05-14 04:17:34'),('67fffa5e69c7474ca9690e968981eebc','t25','t25','[000000, 000000, 000000, 000000, 000000, 000000]',36,36,0,1,'2020-05-14 12:19:35','2020-05-14 04:19:34'),('819b544d3a1e408eb224588932e5417c','textroom','textroom','[00, 00]',4,4,0,1,'2020-05-15 12:03:21','2020-05-15 04:03:21'),('a98ac13c9c2040a38fed3f2984d1a5a6','mb103','mb103','[0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000]',100,100,0,1,'2020-05-14 12:14:06','2020-05-14 04:14:05'),('aed9b18508f4401e95e69cf47edf9069','za560','za560','[00, 00]',4,4,0,1,'2020-05-15 14:44:51','2020-05-15 06:44:51'),('bd258fb060f841aa895c6590c5c57239','za596','za596','[00000, 00000, 00000, 00000, 00000]',25,25,0,1,'2020-05-15 14:54:20','2020-05-15 06:54:20'),('bffe083a96fa4be9849fabb7615899c7','za502','za502','[00000, 00000, 00000, 00000, 00000]',25,25,0,1,'2020-05-14 12:14:37','2020-05-14 04:14:37'),('c6850a7bf78e466b8fc01e6a75b7e147','hf101','hf101','[0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000, 0000000000]',100,100,0,1,'2020-05-14 12:16:19','2020-05-14 04:16:19'); 82 | /*!40000 ALTER TABLE `seat` ENABLE KEYS */; 83 | UNLOCK TABLES; 84 | 85 | -- 86 | -- Table structure for table `user` 87 | -- 88 | 89 | DROP TABLE IF EXISTS `user`; 90 | /*!40101 SET @saved_cs_client = @@character_set_client */; 91 | /*!40101 SET character_set_client = utf8 */; 92 | CREATE TABLE `user` ( 93 | `id` varchar(255) NOT NULL, 94 | `name` varchar(255) NOT NULL COMMENT '用户名称', 95 | `password` varchar(255) DEFAULT NULL COMMENT '管理员/学生', 96 | `student_num` varchar(255) NOT NULL COMMENT '学生学号', 97 | `phone` varchar(255) NOT NULL COMMENT '用户电话', 98 | `role` int(11) NOT NULL COMMENT '0: 普通用户;1: 管理员; 2: 超级管理员', 99 | `status` int(11) NOT NULL COMMENT '0: 停用; 1: 启用; -1: 黑名单', 100 | `bad_record` int(11) NOT NULL COMMENT '默认0, 到3 自动转换黑名单', 101 | `created_time` datetime DEFAULT NULL, 102 | `updated_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 103 | PRIMARY KEY (`id`), 104 | UNIQUE KEY `student_num` (`student_num`) 105 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 106 | /*!40101 SET character_set_client = @saved_cs_client */; 107 | 108 | -- 109 | -- Dumping data for table `user` 110 | -- 111 | 112 | LOCK TABLES `user` WRITE; 113 | /*!40000 ALTER TABLE `user` DISABLE KEYS */; 114 | INSERT INTO `user` VALUES ('0f3b25158ff94675ba486943c407b7c7','dsadda','21232F297A57A5A743894A0E4A801FC3','1561651','4564654',0,1,0,'2020-05-15 14:54:02','2020-05-15 06:54:01'),('1a2a621a06aa4fb59ef95e629bad2958','用户二','21232F297A57A5A743894A0E4A801FC3','160201102860','13222222222',0,1,0,'2020-05-14 12:34:34','2020-05-14 04:34:34'),('28a139dd1e26463e8a816f2b57612df0','cjy','21232F297A57A5A743894A0E4A801FC3','160201101111','13711111111',0,1,0,'2020-05-14 12:43:53','2020-05-14 04:43:53'),('297427a24a9f44bab2e49128a62b897b','用户八','21232F297A57A5A743894A0E4A801FC3','160201102866','13288888888',0,1,0,'2020-05-14 12:37:34','2020-05-14 04:37:34'),('439c4a05b7764e2c918708fc9ca02ce9','用户一','21232F297A57A5A743894A0E4A801FC3','160201102859','13211111111',0,-1,2,'2020-05-14 12:33:10','2020-05-14 04:33:10'),('4450852b3307432ebe80239708941880','用户四','21232F297A57A5A743894A0E4A801FC3','160201102862','13244444444',0,1,2,'2020-05-14 12:35:26','2020-05-14 04:35:26'),('4da9a3165e6545ddb7051ce6ea9c7904','曹靖洋','21232F297A57A5A743894A0E4A801FC3','160201102858','13250539836',1,1,0,'2020-04-15 14:20:09','2020-04-24 09:27:56'),('4f07cca88eba4144acac1b2f402dab90','ddsa','21232F297A57A5A743894A0E4A801FC3','16020','45465',0,1,0,'2020-05-15 14:52:01','2020-05-15 06:52:00'),('4f3d5e95eac24550b8eb3df7f3258dbb','用户三','21232F297A57A5A743894A0E4A801FC3','160201102861','13233333333',0,-1,1,'2020-05-14 12:34:57','2020-05-14 04:34:56'),('5d6a95ca46df4012aeef69c0d78811cc','dsdsada','21232F297A57A5A743894A0E4A801FC3','111','2613',0,1,0,'2020-05-15 14:40:17','2020-05-15 06:40:16'),('6b410d5c52d54a87ac7e8261bc58db53','用户七','21232F297A57A5A743894A0E4A801FC3','160201102865','13277777777',0,1,0,'2020-05-14 12:36:59','2020-05-14 04:36:59'),('775f962bd79c4a5d9ba1539b5a954349','bobby','21232F297A57A5A743894A0E4A801FC3','160201111111','13722222222',0,1,0,'2020-05-14 12:57:02','2020-05-14 04:57:02'),('81f652f7484e4a1298e33cdc5f23c238','dads','21232F297A57A5A743894A0E4A801FC3','516','151532',0,1,0,'2020-05-15 14:44:31','2020-05-15 06:44:31'),('899b2bd680c14c9d8f2653a45cd37246','何子健','21232F297A57A5A743894A0E4A801FC3','140202011031','13160666721',0,1,0,'2020-05-14 14:21:51','2020-05-14 06:21:51'),('8b1f786c4871428e97b2c5dbeb32a1f9','用户九','21232F297A57A5A743894A0E4A801FC3','160201102867','13299999999',0,1,0,'2020-05-14 12:38:10','2020-05-14 04:38:09'),('a238e3fc1d18406ebf272f3c2e5b2b8c','用户六','21232F297A57A5A743894A0E4A801FC3','160201102864','13266666666',0,1,0,'2020-05-14 12:36:39','2020-05-14 04:36:39'),('b7fd8102ce714d8e980fc5f7a5a21ae4','xxx','21232F297A57A5A743894A0E4A801FC3','16020110xxxx','xxxxxxxxxxx',0,1,0,'2020-05-23 14:02:17','2020-05-23 06:02:17'),('e2f24bb5ddd84a9b8571e290392acd8b','dsdas','21232F297A57A5A743894A0E4A801FC3','45463','46545',0,1,0,'2020-05-15 14:49:21','2020-05-15 06:49:21'),('f8e60123f662473a8e09ff68c14c4462','用户五','21232F297A57A5A743894A0E4A801FC3','160201102863','13255555555',0,1,0,'2020-05-14 12:35:42','2020-05-14 04:35:42'); 115 | /*!40000 ALTER TABLE `user` ENABLE KEYS */; 116 | UNLOCK TABLES; 117 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; 118 | 119 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; 120 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; 121 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; 122 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 123 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 124 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 125 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; 126 | 127 | -- Dump completed on 2020-05-27 13:49:13 128 | --------------------------------------------------------------------------------