From e20439c98f771bb939e0ca4362a145d38e440e8d Mon Sep 17 00:00:00 2001 From: guo <1716967236@qq.com> Date: Sun, 18 Aug 2024 19:45:16 +0800 Subject: [PATCH] =?UTF-8?q?1.=20=E5=BC=80=E5=A7=8B=E6=88=96=E7=BB=A7?= =?UTF-8?q?=E7=BB=AD=E4=B8=80=E4=B8=AA=E3=80=90=E5=AD=A6=E4=B9=A0=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E3=80=91API=202.=20=E6=9A=82=E5=81=9C=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E3=80=90=E5=AD=A6=E4=B9=A0=E4=BC=9A=E8=AF=9D=E3=80=91?= =?UTF-8?q?API=203.=E9=80=9A=E8=BF=87sessionId=E8=8E=B7=E5=8F=96=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E3=80=90=E5=AD=A6=E4=B9=A0=E4=BC=9A=E8=AF=9D=E3=80=91?= =?UTF-8?q?API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/StudySessionController.java | 45 ++++++++++++++++ .../controller/TaskController.java | 18 +++++++ .../dto/response/StudySessionResponce.java | 41 ++++++++++++++ .../entity/StudySessionsEntity.java | 54 +++++++++++++++++-- .../enums/StudySessionStateEnum.java | 17 ++++++ .../exception/ErrorParameterException.java | 3 +- .../mapStruct/StudySessionConvert.java | 15 ++++++ .../impl/StudySessionsServiceImpl.java | 35 +++++++++++- 8 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/guo/learningprogresstracker/dto/response/StudySessionResponce.java create mode 100644 src/main/java/com/guo/learningprogresstracker/enums/StudySessionStateEnum.java create mode 100644 src/main/java/com/guo/learningprogresstracker/mapStruct/StudySessionConvert.java diff --git a/src/main/java/com/guo/learningprogresstracker/controller/StudySessionController.java b/src/main/java/com/guo/learningprogresstracker/controller/StudySessionController.java index af80476..34a8a52 100644 --- a/src/main/java/com/guo/learningprogresstracker/controller/StudySessionController.java +++ b/src/main/java/com/guo/learningprogresstracker/controller/StudySessionController.java @@ -1,9 +1,54 @@ package com.guo.learningprogresstracker.controller; +import com.guo.learningprogresstracker.dto.response.StudySessionResponce; +import com.guo.learningprogresstracker.entity.CommonResult; +import com.guo.learningprogresstracker.entity.StudySessionsEntity; +import com.guo.learningprogresstracker.exception.ErrorParameterException; +import com.guo.learningprogresstracker.mapStruct.StudySessionConvert; +import com.guo.learningprogresstracker.service.impl.StudySessionsServiceImpl; +import jakarta.validation.constraints.NotEmpty; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +/** + * 学习会话控制层 + */ +@RequestMapping("/study-sessions") @RestController +@RequiredArgsConstructor +@Validated public class StudySessionController { + private final StudySessionsServiceImpl studySessionsServiceImpl; + + @PostMapping + public void studySessionList() { + + } + + /** + * 通过sessionId获取一个【学习会话】 + */ + @GetMapping("/{sessionId}") + public CommonResult getStudySession(@NotEmpty(message = "sessionId不可为空") @PathVariable String sessionId) throws ErrorParameterException { + StudySessionsEntity studySessionsEntity = studySessionsServiceImpl.getOptById(sessionId) + .orElseThrow(() -> new ErrorParameterException("会话[" + sessionId + "]不存在")); + StudySessionResponce studySessionResponce = StudySessionConvert.MAPPER.toStudySessionResponce(studySessionsEntity); + return CommonResult.success(studySessionResponce); + } + + /** + * 暂停一个【学习会话】 + */ + @PostMapping("/{taskId}/studay-sessions/pause") + public CommonResult pauseStudySession(@PathVariable("sessionId") String sessionId) throws ErrorParameterException { + studySessionsServiceImpl.pauseStudySession(sessionId); + return CommonResult.success(); + } } diff --git a/src/main/java/com/guo/learningprogresstracker/controller/TaskController.java b/src/main/java/com/guo/learningprogresstracker/controller/TaskController.java index de0f5c4..7132fae 100644 --- a/src/main/java/com/guo/learningprogresstracker/controller/TaskController.java +++ b/src/main/java/com/guo/learningprogresstracker/controller/TaskController.java @@ -2,10 +2,13 @@ package com.guo.learningprogresstracker.controller; import cn.dev33.satoken.stp.StpUtil; import com.guo.learningprogresstracker.common.Ops; +import com.guo.learningprogresstracker.dto.response.StudySessionResponce; import com.guo.learningprogresstracker.entity.CommonResult; import com.guo.learningprogresstracker.dto.request.TaskRequest; import com.guo.learningprogresstracker.service.TasksService; +import com.guo.learningprogresstracker.service.impl.StudySessionsServiceImpl; import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.constraints.NotEmpty; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; @@ -29,6 +32,8 @@ public class TaskController { private final TasksService tasksService; + private final StudySessionsServiceImpl studySessionsServiceImpl; + @PostMapping("/tasks") @Operation(summary = "添加新任务") public CommonResult addTask(@RequestBody @Validated({Ops.CreateG.class}) TaskRequest taskRequest) { @@ -61,4 +66,17 @@ public class TaskController { public CommonResult tasksList() { return CommonResult.success(tasksService.taskList()); } + + /** + * 开始或继续一个【学习会话】 + * + */ + @GetMapping("/{taskId}/studay-sessions/start-or-continue") + public CommonResult startOrContinueStudySession(@NotEmpty(message = "taskId不可为空") + @PathVariable String taskId) { + StudySessionResponce responce = studySessionsServiceImpl.startOrContinueStudySession(taskId); + return CommonResult.success(responce); + + } + } diff --git a/src/main/java/com/guo/learningprogresstracker/dto/response/StudySessionResponce.java b/src/main/java/com/guo/learningprogresstracker/dto/response/StudySessionResponce.java new file mode 100644 index 0000000..d7a8e02 --- /dev/null +++ b/src/main/java/com/guo/learningprogresstracker/dto/response/StudySessionResponce.java @@ -0,0 +1,41 @@ +package com.guo.learningprogresstracker.dto.response; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class StudySessionResponce { + + private Integer sessionId; + + private Integer taskId; + + + @Schema(description = "学习开始时间") + private LocalDateTime startTime; + + @Schema(description = "上次本会话开始时间") + private LocalDateTime lastStartTime; + + + @Schema(description = "学习结束时间") + private LocalDateTime endTime; + + + @Schema(description = "实际使用时间(分钟)") + private Integer actualTime; + + + @Schema(description = "有效学习时间(分钟)") + private Integer effectiveTime; + + + @Schema(description = "有效时间比") + private Double effectivenessRatio; + + + @Schema(description = "学习会话的状态(进行中、暂停、已结束)") + private String sessionState; +} diff --git a/src/main/java/com/guo/learningprogresstracker/entity/StudySessionsEntity.java b/src/main/java/com/guo/learningprogresstracker/entity/StudySessionsEntity.java index 03c464a..b27afc2 100644 --- a/src/main/java/com/guo/learningprogresstracker/entity/StudySessionsEntity.java +++ b/src/main/java/com/guo/learningprogresstracker/entity/StudySessionsEntity.java @@ -4,20 +4,23 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import java.io.Serializable; -import java.time.LocalDateTime; +import com.guo.learningprogresstracker.enums.StudySessionStateEnum; import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +import java.io.Serializable; +import java.time.Duration; +import java.time.LocalDateTime; /** * 记录每次学习会话的具体数据 * @TableName study_sessions */ @TableName(value ="study_sessions") +@Slf4j @Data public class StudySessionsEntity extends BaseEntity implements Serializable { - /** - * - */ + @TableId(value = "session_id", type = IdType.AUTO) private Integer sessionId; @@ -33,6 +36,9 @@ public class StudySessionsEntity extends BaseEntity implements Serializable { @TableField(value = "start_time") private LocalDateTime startTime; + @TableField(value = "last_start_time") + private LocalDateTime lastStartTime; + /** * 学习结束时间 */ @@ -66,4 +72,42 @@ public class StudySessionsEntity extends BaseEntity implements Serializable { @TableField(exist = false) private static final long serialVersionUID = 1L; + + /** + * 初始化新会话 + * @return + */ + public static StudySessionsEntity initNewSession(){ + StudySessionsEntity studySessionsEntity = new StudySessionsEntity(); + studySessionsEntity.setStartTime(LocalDateTime.now()); + studySessionsEntity.setLastModifiedTime(LocalDateTime.now()); + studySessionsEntity.setSessionState(StudySessionStateEnum.ONGOING.name()); + return studySessionsEntity; + } + + /** + * 继续会话 + */ + public void continueStudySession(){ + if (this.getSessionState().equals(StudySessionStateEnum.PAUSED.name())){ + this.setSessionState(StudySessionStateEnum.ONGOING.name()); + this.setLastStartTime(LocalDateTime.now()); + }else{ + log.warn("不应出现的情况:开始了一个状态为【{}】的学习会话",this.getSessionState()); + } + } + + /** + * 暂停会话 + */ + public void pausedStudySession(){ + if (this.getSessionState().equals(StudySessionStateEnum.PAUSED.name())){ + // + }else { + this.setEndTime(LocalDateTime.now()); + this.setEffectiveTime((int) Duration.between(this.lastStartTime,this.endTime).toMinutes()); + this.setActualTime((int) Duration.between(this.endTime,this.startTime).toMinutes()); + this.setSessionState(StudySessionStateEnum.PAUSED.name()); + } + } } \ No newline at end of file diff --git a/src/main/java/com/guo/learningprogresstracker/enums/StudySessionStateEnum.java b/src/main/java/com/guo/learningprogresstracker/enums/StudySessionStateEnum.java new file mode 100644 index 0000000..22fb086 --- /dev/null +++ b/src/main/java/com/guo/learningprogresstracker/enums/StudySessionStateEnum.java @@ -0,0 +1,17 @@ +package com.guo.learningprogresstracker.enums; + +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public enum StudySessionStateEnum { + ONGOING("进行中"), + PAUSED("暂停"), + ENDED("已结束"); + + private final String description; + + public String getDescription() { + return this.description; + } + +} diff --git a/src/main/java/com/guo/learningprogresstracker/exception/ErrorParameterException.java b/src/main/java/com/guo/learningprogresstracker/exception/ErrorParameterException.java index aaeba50..0cad1d6 100644 --- a/src/main/java/com/guo/learningprogresstracker/exception/ErrorParameterException.java +++ b/src/main/java/com/guo/learningprogresstracker/exception/ErrorParameterException.java @@ -5,7 +5,8 @@ package com.guo.learningprogresstracker.exception; * * 数据不合法时抛出此错误 * 此错误由GlobalExceptionHandler类统一处理 - * */ + * + * @author guo*/ public class ErrorParameterException extends Exception { public ErrorParameterException(String message){ super(message); diff --git a/src/main/java/com/guo/learningprogresstracker/mapStruct/StudySessionConvert.java b/src/main/java/com/guo/learningprogresstracker/mapStruct/StudySessionConvert.java new file mode 100644 index 0000000..c816a8c --- /dev/null +++ b/src/main/java/com/guo/learningprogresstracker/mapStruct/StudySessionConvert.java @@ -0,0 +1,15 @@ +package com.guo.learningprogresstracker.mapStruct; + +import com.guo.learningprogresstracker.dto.response.StudySessionResponce; +import com.guo.learningprogresstracker.entity.StudySessionsEntity; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; +import org.mapstruct.factory.Mappers; + +@Mapper(componentModel = "spring",unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface StudySessionConvert { + StudySessionConvert MAPPER = Mappers.getMapper(StudySessionConvert.class); + + + StudySessionResponce toStudySessionResponce(StudySessionsEntity studySessionsEntity); +} diff --git a/src/main/java/com/guo/learningprogresstracker/service/impl/StudySessionsServiceImpl.java b/src/main/java/com/guo/learningprogresstracker/service/impl/StudySessionsServiceImpl.java index 8bfb9ab..9c66de2 100644 --- a/src/main/java/com/guo/learningprogresstracker/service/impl/StudySessionsServiceImpl.java +++ b/src/main/java/com/guo/learningprogresstracker/service/impl/StudySessionsServiceImpl.java @@ -1,11 +1,18 @@ package com.guo.learningprogresstracker.service.impl; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.guo.learningprogresstracker.dto.response.StudySessionResponce; import com.guo.learningprogresstracker.entity.StudySessionsEntity; -import com.guo.learningprogresstracker.service.StudySessionsService; +import com.guo.learningprogresstracker.enums.StudySessionStateEnum; +import com.guo.learningprogresstracker.exception.ErrorParameterException; +import com.guo.learningprogresstracker.mapStruct.StudySessionConvert; import com.guo.learningprogresstracker.mapper.StudySessionsMapper; +import com.guo.learningprogresstracker.service.StudySessionsService; import org.springframework.stereotype.Service; +import java.util.Optional; + /** * @author guo * @description 针对表【study_sessions(记录每次学习会话的具体数据)】的数据库操作Service实现 @@ -15,6 +22,32 @@ import org.springframework.stereotype.Service; public class StudySessionsServiceImpl extends ServiceImpl implements StudySessionsService{ + public StudySessionResponce startOrContinueStudySession(String taskId) { + // 任务id下是否存在非”已结束“的学习会话 + Optional oneOpt = this.getOneOpt(Wrappers.lambdaQuery() + .eq(StudySessionsEntity::getTaskId, taskId) + .ne(StudySessionsEntity::getSessionState, StudySessionStateEnum.ENDED.name())); + // 有则返回该未完成会话,否则创建新的会话 + if (oneOpt.isEmpty()) { + // 返回一个新的会话 + StudySessionsEntity studySessionsEntity = StudySessionsEntity.initNewSession(); + this.save(studySessionsEntity); + return StudySessionConvert.MAPPER.toStudySessionResponce(studySessionsEntity); + }else { + // 返回已经存在的会话 + StudySessionsEntity studySessionsEntity = oneOpt.get(); + studySessionsEntity.continueStudySession(); + this.updateById(studySessionsEntity); + return StudySessionConvert.MAPPER.toStudySessionResponce(studySessionsEntity); + } + } + + public void pauseStudySession(String sessionId) throws ErrorParameterException { + StudySessionsEntity studySessionsEntity = this.getOptById(sessionId) + .orElseThrow(() -> new ErrorParameterException("会话[" + sessionId + "]不存在")); + studySessionsEntity.pausedStudySession(); + this.updateById(studySessionsEntity); + } }