diff --git a/Dockerfile b/Dockerfile
index a02b14a..2c7841f 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,23 +1,27 @@
-# 基础镜像使用Java
+#指定基础镜像(一般指定程序所依赖的环境)
+#本例子是构建SpringBoot,所以指定的jdk环境变量
FROM openjdk:17
+#添加维护者信息
+MAINTAINER author:chenyuepan
+MAINTAINER mail:3158614516@qq.com
-# 作者
-MAINTAINER yuepan
+#将./hello-world.jar添加到容器的/opt目录中
+COPY ./venue_reservation_service-0.0.1-SNAPSHOT.jar /opt
-# 指定容器需要映射到主机的端口
-EXPOSE 9020
-
-# VOLUME 指定了临时文件目录为/tmp。
-# 其效果是在主机 /var/lib/docker 目录下创建了一个临时文件,并链接到容器的/tmp
-VOLUME /tmp
+#指定dockerfile的命令在哪个目录下执行
+WORKDIR /opt
-# 定义 JAR_FILE 参数,默认值为打包的 JAR 文件名
-ARG JAR_FILE=venue_reservation_service-0.0.1-SNAPSHOT.jar
+#指定容器和外界交互的端口
+EXPOSE 9020
-# 将jar包添加到容器中并更名为app.jar
-ADD target/${JAR_FILE} /docker-venue.jar
+#容器运行后执行的命令(该命令在WORKDIR指定的工作目录下执行)
+#注意:多个CMD指令只有最后一个会生效
+CMD java -jar venue_reservation_service-0.0.1-SNAPSHOT.jar
-#容器启动执行命令
-ENTRYPOINT ["java", "-jar", "/docker-venue.jar"]
+#在构建镜像时执行的命令
+#我这边用它来打印java的环境变量
+RUN java -version
+#添加该镜像的元数据
+LABEL version="1.0" description="这是一个Web服务器" by="edc"
diff --git a/drone.yml b/drone.yml
new file mode 100644
index 0000000..7b6e1a0
--- /dev/null
+++ b/drone.yml
@@ -0,0 +1,41 @@
+kind: pipeline
+type: docker
+name: venue_reservation_service
+
+steps:
+ - name: build-jar # 流水线名称
+ image: maven:3.8.5-openjdk-17 # 定义创建容器的Docker镜像
+ volumes: # 将容器内目录挂载到宿主机,仓库需要开启Trusted设置
+ - name: maven-cache
+ path: /root/.m2 # 将maven下载依赖的目录挂载出来,防止重复下载
+ - name: maven-build
+ path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
+ commands: # 定义在Docker容器中执行的shell命令
+ - mvn clean package -DskipTests=true # 应用打包命
+ - cp target/game.jar /app/build/venue_reservation_service-0.0.1-SNAPSHOT.jar
+ - cp Dockerfile /app/build/
+ - cp run.sh /app/build/
+ - name: build-docker # 流水线名称
+ image: plugins/docker
+ volumes: # 将容器内目录挂载到宿主机,仓库需要开启Trusted设置
+ - name: maven-build
+ path: /app/build # 将应用打包好的Jar和执行脚本挂载出来
+ - name: docker
+ path: /var/run/docker.sock # 挂载宿主机的docker
+ settings:
+ dockerfile: /app/build/Dockerfile
+ commands: # 定义在Docker容器中执行的shell命令
+ - cd /app/build
+ - chmod +x run.sh
+ - sh run.sh
+ - docker ps
+volumes: # 定义流水线挂载目录,用于共享数据
+ - name: maven-build
+ host:
+ path: /home/docker/drone/maven/build # 从宿主机中挂载的目录
+ - name: maven-cache
+ host:
+ path: /home/docker/drone/maven/cache
+ - name: docker
+ host:
+ path: /var/run/docker.sock
diff --git a/pom.xml b/pom.xml
index 33ed0c4..da2944c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -202,6 +202,24 @@
+ * Knife4j配置类 + *
+ * + * @author Patrick + * @since 2025-1-1 + */ +@Configuration +public class Knife4jConfig { + + /** + * 创建系统分组api + * + */ + @Bean + public GroupedOpenApi systemApi() { + return createRestApi("系统管理", "com.example.venue_reservation_service.controller"); + } + + /** + * 创建api + * + * @param groupName 分组名称 + * @param basePackage 包路径 + * @return GroupedOpenApi + */ + public GroupedOpenApi createRestApi(String groupName, String basePackage) { + return GroupedOpenApi.builder() + .group(groupName) // 分组名称 + .packagesToScan(basePackage) // 扫描的包路径 + .pathsToMatch("/**") // 匹配所有路径 + .addOpenApiCustomizer(openApi -> openApi.info(apiInfo())) // 设置api信息 + .build(); + } + + /** + * api简介信息 + * + * @return ApiInfo + */ + private Info apiInfo() { + return new Info() + .title("华交场馆管控一体化平台API") // 标题 + .description("校园 e 站通・华交场馆管控一体化平台 -- 接口文档") // 描述 + .version("1.0.0") // 版本号 + .termsOfService("http://doc.xiaominfo.com") // 服务条款 + .contact(new Contact().name("实训小组1") + .url("https://github.com/Patrick-Luo-THR") + .email("patrick.luo@163.com")) // 联系人信息 + .license(new License().name("Apache 2.0") + .url("http://www.apache.org/licenses/LICENSE-2.0.html")); // 许可证信息 + } + +} + diff --git a/src/main/java/com/example/venue_reservation_service/config/RabbitMQConfig.java b/src/main/java/com/example/venue_reservation_service/config/RabbitMQConfig.java new file mode 100644 index 0000000..26866f4 --- /dev/null +++ b/src/main/java/com/example/venue_reservation_service/config/RabbitMQConfig.java @@ -0,0 +1,35 @@ +package com.example.venue_reservation_service.config; + +import org.springframework.amqp.core.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Map; + +@Configuration +public class RabbitMQConfig { + + // 定义延迟交换机(使用自定义x-delayed-message类型) + @Bean + public CustomExchange delayedExchange() { + return new CustomExchange("delayed.exchange", "x-delayed-message", + true, + false, + Map.of("x-delayed-type", "direct")); + } + + // 定义延迟队列 + @Bean + public Queue delayedQueue() { + return QueueBuilder.durable("delayed.queue").build(); + } + + // 绑定队列到交换机 + @Bean + public Binding binding(Queue delayedQueue, CustomExchange delayedExchange) { + return BindingBuilder.bind(delayedQueue) + .to(delayedExchange) + .with("delay.routing.key") + .noargs(); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/controller/AdminController.java b/src/main/java/com/example/venue_reservation_service/controller/AdminController.java index 415a6e2..5919eba 100644 --- a/src/main/java/com/example/venue_reservation_service/controller/AdminController.java +++ b/src/main/java/com/example/venue_reservation_service/controller/AdminController.java @@ -1,60 +1,62 @@ package com.example.venue_reservation_service.controller; -import com.example.venue_reservation_service.domain.User; import com.example.venue_reservation_service.dto.AdminSlot; import com.example.venue_reservation_service.dto.PointDTO; import com.example.venue_reservation_service.service.AdminService; import com.example.venue_reservation_service.vo.Result; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/admin") @CrossOrigin -@Api("管理员接口") +@Tag(name = "管理员接口", description = "管理员及超级管理员专用接口,包含场馆管理、用户管理等操作") public class AdminController { @Resource private AdminService adminService; - @ApiOperation("查询管理的场馆") + @Operation(summary = "查询管理的场馆", description = "根据管理员ID查询其管理的所有场馆信息", parameters = {@Parameter(name = "userId", description = "管理员用户ID", required = true)}) @GetMapping("/query") - public Result query(@RequestParam("userId") Integer userId){ + public Result query(@RequestParam("userId") Integer userId) { return adminService.queryVenue(userId); } - @ApiOperation("管理员添加场地禁用时间") + @Operation(summary = "添加场地禁用时间", description = "设置指定场地的禁用时间段,用于维护或特殊安排", parameters = {@Parameter(name = "slot", description = "场地禁用时间对象,包含场地ID、开始/结束时间等信息", required = true)}) @PostMapping("/time") - public Result time(@RequestBody AdminSlot slot){ + public Result time(@RequestBody AdminSlot slot) { return adminService.addTime(slot); } - @ApiOperation("通过手机号查询用户") + @Operation(summary = "通过手机号查询用户", description = "根据手机号精确查询用户信息", parameters = {@Parameter(name = "phone", description = "用户手机号(11位数字)", required = true)}) @GetMapping("/select") - public Result select(@RequestParam("phone") String phone){ + public Result select(@RequestParam("phone") String phone) { return adminService.selectUser(phone); } - @ApiOperation("管理员为用户账号充值积分") + @Operation(summary = "为用户充值积分", description = "管理员为指定用户账号充值积分,支持备注说明", parameters = {@Parameter(name = "dto", description = "积分充值对象,包含用户ID、积分数量、操作备注等信息", required = true)}) @PostMapping("/point") - public Result point(@RequestBody PointDTO dto){ + public Result point(@RequestBody PointDTO dto) { return adminService.userPoint(dto); } - @ApiOperation("管理员绑定关联场馆") + @Operation(summary = "管理员绑定关联场馆", description = "将管理员与指定类型的场馆进行关联,使其可以管理该场馆", parameters = { + @Parameter(name = "userId", description = "管理员用户ID", required = true), + @Parameter(name = "typeId", description = "场馆编号", required = true)}) @PostMapping("/manage") - public Result manage(@RequestParam("userId") Integer userId, - @RequestParam("typeId") Integer typeId){ + public Result manage(@RequestParam("userId") Integer userId, @RequestParam("typeId") Integer typeId) { return adminService.manage(userId, typeId); } - @ApiOperation("移除关联场馆信息") + @Operation(summary = "移除关联场馆", description = "取消管理员与指定类型场馆的关联关系", + parameters = { + @Parameter(name = "userId", description = "管理员用户ID", required = true), + @Parameter(name = "typeId", description = "场馆编号", required = true)}) @PostMapping("/cancel") - public Result cancel(@RequestParam("userId") Integer userId, - @RequestParam("typeId") Integer typeId){ + public Result cancel(@RequestParam("userId") Integer userId, @RequestParam("typeId") Integer typeId) { return adminService.cancel(userId, typeId); } - -} +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java b/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java index 8f87e90..3cd32e6 100644 --- a/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java +++ b/src/main/java/com/example/venue_reservation_service/controller/ReservationController.java @@ -65,13 +65,13 @@ public class ReservationController { @ApiOperation("获取预约数据") @GetMapping("/data") - public Result data(@RequestParam("college") String college){ - return reservationService.queryData(college); + public Result data(){ + return Result.ok(reservationService.list()).message("数据获取成功"); } @ApiOperation("导出用户预约记录") - @GetMapping("/excel/{id}") - public void excel(@PathVariable("id") Integer userId, HttpServletResponse response){ + @GetMapping("/excel") + public void excel(@RequestParam(value = "id", required = false) Integer userId, HttpServletResponse response){ reservationService.exportExcel(response, userId); } diff --git a/src/main/java/com/example/venue_reservation_service/controller/UserController.java b/src/main/java/com/example/venue_reservation_service/controller/UserController.java index ab44b6e..e6762e3 100644 --- a/src/main/java/com/example/venue_reservation_service/controller/UserController.java +++ b/src/main/java/com/example/venue_reservation_service/controller/UserController.java @@ -1,118 +1,308 @@ package com.example.venue_reservation_service.controller; -import com.example.venue_reservation_service.annotation.Log; import com.example.venue_reservation_service.domain.User; import com.example.venue_reservation_service.dto.*; +import com.example.venue_reservation_service.mq.DelayMessageSender; import com.example.venue_reservation_service.service.UserService; import com.example.venue_reservation_service.vo.Result; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import java.time.LocalDate; +import java.time.LocalTime; + @RestController @RequestMapping("/user") -@Api("用户接口管理") +@Tag(name = "用户模块", description = "用户模块相关接口,包含登录、信息管理、充值等功能") @CrossOrigin public class UserController { @Resource private UserService userService; + @Autowired + private DelayMessageSender delayMessageSender; + + // 原始预约处理方法替换为发送延迟消息 + public void scheduleReservationCheck(long reservationId, LocalDate reservationDate, LocalTime end) { + delayMessageSender.sendReservationCheck(reservationId, reservationDate, end); + } + @GetMapping("/test") - public Result test(){ - return Result.ok("test").message("success"); + @Operation( + summary = "示例接口", + description = "用于测试系统通信的示例接口,发送测试消息到RabbitMQ", + parameters = {} + ) + public Result test() { + delayMessageSender.sendTestMessage(); + return Result.ok("测试消息已发送,请观察控制台输出").message("success"); } - @ApiOperation("login") + @Operation( + summary = "用户登录", + description = "通过微信小程序临时授权码获取用户OpenID完成登录", + parameters = { + @Parameter( + name = "code", + description = "微信小程序登录时获取的临时授权码(有效期5分钟)", + required = true, + schema = @Schema(type = "string"), + example = "0A3m7r000aBcDe123f456" + ) + } + ) @GetMapping("/login") - public Result getOpenId(@RequestParam("code")String code){ + public Result getOpenId(@RequestParam("code") String code) { return userService.getOpenId(code); } - @ApiOperation("管理员登录") + @Operation( + summary = "管理员登录", + description = "场馆管理员登录系统,验证账号密码", + parameters = { + @Parameter( + name = "dto", + description = "管理员登录DTO,包含账号和密码", + required = true, + schema = @Schema(implementation = AdminDTO.class) + ) + } + ) @PostMapping("/admin") -// @Log(operationType = "POST", operationDesc = "场馆管理员登录,用户账号为#{#body.account}") - public Result adminLogin(@RequestBody AdminDTO dto){ + public Result adminLogin(@RequestBody AdminDTO dto) { return userService.adminLogin(dto); } - @ApiOperation("用户个人信息完善") + @Operation( + summary = "完善用户信息", + description = "用户完善个人信息,如姓名、性别、生日等", + parameters = { + @Parameter( + name = "userInfo", + description = "用户信息DTO,包含用户基本资料", + required = true, + schema = @Schema(implementation = UserInfo.class) + ) + } + ) @PostMapping("/update") - public Result update(@RequestBody UserInfo userInfo){ + public Result update(@RequestBody UserInfo userInfo) { return userService.userUpdate(userInfo); } - @ApiOperation("获取用户列表") + @Operation( + summary = "查询用户列表", + description = "根据条件查询用户列表,支持分页和筛选", + parameters = { + @Parameter( + name = "dto", + description = "用户查询DTO,包含查询条件和分页参数", + required = true, + schema = @Schema(implementation = UserDTO.class) + ) + } + ) @PostMapping("/list") - public Result queryUserList(@RequestBody UserDTO dto){ + public Result queryUserList(@RequestBody UserDTO dto) { return userService.getUserList(dto); } - @ApiOperation("校验用户身份信息") + @Operation( + summary = "校验用户身份", + description = "校验用户提交的身份信息(如身份证、学生证等)", + parameters = { + @Parameter( + name = "dto", + description = "身份校验DTO,包含用户身份信息", + required = true, + schema = @Schema(implementation = CheckDTO.class) + ) + } + ) @PostMapping("/check") - public Result check(@RequestBody CheckDTO dto){ + public Result check(@RequestBody CheckDTO dto) { return userService.userCheck(dto); } - @ApiOperation("获取用户的认证信息") + @Operation( + summary = "获取用户认证信息", + description = "根据用户ID获取其认证信息(如学校、专业等)", + parameters = { + @Parameter( + name = "userId", + description = "用户ID", + required = true, + schema = @Schema(type = "integer") + ) + } + ) @GetMapping("/detail") - public Result get(@RequestParam("id") Integer userId){ + public Result get(@RequestParam("id") Integer userId) { return userService.getSchool(userId); } - @ApiOperation("充值") + @Operation( + summary = "用户充值", + description = "用户账户余额充值", + parameters = { + @Parameter( + name = "userId", + description = "用户ID", + required = true, + schema = @Schema(type = "integer") + ), + @Parameter( + name = "amount", + description = "充值金额(单位:元)", + required = true, + schema = @Schema(type = "number", format = "double") + ) + } + ) @PostMapping("/recharge") - public Result recharge(@RequestParam("id") Integer userId, - @RequestParam("amount") Double amount){ + public Result recharge(@RequestParam("id") Integer userId, @RequestParam("amount") Double amount) { return userService.userRecharge(userId, amount); } - @ApiOperation("用户补充手机号及邮箱") + @Operation( + summary = "补充联系方式", + description = "用户补充手机号和邮箱信息", + parameters = { + @Parameter( + name = "dto", + description = "联系方式DTO,包含手机号和邮箱", + required = true, + schema = @Schema(implementation = PhoneDTO.class) + ) + } + ) @PostMapping("/phone") - public Result check(@RequestBody PhoneDTO dto){ + public Result check(@RequestBody PhoneDTO dto) { return userService.checkPhone(dto); } - @ApiOperation("获取用户的数量") + @Operation( + summary = "获取用户数量", + description = "获取系统用户总数", + parameters = {} + ) @GetMapping("/num") - public Result num(){ + public Result num() { return userService.useNum(); } - @ApiOperation("获取管理员信息") + @Operation( + summary = "查询管理员信息", + description = "查询管理员列表,支持分页查询", + parameters = { + @Parameter( + name = "dto", + description = "分页查询DTO,包含页码和每页数量", + required = true, + schema = @Schema(implementation = PageDTO.class) + ) + } + ) @PostMapping("/admininfo") - public Result admininfo(@RequestBody PageDTO dto){ + public Result admininfo(@RequestBody PageDTO dto) { return userService.admininfo(dto); } - @ApiOperation("超级管理员添加管理员信息") + @Operation( + summary = "创建管理员", + description = "超级管理员创建新的管理员账号", + parameters = { + @Parameter( + name = "user", + description = "管理员用户对象,包含账号信息", + required = true, + schema = @Schema(implementation = User.class) + ) + } + ) @PostMapping("/create") - public Result create(@RequestBody User user){ + public Result create(@RequestBody User user) { return userService.createAdmin(user); } - @ApiOperation("移除管理员信息") + @Operation( + summary = "移除管理员", + description = "超级管理员移除指定管理员账号", + parameters = { + @Parameter( + name = "userId", + description = "待移除的管理员用户ID", + required = true, + schema = @Schema(type = "integer") + ) + } + ) @GetMapping("/remove") - public Result remove(@RequestParam("userId") Integer userId){ + public Result remove(@RequestParam("userId") Integer userId) { return userService.removeAdmin(userId); } - @ApiOperation("修改账号密码") + @Operation( + summary = "修改密码", + description = "用户修改账号密码", + parameters = { + @Parameter( + name = "dto", + description = "密码修改DTO,包含原密码和新密码", + required = true, + schema = @Schema(implementation = PasswdDTO.class) + ) + } + ) @PostMapping("/passwd") - public Result passwd(@RequestBody PasswdDTO dto){ + public Result passwd(@RequestBody PasswdDTO dto) { return userService.passwd(dto); } - @ApiOperation("用户头像上传") + @Operation( + summary = "上传头像", + description = "用户上传个人头像", + parameters = { + @Parameter( + name = "userId", + description = "用户ID", + required = true, + schema = @Schema(type = "integer") + ), + @Parameter( + name = "image", + description = "头像图片文件(支持JPG、PNG格式)", + required = true, + schema = @Schema(type = "file") + ) + } + ) @PostMapping("/upload") - public Result upload(@RequestParam("id") Integer userId, @RequestParam("image") MultipartFile file){ + public Result upload(@RequestParam("id") Integer userId, @RequestParam("image") MultipartFile file) { return userService.upload(userId, file); } - @ApiOperation("用户信息获取") + + @Operation( + summary = "获取用户信息", + description = "根据用户ID获取详细信息", + parameters = { + @Parameter( + name = "userId", + description = "用户ID", + required = true, + schema = @Schema(type = "integer") + ) + } + ) @GetMapping("/info/{id}") - public Result info(@PathVariable("id") Integer userId){ + public Result info(@PathVariable("id") Integer userId) { return userService.getUserInfo(userId); } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/venue_reservation_service/domain/User.java b/src/main/java/com/example/venue_reservation_service/domain/User.java index b2bbe62..6cfe9cb 100644 --- a/src/main/java/com/example/venue_reservation_service/domain/User.java +++ b/src/main/java/com/example/venue_reservation_service/domain/User.java @@ -62,8 +62,8 @@ public class User implements Serializable { /** * 账号注册时间 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime registerTime; /** @@ -79,8 +79,8 @@ public class User implements Serializable { /** * 用户信息修改时间 */ - @JsonFormat(pattern = "yyyy-MM-dd") - @DateTimeFormat(pattern = "yyyy-MM-dd") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") private LocalDateTime updateTime; /** diff --git a/src/main/java/com/example/venue_reservation_service/dto/AdminDTO.java b/src/main/java/com/example/venue_reservation_service/dto/AdminDTO.java index 8b59cff..890ad9f 100644 --- a/src/main/java/com/example/venue_reservation_service/dto/AdminDTO.java +++ b/src/main/java/com/example/venue_reservation_service/dto/AdminDTO.java @@ -1,11 +1,13 @@ package com.example.venue_reservation_service.dto; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.util.HashMap; import java.util.Map; @Data +@Schema(description = "管理员登录对象") public class AdminDTO { private String account; @@ -14,5 +16,4 @@ public class AdminDTO { private String token; - } diff --git a/src/main/java/com/example/venue_reservation_service/dto/AdminSlot.java b/src/main/java/com/example/venue_reservation_service/dto/AdminSlot.java index 5bd69d6..6f85daa 100644 --- a/src/main/java/com/example/venue_reservation_service/dto/AdminSlot.java +++ b/src/main/java/com/example/venue_reservation_service/dto/AdminSlot.java @@ -2,6 +2,7 @@ package com.example.venue_reservation_service.dto; import com.example.venue_reservation_service.vo.AdminTime; import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; @@ -9,15 +10,20 @@ import java.time.LocalDate; import java.util.List; @Data +@Schema(description = "禁用时间设置对象") public class AdminSlot { + @Schema(description = "用户编号") Integer userId; + @Schema(description = "场地编号") Integer venueId; + @Schema(description = "禁用日期") @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate date; + @Schema(description = "选择的时间段") List