diff --git a/src/main/java/xyz/playedu/api/bus/UserBus.java b/src/main/java/xyz/playedu/api/bus/UserBus.java index e1be817..8dbe2ad 100644 --- a/src/main/java/xyz/playedu/api/bus/UserBus.java +++ b/src/main/java/xyz/playedu/api/bus/UserBus.java @@ -1,11 +1,17 @@ package xyz.playedu.api.bus; +import lombok.SneakyThrows; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; +import xyz.playedu.api.PlayEduFCtx; +import xyz.playedu.api.caches.UserLastLearnTimeCache; import xyz.playedu.api.domain.Course; import xyz.playedu.api.domain.CourseHour; import xyz.playedu.api.domain.User; +import xyz.playedu.api.event.UserLearnCourseUpdateEvent; +import xyz.playedu.api.exception.ServiceException; import xyz.playedu.api.service.CourseService; import xyz.playedu.api.service.UserService; @@ -24,6 +30,12 @@ public class UserBus { @Autowired private UserService userService; + @Autowired + private UserLastLearnTimeCache userLastLearnTimeCache; + + @Autowired + private ApplicationContext ctx; + public boolean canSeeCourse(User user, Course course) { List courseDepIds = courseService.getDepIdsByCourseId(course.getId()); if (courseDepIds == null || courseDepIds.size() == 0) { @@ -36,5 +48,20 @@ public class UserBus { } return CollectionUtils.intersection(courseDepIds, userDepIds).size() > 0; } + + public void userLearnDurationRecord(User user, Course course, CourseHour hour) { + Long curTime = System.currentTimeMillis(); + + // 最近一次学习时间 + Long lastTime = userLastLearnTimeCache.get(PlayEduFCtx.getUserId()); + // 最大周期为10s + if (lastTime == null || curTime - lastTime > 10000) { + lastTime = curTime - 10000; + } + + userLastLearnTimeCache.put(user.getId(), curTime); + + ctx.publishEvent(new UserLearnCourseUpdateEvent(this, user.getId(), course.getId(), hour.getId(), lastTime, curTime)); + } } diff --git a/src/main/java/xyz/playedu/api/caches/UserCanSeeCourseCache.java b/src/main/java/xyz/playedu/api/caches/UserCanSeeCourseCache.java index 7ff4429..193e41d 100644 --- a/src/main/java/xyz/playedu/api/caches/UserCanSeeCourseCache.java +++ b/src/main/java/xyz/playedu/api/caches/UserCanSeeCourseCache.java @@ -25,12 +25,13 @@ public class UserCanSeeCourseCache { public boolean check(User user, Course course, boolean isThrow) throws ServiceException { boolean result; if (RedisUtil.exists(key(user, course))) { - result = "1".equals(RedisUtil.get(key(user, course))); + String cacheResult = (String) RedisUtil.get(key(user, course)); + result = "1".equals(cacheResult); } else { result = userBus.canSeeCourse(user, course); put(user, course, result); } - if (isThrow) { + if (!result && isThrow) { throw new ServiceException("无权限观看"); } return result; diff --git a/src/main/java/xyz/playedu/api/caches/UserLastLearnTimeCache.java b/src/main/java/xyz/playedu/api/caches/UserLastLearnTimeCache.java new file mode 100644 index 0000000..ad9021b --- /dev/null +++ b/src/main/java/xyz/playedu/api/caches/UserLastLearnTimeCache.java @@ -0,0 +1,24 @@ +package xyz.playedu.api.caches; + +import org.springframework.stereotype.Component; +import xyz.playedu.api.util.RedisUtil; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/22 13:57 + */ +@Component +public class UserLastLearnTimeCache { + + private final static String groupName = "user-learn-last-timestamp"; + + private final static int expire = 9500;//9.5s + + public Long get(Integer userId) { + return (Long) RedisUtil.hGet(groupName, userId + ""); + } + + public void put(Integer userId, Long timestamp) { + RedisUtil.hSet(groupName, userId + "", timestamp); + } +} diff --git a/src/main/java/xyz/playedu/api/controller/frontend/HourController.java b/src/main/java/xyz/playedu/api/controller/frontend/HourController.java index 8137dc0..532c787 100644 --- a/src/main/java/xyz/playedu/api/controller/frontend/HourController.java +++ b/src/main/java/xyz/playedu/api/controller/frontend/HourController.java @@ -1,17 +1,16 @@ package xyz.playedu.api.controller.frontend; +import lombok.SneakyThrows; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import xyz.playedu.api.PlayEduFCtx; +import xyz.playedu.api.bus.UserBus; import xyz.playedu.api.caches.CourseCache; import xyz.playedu.api.caches.UserCanSeeCourseCache; import xyz.playedu.api.domain.*; -import xyz.playedu.api.exception.NotFoundException; -import xyz.playedu.api.exception.ServiceException; import xyz.playedu.api.request.frontend.CourseHourRecordRequest; import xyz.playedu.api.service.CourseHourService; -import xyz.playedu.api.service.CourseService; import xyz.playedu.api.service.ResourceService; import xyz.playedu.api.service.UserCourseHourRecordService; import xyz.playedu.api.types.JsonResponse; @@ -26,9 +25,6 @@ import java.util.HashMap; @RequestMapping("/api/v1/course/{courseId}/hour") public class HourController { - @Autowired - private CourseService courseService; - @Autowired private CourseHourService hourService; @@ -39,13 +35,18 @@ public class HourController { private UserCourseHourRecordService userCourseHourRecordService; @Autowired - private UserCanSeeCourseCache userCanSeeCourseCache; + private UserBus userBus; + + // ------- CACHE ---------- + @Autowired + private UserCanSeeCourseCache userCanSeeCourseCache; @Autowired private CourseCache courseCache; @GetMapping("/{id}/play") - public JsonResponse play(@PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) throws NotFoundException, ServiceException { + @SneakyThrows + public JsonResponse play(@PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) { Course course = courseCache.findOrFail(courseId); userCanSeeCourseCache.check(PlayEduFCtx.getUser(), course, true); CourseHour hour = hourService.findOrFail(id, courseId); @@ -60,7 +61,8 @@ public class HourController { } @PostMapping("/{id}/record") - public JsonResponse record(@PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id, @RequestBody @Validated CourseHourRecordRequest req) throws NotFoundException, ServiceException { + @SneakyThrows + public JsonResponse record(@PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id, @RequestBody @Validated CourseHourRecordRequest req) { Integer duration = req.getDuration(); if (duration <= 0) { return JsonResponse.error("duration参数错误"); @@ -79,9 +81,12 @@ public class HourController { } @PostMapping("/{id}/ping") - public JsonResponse ping(@PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) throws NotFoundException, ServiceException { + @SneakyThrows + public JsonResponse ping(@PathVariable(name = "courseId") Integer courseId, @PathVariable(name = "id") Integer id) { Course course = courseCache.findOrFail(courseId); + CourseHour hour = hourService.findOrFail(id, courseId); userCanSeeCourseCache.check(PlayEduFCtx.getUser(), course, true); + userBus.userLearnDurationRecord(PlayEduFCtx.getUser(), course, hour); return JsonResponse.success(); } diff --git a/src/main/java/xyz/playedu/api/domain/UserLearnDurationRecord.java b/src/main/java/xyz/playedu/api/domain/UserLearnDurationRecord.java index 97c7b4c..3e744aa 100644 --- a/src/main/java/xyz/playedu/api/domain/UserLearnDurationRecord.java +++ b/src/main/java/xyz/playedu/api/domain/UserLearnDurationRecord.java @@ -6,8 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; import java.util.Date; - -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; /** @@ -26,13 +24,12 @@ public class UserLearnDurationRecord implements Serializable { /** * */ - @JsonProperty("user_id") private Integer userId; /** * */ - private Date date; + private Date createdDate; /** * 已学习时长[微秒] @@ -42,15 +39,23 @@ public class UserLearnDurationRecord implements Serializable { /** * 开始时间 */ - @JsonProperty("start_at") private Date startAt; /** * 结束时间 */ - @JsonProperty("end_at") private Date endAt; + /** + * + */ + private Integer courseId; + + /** + * + */ + private Integer hourId; + @TableField(exist = false) private static final long serialVersionUID = 1L; @@ -68,10 +73,12 @@ public class UserLearnDurationRecord implements Serializable { UserLearnDurationRecord other = (UserLearnDurationRecord) that; return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId())) - && (this.getDate() == null ? other.getDate() == null : this.getDate().equals(other.getDate())) + && (this.getCreatedDate() == null ? other.getCreatedDate() == null : this.getCreatedDate().equals(other.getCreatedDate())) && (this.getDuration() == null ? other.getDuration() == null : this.getDuration().equals(other.getDuration())) && (this.getStartAt() == null ? other.getStartAt() == null : this.getStartAt().equals(other.getStartAt())) - && (this.getEndAt() == null ? other.getEndAt() == null : this.getEndAt().equals(other.getEndAt())); + && (this.getEndAt() == null ? other.getEndAt() == null : this.getEndAt().equals(other.getEndAt())) + && (this.getCourseId() == null ? other.getCourseId() == null : this.getCourseId().equals(other.getCourseId())) + && (this.getHourId() == null ? other.getHourId() == null : this.getHourId().equals(other.getHourId())); } @Override @@ -80,10 +87,12 @@ public class UserLearnDurationRecord implements Serializable { int result = 1; result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); - result = prime * result + ((getDate() == null) ? 0 : getDate().hashCode()); + result = prime * result + ((getCreatedDate() == null) ? 0 : getCreatedDate().hashCode()); result = prime * result + ((getDuration() == null) ? 0 : getDuration().hashCode()); result = prime * result + ((getStartAt() == null) ? 0 : getStartAt().hashCode()); result = prime * result + ((getEndAt() == null) ? 0 : getEndAt().hashCode()); + result = prime * result + ((getCourseId() == null) ? 0 : getCourseId().hashCode()); + result = prime * result + ((getHourId() == null) ? 0 : getHourId().hashCode()); return result; } @@ -95,10 +104,12 @@ public class UserLearnDurationRecord implements Serializable { sb.append("Hash = ").append(hashCode()); sb.append(", id=").append(id); sb.append(", userId=").append(userId); - sb.append(", date=").append(date); + sb.append(", createdDate=").append(createdDate); sb.append(", duration=").append(duration); sb.append(", startAt=").append(startAt); sb.append(", endAt=").append(endAt); + sb.append(", courseId=").append(courseId); + sb.append(", hourId=").append(hourId); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); return sb.toString(); diff --git a/src/main/java/xyz/playedu/api/domain/UserLearnDurationStats.java b/src/main/java/xyz/playedu/api/domain/UserLearnDurationStats.java new file mode 100644 index 0000000..cd3e9e5 --- /dev/null +++ b/src/main/java/xyz/playedu/api/domain/UserLearnDurationStats.java @@ -0,0 +1,85 @@ +package xyz.playedu.api.domain; + +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.util.Date; +import lombok.Data; + +/** + * + * @TableName user_learn_duration_stats + */ +@TableName(value ="user_learn_duration_stats") +@Data +public class UserLearnDurationStats implements Serializable { + /** + * + */ + @TableId(type = IdType.AUTO) + private Integer id; + + /** + * + */ + private Integer userId; + + /** + * + */ + private Integer duration; + + /** + * + */ + private Date createdDate; + + @TableField(exist = false) + private static final long serialVersionUID = 1L; + + @Override + public boolean equals(Object that) { + if (this == that) { + return true; + } + if (that == null) { + return false; + } + if (getClass() != that.getClass()) { + return false; + } + UserLearnDurationStats other = (UserLearnDurationStats) that; + return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) + && (this.getUserId() == null ? other.getUserId() == null : this.getUserId().equals(other.getUserId())) + && (this.getDuration() == null ? other.getDuration() == null : this.getDuration().equals(other.getDuration())) + && (this.getCreatedDate() == null ? other.getCreatedDate() == null : this.getCreatedDate().equals(other.getCreatedDate())); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); + result = prime * result + ((getUserId() == null) ? 0 : getUserId().hashCode()); + result = prime * result + ((getDuration() == null) ? 0 : getDuration().hashCode()); + result = prime * result + ((getCreatedDate() == null) ? 0 : getCreatedDate().hashCode()); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(getClass().getSimpleName()); + sb.append(" ["); + sb.append("Hash = ").append(hashCode()); + sb.append(", id=").append(id); + sb.append(", userId=").append(userId); + sb.append(", duration=").append(duration); + sb.append(", createdDate=").append(createdDate); + sb.append(", serialVersionUID=").append(serialVersionUID); + sb.append("]"); + return sb.toString(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/playedu/api/event/UserLearnCourseUpdateEvent.java b/src/main/java/xyz/playedu/api/event/UserLearnCourseUpdateEvent.java new file mode 100644 index 0000000..da49aa0 --- /dev/null +++ b/src/main/java/xyz/playedu/api/event/UserLearnCourseUpdateEvent.java @@ -0,0 +1,31 @@ +package xyz.playedu.api.event; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.context.ApplicationEvent; + +import java.util.Date; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/22 14:14 + */ +@Setter +@Getter +public class UserLearnCourseUpdateEvent extends ApplicationEvent { + + private Integer userId; + private Integer courseId; + private Integer hourId; + private Long startAt; + private Long endAt; + + public UserLearnCourseUpdateEvent(Object source, Integer userId, Integer courseId, Integer hourId, Long startTime, Long endTime) { + super(source); + this.userId = userId; + this.courseId = courseId; + this.hourId = hourId; + this.startAt = startTime; + this.endAt = endTime; + } +} diff --git a/src/main/java/xyz/playedu/api/listener/UserLearnCourseUpdateListener.java b/src/main/java/xyz/playedu/api/listener/UserLearnCourseUpdateListener.java new file mode 100644 index 0000000..a697c13 --- /dev/null +++ b/src/main/java/xyz/playedu/api/listener/UserLearnCourseUpdateListener.java @@ -0,0 +1,35 @@ +package xyz.playedu.api.listener; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Component; +import xyz.playedu.api.event.UserLearnCourseUpdateEvent; +import xyz.playedu.api.service.UserLearnDurationRecordService; +import xyz.playedu.api.service.UserLearnDurationStatsService; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/22 14:18 + */ +@Component +@Slf4j +public class UserLearnCourseUpdateListener { + + @Autowired + private UserLearnDurationRecordService userLearnDurationRecordService; + + @Autowired + private UserLearnDurationStatsService userLearnDurationStatsService; + + @Async + @EventListener + public void storeLearnDuration(UserLearnCourseUpdateEvent event) { + // 观看时长统计 + userLearnDurationStatsService.storeOrUpdate(event.getUserId(), event.getStartAt(), event.getEndAt()); + // 观看记录 + userLearnDurationRecordService.store(event.getUserId(), event.getCourseId(), event.getHourId(), event.getStartAt(), event.getEndAt()); + } + +} diff --git a/src/main/java/xyz/playedu/api/mapper/UserLearnDurationRecordMapper.java b/src/main/java/xyz/playedu/api/mapper/UserLearnDurationRecordMapper.java index 13ebbfb..290c9ff 100644 --- a/src/main/java/xyz/playedu/api/mapper/UserLearnDurationRecordMapper.java +++ b/src/main/java/xyz/playedu/api/mapper/UserLearnDurationRecordMapper.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * @author tengteng * @description 针对表【user_learn_duration_records】的数据库操作Mapper -* @createDate 2023-03-20 16:41:12 +* @createDate 2023-03-22 13:55:17 * @Entity xyz.playedu.api.domain.UserLearnDurationRecord */ @Mapper diff --git a/src/main/java/xyz/playedu/api/mapper/UserLearnDurationStatsMapper.java b/src/main/java/xyz/playedu/api/mapper/UserLearnDurationStatsMapper.java new file mode 100644 index 0000000..4fbb241 --- /dev/null +++ b/src/main/java/xyz/playedu/api/mapper/UserLearnDurationStatsMapper.java @@ -0,0 +1,20 @@ +package xyz.playedu.api.mapper; + +import org.apache.ibatis.annotations.Mapper; +import xyz.playedu.api.domain.UserLearnDurationStats; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author tengteng +* @description 针对表【user_learn_duration_stats】的数据库操作Mapper +* @createDate 2023-03-22 13:55:29 +* @Entity xyz.playedu.api.domain.UserLearnDurationStats +*/ +@Mapper +public interface UserLearnDurationStatsMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/xyz/playedu/api/service/UserLearnDurationRecordService.java b/src/main/java/xyz/playedu/api/service/UserLearnDurationRecordService.java index be2fa8b..2750cfb 100644 --- a/src/main/java/xyz/playedu/api/service/UserLearnDurationRecordService.java +++ b/src/main/java/xyz/playedu/api/service/UserLearnDurationRecordService.java @@ -4,10 +4,10 @@ import xyz.playedu.api.domain.UserLearnDurationRecord; import com.baomidou.mybatisplus.extension.service.IService; /** -* @author tengteng -* @description 针对表【user_learn_duration_records】的数据库操作Service -* @createDate 2023-03-20 16:41:12 -*/ + * @author tengteng + * @description 针对表【user_learn_duration_records】的数据库操作Service + * @createDate 2023-03-20 16:41:12 + */ public interface UserLearnDurationRecordService extends IService { - + void store(Integer userId, Integer courseId, Integer hourId, Long startTime, Long endTime); } diff --git a/src/main/java/xyz/playedu/api/service/UserLearnDurationStatsService.java b/src/main/java/xyz/playedu/api/service/UserLearnDurationStatsService.java new file mode 100644 index 0000000..8415f92 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/UserLearnDurationStatsService.java @@ -0,0 +1,13 @@ +package xyz.playedu.api.service; + +import xyz.playedu.api.domain.UserLearnDurationStats; +import com.baomidou.mybatisplus.extension.service.IService; + +/** + * @author tengteng + * @description 针对表【user_learn_duration_stats】的数据库操作Service + * @createDate 2023-03-22 13:55:29 + */ +public interface UserLearnDurationStatsService extends IService { + void storeOrUpdate(Integer userId, Long startTime, Long endTime); +} diff --git a/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationRecordServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationRecordServiceImpl.java index 718b7f0..64343e4 100644 --- a/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationRecordServiceImpl.java +++ b/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationRecordServiceImpl.java @@ -1,20 +1,42 @@ package xyz.playedu.api.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.SneakyThrows; import xyz.playedu.api.domain.UserLearnDurationRecord; import xyz.playedu.api.service.UserLearnDurationRecordService; import xyz.playedu.api.mapper.UserLearnDurationRecordMapper; import org.springframework.stereotype.Service; +import java.text.SimpleDateFormat; +import java.util.Date; + /** -* @author tengteng -* @description 针对表【user_learn_duration_records】的数据库操作Service实现 -* @createDate 2023-03-20 16:41:12 -*/ + * @author tengteng + * @description 针对表【user_learn_duration_records】的数据库操作Service实现 + * @createDate 2023-03-20 16:41:12 + */ @Service public class UserLearnDurationRecordServiceImpl extends ServiceImpl - implements UserLearnDurationRecordService{ + implements UserLearnDurationRecordService { + @Override + @SneakyThrows + public void store(Integer userId, Integer courseId, Integer hourId, Long startTime, Long endTime) { + // 处理日期 + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String date = simpleDateFormat.format(new Date(endTime)); + + UserLearnDurationRecord record = new UserLearnDurationRecord(); + record.setUserId(userId); + record.setCourseId(courseId); + record.setHourId(hourId); + record.setStartAt(new Date(startTime)); + record.setEndAt(new Date(endTime)); + record.setDuration((int) (endTime - startTime)); + record.setCreatedDate(simpleDateFormat.parse(date)); + + save(record); + } } diff --git a/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationStatsServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationStatsServiceImpl.java new file mode 100644 index 0000000..a143811 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/impl/UserLearnDurationStatsServiceImpl.java @@ -0,0 +1,50 @@ +package xyz.playedu.api.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.SneakyThrows; +import xyz.playedu.api.domain.UserLearnDurationStats; +import xyz.playedu.api.service.UserLearnDurationStatsService; +import xyz.playedu.api.mapper.UserLearnDurationStatsMapper; +import org.springframework.stereotype.Service; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author tengteng + * @description 针对表【user_learn_duration_stats】的数据库操作Service实现 + * @createDate 2023-03-22 13:55:29 + */ +@Service +public class UserLearnDurationStatsServiceImpl extends ServiceImpl + implements UserLearnDurationStatsService { + + @Override + @SneakyThrows + public void storeOrUpdate(Integer userId, Long startTime, Long endTime) { + // 处理日期 + SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); + String date = simpleDateFormat.format(new Date(endTime)); + // duration + Long duration = endTime - startTime; + + UserLearnDurationStats stats = getOne(query().getWrapper().eq("user_id", userId).eq("created_date", date)); + if (stats == null) { + UserLearnDurationStats newStats = new UserLearnDurationStats(); + newStats.setUserId(userId); + newStats.setDuration(Math.toIntExact(duration)); + newStats.setCreatedDate(simpleDateFormat.parse(date)); + save(newStats); + return; + } + + UserLearnDurationStats newStats = new UserLearnDurationStats(); + newStats.setId(stats.getId()); + newStats.setDuration((int) (stats.getDuration() + duration)); + updateById(newStats); + } +} + + + + diff --git a/src/main/resources/mapper/UserLearnDurationRecordMapper.xml b/src/main/resources/mapper/UserLearnDurationRecordMapper.xml index 8d3c788..368218e 100644 --- a/src/main/resources/mapper/UserLearnDurationRecordMapper.xml +++ b/src/main/resources/mapper/UserLearnDurationRecordMapper.xml @@ -7,14 +7,17 @@ - + + + - id,user_id,date, - duration,start_at,end_at + id,user_id,created_date, + duration,start_at,end_at, + course_id,hour_id diff --git a/src/main/resources/mapper/UserLearnDurationStatsMapper.xml b/src/main/resources/mapper/UserLearnDurationStatsMapper.xml new file mode 100644 index 0000000..b758dfd --- /dev/null +++ b/src/main/resources/mapper/UserLearnDurationStatsMapper.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + id,user_id,duration, + created_date + +