|
@@ -1,15 +1,25 @@
|
|
|
package com.fs.app.controller.live;
|
|
package com.fs.app.controller.live;
|
|
|
|
|
|
|
|
import com.fs.app.controller.AppBaseController;
|
|
import com.fs.app.controller.AppBaseController;
|
|
|
|
|
+import com.fs.app.vo.UpdateWatchDurationVO;
|
|
|
import com.fs.common.annotation.RepeatSubmit;
|
|
import com.fs.common.annotation.RepeatSubmit;
|
|
|
import com.fs.common.core.domain.R;
|
|
import com.fs.common.core.domain.R;
|
|
|
import com.fs.his.domain.FsUser;
|
|
import com.fs.his.domain.FsUser;
|
|
|
|
|
+import com.fs.his.service.IFsUserIntegralLogsService;
|
|
|
import com.fs.his.service.IFsUserService;
|
|
import com.fs.his.service.IFsUserService;
|
|
|
|
|
+import com.fs.live.domain.Live;
|
|
|
import com.fs.live.domain.LiveCompletionPointsRecord;
|
|
import com.fs.live.domain.LiveCompletionPointsRecord;
|
|
|
|
|
+import com.fs.live.mapper.LiveCompletionPointsRecordMapper;
|
|
|
import com.fs.live.service.ILiveCompletionPointsRecordService;
|
|
import com.fs.live.service.ILiveCompletionPointsRecordService;
|
|
|
|
|
+import com.fs.live.service.ILiveService;
|
|
|
|
|
+import org.redisson.api.RedissonClient;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
|
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.time.LocalDateTime;
|
|
|
|
|
+import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
@@ -27,6 +37,18 @@ public class LiveCompletionPointsController extends AppBaseController {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private IFsUserService fsUserService;
|
|
private IFsUserService fsUserService;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private ILiveService liveService;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private IFsUserIntegralLogsService fsUserIntegralLogsService;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private LiveCompletionPointsRecordMapper completionPointsRecordMapper;
|
|
|
|
|
+
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private RedissonClient redissonClient;
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 领取完课积分
|
|
* 领取完课积分
|
|
|
*/
|
|
*/
|
|
@@ -64,20 +86,20 @@ public class LiveCompletionPointsController extends AppBaseController {
|
|
|
@GetMapping("/info")
|
|
@GetMapping("/info")
|
|
|
public R getInfo(@RequestParam Long liveId) {
|
|
public R getInfo(@RequestParam Long liveId) {
|
|
|
Long userId = Long.parseLong(getUserId());
|
|
Long userId = Long.parseLong(getUserId());
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 1. 获取用户积分余额
|
|
// 1. 获取用户积分余额
|
|
|
FsUser user = fsUserService.selectFsUserByUserId(userId);
|
|
FsUser user = fsUserService.selectFsUserByUserId(userId);
|
|
|
Long integral = user != null && user.getIntegral() != null ? user.getIntegral() : 0L;
|
|
Long integral = user != null && user.getIntegral() != null ? user.getIntegral() : 0L;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 2. 获取完课记录列表(包含已领取和未领取)
|
|
// 2. 获取完课记录列表(包含已领取和未领取)
|
|
|
List<LiveCompletionPointsRecord> records = completionPointsRecordService.getUserRecords(liveId, userId);
|
|
List<LiveCompletionPointsRecord> records = completionPointsRecordService.getUserRecords(liveId, userId);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 3. 统计信息
|
|
// 3. 统计信息
|
|
|
long totalPoints = records.stream()
|
|
long totalPoints = records.stream()
|
|
|
.filter(r -> r.getReceiveStatus() == 1)
|
|
.filter(r -> r.getReceiveStatus() == 1)
|
|
|
.mapToLong(LiveCompletionPointsRecord::getPointsAwarded)
|
|
.mapToLong(LiveCompletionPointsRecord::getPointsAwarded)
|
|
|
.sum();
|
|
.sum();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
long unreceivedCount = records.stream()
|
|
long unreceivedCount = records.stream()
|
|
|
.filter(r -> r.getReceiveStatus() == 0)
|
|
.filter(r -> r.getReceiveStatus() == 0)
|
|
|
.count();
|
|
.count();
|
|
@@ -88,7 +110,7 @@ public class LiveCompletionPointsController extends AppBaseController {
|
|
|
result.put("totalDays", records.size()); // 累计看直播天数
|
|
result.put("totalDays", records.size()); // 累计看直播天数
|
|
|
result.put("unreceivedCount", unreceivedCount); // 未领取记录数
|
|
result.put("unreceivedCount", unreceivedCount); // 未领取记录数
|
|
|
result.put("records", records); // 完课记录列表
|
|
result.put("records", records); // 完课记录列表
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
return R.ok().put("data", result);
|
|
return R.ok().put("data", result);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -98,7 +120,7 @@ public class LiveCompletionPointsController extends AppBaseController {
|
|
|
@PostMapping("/test/create")
|
|
@PostMapping("/test/create")
|
|
|
public R testCreateRecord(@RequestParam Long liveId, @RequestParam(required = false) Long watchDuration) {
|
|
public R testCreateRecord(@RequestParam Long liveId, @RequestParam(required = false) Long watchDuration) {
|
|
|
Long userId = Long.parseLong(getUserId());
|
|
Long userId = Long.parseLong(getUserId());
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
// 调用完课记录创建方法(watchDuration为null时会自动从数据库累计)
|
|
// 调用完课记录创建方法(watchDuration为null时会自动从数据库累计)
|
|
|
completionPointsRecordService.checkAndCreateCompletionRecord(liveId, userId, watchDuration);
|
|
completionPointsRecordService.checkAndCreateCompletionRecord(liveId, userId, watchDuration);
|
|
@@ -107,4 +129,121 @@ public class LiveCompletionPointsController extends AppBaseController {
|
|
|
return R.error("创建失败: " + e.getMessage());
|
|
return R.error("创建失败: " + e.getMessage());
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 第二个接口:更新用户的看课时长
|
|
|
|
|
+ * POST请求,传入直播间id和看课时长
|
|
|
|
|
+ * 更新用户看课completionPointsRecordService看课记录里面的时长
|
|
|
|
|
+ */
|
|
|
|
|
+ @PostMapping("/update-watch-duration")
|
|
|
|
|
+ @Transactional
|
|
|
|
|
+ public R updateWatchDuration(@RequestParam Long liveId, @RequestParam Long watchDuration) {
|
|
|
|
|
+ Long userId = Long.parseLong(getUserId());
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1. 获取直播间信息
|
|
|
|
|
+ Live live = liveService.selectLiveByLiveId(liveId);
|
|
|
|
|
+ if (live == null) {
|
|
|
|
|
+ return R.error("直播间不存在");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 判断当前时间是否在直播期间(状态为2,直播中)
|
|
|
|
|
+ boolean isLiveInProgress = false;
|
|
|
|
|
+ LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
+
|
|
|
|
|
+ if (live.getStatus() != null && live.getStatus() == 2) {
|
|
|
|
|
+ // status=2 表示直播中
|
|
|
|
|
+ isLiveInProgress = true;
|
|
|
|
|
+ } else if (live.getStartTime() != null && live.getFinishTime() != null) {
|
|
|
|
|
+ // 判断当前时间是否在开播时间和结束时间之间
|
|
|
|
|
+ isLiveInProgress = (now.isAfter(live.getStartTime()) || now.isEqual(live.getStartTime()))
|
|
|
|
|
+ && (now.isBefore(live.getFinishTime()) || now.isEqual(live.getFinishTime()));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!isLiveInProgress) {
|
|
|
|
|
+ return R.error("当前不在直播期间,无法更新看课时长");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 查询当前直播间的完课记录(不限制日期)
|
|
|
|
|
+ LiveCompletionPointsRecord record = completionPointsRecordMapper.selectLatestByUserAndLiveId(liveId, userId);
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 计算看课时长
|
|
|
|
|
+ Date updateTime = null;
|
|
|
|
|
+ if (record != null && record.getUpdateTime() != null) {
|
|
|
|
|
+ updateTime = record.getUpdateTime();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 判断更新时间与直播间开始时间的关系
|
|
|
|
|
+ Date startTime = live.getStartTime() != null
|
|
|
|
|
+ ? java.sql.Timestamp.valueOf(live.getStartTime()) : null;
|
|
|
|
|
+
|
|
|
|
|
+ Date currentTime = new Date();
|
|
|
|
|
+ long timeDiff = 0L;
|
|
|
|
|
+
|
|
|
|
|
+ if (updateTime != null && startTime != null) {
|
|
|
|
|
+ if (updateTime.before(startTime)) {
|
|
|
|
|
+ // 更新时间小于直播间开始时间,使用直播间开始时间进行计算
|
|
|
|
|
+ timeDiff = (currentTime.getTime() - startTime.getTime()) / 1000; // 转换为秒
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 更新时间大于等于开播时间,按照更新时间进行计算
|
|
|
|
|
+ timeDiff = (currentTime.getTime() - updateTime.getTime()) / 1000; // 转换为秒
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (startTime != null) {
|
|
|
|
|
+ // 没有更新记录,使用直播间开始时间计算
|
|
|
|
|
+ timeDiff = (currentTime.getTime() - startTime.getTime()) / 1000; // 转换为秒
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 如果请求传入的时间大于这个时间差,就使用计算出的看课时长,否则使用请求传入的时长
|
|
|
|
|
+ Long finalWatchDuration;
|
|
|
|
|
+ if (watchDuration > timeDiff) {
|
|
|
|
|
+ // 请求传入的时间大于时间差,使用计算出的看课时长
|
|
|
|
|
+ finalWatchDuration = timeDiff;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 否则使用请求传入的时长
|
|
|
|
|
+ finalWatchDuration = watchDuration;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 6. 更新完课记录中的看课时长
|
|
|
|
|
+ if (record == null) {
|
|
|
|
|
+ // 如果没有记录,先创建记录
|
|
|
|
|
+ record = completionPointsRecordService.createCompletionRecord(liveId, userId);
|
|
|
|
|
+ record.setWatchDuration(finalWatchDuration);
|
|
|
|
|
+ completionPointsRecordMapper.updateRecord(record);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 更新现有记录的看课时长
|
|
|
|
|
+ Long currentWatchDuration = record.getWatchDuration() != null
|
|
|
|
|
+ ? record.getWatchDuration() : 0L;
|
|
|
|
|
+ record.setWatchDuration(currentWatchDuration + finalWatchDuration);
|
|
|
|
|
+
|
|
|
|
|
+ // 重新计算完课比例
|
|
|
|
|
+ Long videoDuration = live.getDuration();
|
|
|
|
|
+ if (videoDuration != null && videoDuration > 0) {
|
|
|
|
|
+ BigDecimal completionRate = BigDecimal.valueOf(record.getWatchDuration())
|
|
|
|
|
+ .multiply(BigDecimal.valueOf(100))
|
|
|
|
|
+ .divide(BigDecimal.valueOf(videoDuration), 2, java.math.RoundingMode.HALF_UP);
|
|
|
|
|
+ if (completionRate.compareTo(BigDecimal.valueOf(100)) > 0) {
|
|
|
|
|
+ completionRate = BigDecimal.valueOf(100);
|
|
|
|
|
+ }
|
|
|
|
|
+ record.setCompletionRate(completionRate);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int updateResult = completionPointsRecordMapper.updateRecord(record);
|
|
|
|
|
+ if (updateResult <= 0) {
|
|
|
|
|
+ return R.error("更新看课时间失败");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ UpdateWatchDurationVO vo = new UpdateWatchDurationVO();
|
|
|
|
|
+ vo.setWatchDuration(finalWatchDuration);
|
|
|
|
|
+ vo.setTotalWatchDuration(record != null && record.getWatchDuration() != null
|
|
|
|
|
+ ? record.getWatchDuration() : finalWatchDuration);
|
|
|
|
|
+
|
|
|
|
|
+ return R.ok().put("data", vo);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return R.error("更新失败: " + e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|