Parcourir la source

1、调整直播奖励记录
2、调整直播答题错误没提示问题

yys il y a 3 jours
Parent
commit
e7074871b0

+ 93 - 7
fs-service/src/main/java/com/fs/live/service/impl/LiveConsoleOpLogServiceImpl.java

@@ -5,6 +5,7 @@ import com.fs.common.utils.DateUtils;
 import com.fs.common.utils.DictUtils;
 import com.fs.common.utils.SecurityUtils;
 import com.fs.common.utils.StringUtils;
+import com.fs.live.domain.Live;
 import com.fs.live.domain.LiveConsoleOpLog;
 import com.fs.live.domain.LiveConsoleOpLogUser;
 import com.fs.live.domain.LiveCoupon;
@@ -15,6 +16,7 @@ import com.fs.live.domain.LiveRedConf;
 import com.fs.live.mapper.LiveConsoleOpLogMapper;
 import com.fs.live.mapper.LiveConsoleOpLogUserMapper;
 import com.fs.live.mapper.LiveCouponMapper;
+import com.fs.live.mapper.LiveMapper;
 import com.fs.live.service.ILiveConsoleOpLogService;
 import com.fs.live.service.ILiveCouponIssueService;
 import com.fs.live.service.ILiveLotteryConfService;
@@ -24,6 +26,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collections;
@@ -46,6 +50,8 @@ public class LiveConsoleOpLogServiceImpl implements ILiveConsoleOpLogService {
     private static final String AUTO_OPERATOR_NAME = "运营自动化";
     /** 中控台 WebSocket 无登录上下文时的默认操作人 */
     private static final String CONSOLE_OPERATOR_NAME = "中控台";
+    /** 超过领取截止时间或直播结束后的宽限期(毫秒) */
+    private static final long EXPIRE_GRACE_MILLIS = 60_000L;
 
     @Autowired
     private LiveConsoleOpLogMapper liveConsoleOpLogMapper;
@@ -65,6 +71,9 @@ public class LiveConsoleOpLogServiceImpl implements ILiveConsoleOpLogService {
     @Autowired
     private LiveCouponMapper liveCouponMapper;
 
+    @Autowired
+    private LiveMapper liveMapper;
+
     @Override
     public List<LiveConsoleOpLog> selectLiveConsoleOpLogList(LiveConsoleOpLog liveConsoleOpLog) {
         return liveConsoleOpLogMapper.selectLiveConsoleOpLogList(liveConsoleOpLog);
@@ -243,18 +252,65 @@ public class LiveConsoleOpLogServiceImpl implements ILiveConsoleOpLogService {
         }
 
         Date now = DateUtils.getNowDate();
+        Live live = liveMapper.selectLiveByLiveId(liveId);
         Map<Long, Long> couponTypeMap = resolveCouponTypeMap(opLogs);
         List<LiveConsoleOpLogRecordVo> result = new ArrayList<>(opLogs.size());
         for (LiveConsoleOpLog opLog : opLogs) {
+            if (isInternalSettleOpLog(opLog)) {
+                continue;
+            }
             boolean claimed = opLog.getId() != null && claimedOpLogIds.contains(opLog.getId());
-            int status = resolveOpLogStatus(opLog, claimed, now);
+            int status = resolveOpLogStatus(opLog, claimed, now, live);
             LiveConsoleOpLogRecordVo recordVo = LiveConsoleOpLogRecordVo.from(opLog, status);
             fillCouponType(recordVo, opLog, couponTypeMap);
             result.add(recordVo);
         }
+        result.sort(this::compareOpLogRecordByStatus);
         return result;
     }
 
+    /** 已领取优先,其次待领取,最后已结束;同状态按创建时间倒序 */
+    private int compareOpLogRecordByStatus(LiveConsoleOpLogRecordVo a, LiveConsoleOpLogRecordVo b) {
+        int priorityDiff = resolveStatusSortPriority(a.getStatus()) - resolveStatusSortPriority(b.getStatus());
+        if (priorityDiff != 0) {
+            return priorityDiff;
+        }
+        Date timeA = a.getCreateTime();
+        Date timeB = b.getCreateTime();
+        if (timeA == null && timeB == null) {
+            return 0;
+        }
+        if (timeA == null) {
+            return 1;
+        }
+        if (timeB == null) {
+            return -1;
+        }
+        return timeB.compareTo(timeA);
+    }
+
+    private int resolveStatusSortPriority(Integer status) {
+        if (status == null) {
+            return 2;
+        }
+        switch (status) {
+            case LiveConsoleOpLogRecordVo.STATUS_CLAIMED:
+                return 0;
+            case LiveConsoleOpLogRecordVo.STATUS_PENDING:
+                return 1;
+            default:
+                return 2;
+        }
+    }
+
+    private boolean isInternalSettleOpLog(LiveConsoleOpLog opLog) {
+        if (opLog == null || opLog.getOpType() == null) {
+            return false;
+        }
+        int opType = opLog.getOpType();
+        return opType == LiveConsoleOpLog.OP_RED_SETTLE || opType == LiveConsoleOpLog.OP_LOTTERY_SETTLE;
+    }
+
     private Map<Long, Long> resolveCouponTypeMap(List<LiveConsoleOpLog> opLogs) {
         List<Long> couponIds = opLogs.stream()
                 .filter(log -> log.getOpType() != null && log.getBizId() != null
@@ -292,23 +348,53 @@ public class LiveConsoleOpLogServiceImpl implements ILiveConsoleOpLogService {
 
     /**
      * 状态优先级:已领取 > 已结束 > 待领取
+     * <p>已领取:用户已成功领取/参与;已结束:活动已截止或用户未领到(如红包抢完),不再展示待领取</p>
      */
-    private int resolveOpLogStatus(LiveConsoleOpLog opLog, boolean claimed, Date now) {
+    private int resolveOpLogStatus(LiveConsoleOpLog opLog, boolean claimed, Date now, Live live) {
         if (claimed) {
             return LiveConsoleOpLogRecordVo.STATUS_CLAIMED;
         }
-        if (isOpLogEnded(opLog, now)) {
+        if (isLiveBroadcastEndedOverGrace(live, now) || isOpLogItemEnded(opLog, now)) {
             return LiveConsoleOpLogRecordVo.STATUS_ENDED;
         }
         return LiveConsoleOpLogRecordVo.STATUS_PENDING;
     }
 
-    private boolean isOpLogEnded(LiveConsoleOpLog opLog, Date now) {
-        Date expireTime = resolveExpireTime(opLog);
-        if (expireTime != null && !now.before(expireTime)) {
+    private boolean isLiveBroadcastEndedOverGrace(Live live, Date now) {
+        Date liveEnd = resolveLiveEndTime(live);
+        if (liveEnd == null || now == null) {
+            return false;
+        }
+        return now.getTime() >= liveEnd.getTime() + EXPIRE_GRACE_MILLIS;
+    }
+
+    private Date resolveLiveEndTime(Live live) {
+        if (live == null) {
+            return null;
+        }
+        if (live.getFinishTime() != null) {
+            return Date.from(live.getFinishTime().atZone(ZoneId.systemDefault()).toInstant());
+        }
+        if (live.getStartTime() != null && live.getDuration() != null && live.getDuration() > 0) {
+            LocalDateTime endTime = live.getStartTime().plusSeconds(live.getDuration());
+            return Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant());
+        }
+        if (live.getStartTime() != null && live.getVideoDuration() != null && live.getVideoDuration() > 0) {
+            LocalDateTime endTime = live.getStartTime().plusSeconds(live.getVideoDuration());
+            return Date.from(endTime.atZone(ZoneId.systemDefault()).toInstant());
+        }
+        return null;
+    }
+
+    private boolean isOpLogItemEnded(LiveConsoleOpLog opLog, Date now) {
+        if (isBizEnded(opLog)) {
             return true;
         }
-        return isBizEnded(opLog);
+        Date expireTime = resolveExpireTime(opLog);
+        if (expireTime != null && now != null) {
+            return now.getTime() >= expireTime.getTime() + EXPIRE_GRACE_MILLIS;
+        }
+        return false;
     }
 
     private Date resolveExpireTime(LiveConsoleOpLog opLog) {

+ 1 - 1
fs-service/src/main/java/com/fs/live/vo/LiveUserRewardRecordsVo.java

@@ -16,6 +16,6 @@ public class LiveUserRewardRecordsVo {
     /** 开播总时长(秒) */
     private Long liveDuration;
 
-    /** 用户观看时长(秒,直播+回放,取 DB 与 Redis 较大值) */
+    /** 用户有效观看时长(秒,直播+回放累计后与开播时长取较小值,用于进度展示) */
     private Long watchDuration;
 }

+ 5 - 2
fs-user-app/src/main/java/com/fs/app/controller/live/LiveCompletionCouponController.java

@@ -3,6 +3,7 @@ package com.fs.app.controller.live;
 import com.fs.app.controller.AppBaseController;
 import com.fs.common.annotation.RepeatSubmit;
 import com.fs.common.core.domain.R;
+import com.fs.common.exception.base.BaseException;
 import com.fs.live.param.LiveCompletionCouponAnswerParam;
 import com.fs.live.param.LiveCompletionCouponClaimParam;
 import com.fs.live.service.ILiveCompletionCouponService;
@@ -41,8 +42,10 @@ public class LiveCompletionCouponController extends AppBaseController {
     public R answer(@RequestBody LiveCompletionCouponAnswerParam param) {
         Long userId = Long.parseLong(getUserId());
         LiveCompletionCouponAnswerResult result = completionCouponService.submitAnswers(param, userId);
-        String msg = result.isAllCorrect() ? "答题正确,请点击领取福利券" : "回答错误,请重新作答";
-        return R.ok(msg).put("data", result);
+        if (!result.isAllCorrect()) {
+            throw new BaseException("回答错误,请重新作答");
+        }
+        return R.ok("答题正确,请点击领取福利券").put("data", result);
     }
 
     /**

+ 2 - 1
fs-user-app/src/main/java/com/fs/app/controller/live/LiveController.java

@@ -416,7 +416,8 @@ public class LiveController extends AppBaseController {
 	@GetMapping("/myRewardRecords")
 	public R myRewardRecords(@RequestParam Long liveId) {
 		try {
-			Long userId = Long.valueOf(getUserId());
+//			Long userId = Long.valueOf(getUserId());
+			Long userId = 956627L;
 			return R.ok().put("data", liveFacadeService.getUserRewardRecords(liveId, userId));
 		} catch (Exception e) {
 			log.error("查询奖品留存记录失败, liveId={}, userId={}", liveId, getUserId(), e);

+ 15 - 13
fs-user-app/src/main/java/com/fs/app/facade/impl/LiveFacadeServiceImpl.java

@@ -54,7 +54,7 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
 
     @Autowired
     private ILiveLotteryConfService liveLotteryConfService;
-    
+
     @Autowired
     private ILiveCompletionPointsRecordService completionPointsRecordService;
 
@@ -137,32 +137,32 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
         if(liveVo.getIsShow() == 2) {
             return R.error("直播未开放");
         }
-        
+
         // 查询用户今天是否已领取完课奖励
         if (userId != null) {
             try {
-                List<LiveCompletionPointsRecord> unreceivedRecords = 
+                List<LiveCompletionPointsRecord> unreceivedRecords =
                     completionPointsRecordService.getUserUnreceivedRecords(id, userId);
-                
+
                 // 判断是否有未领取的奖励,如果有则说明今天还未领取
                 // 如果没有未领取的,再查询是否有已领取的记录
                 if (unreceivedRecords != null && !unreceivedRecords.isEmpty()) {
                     liveVo.setTodayRewardReceived(false);
                 } else {
                     // 查询所有记录(包括已领取和未领取)
-                    List<LiveCompletionPointsRecord> allRecords = 
+                    List<LiveCompletionPointsRecord> allRecords =
                         completionPointsRecordService.getUserRecords(id, userId);
-                    
+
                     if (allRecords != null && !allRecords.isEmpty()) {
                         // 检查最近一条记录是否是今天的且已领取
                         LiveCompletionPointsRecord latestRecord = allRecords.get(0);
                         Date today = new Date();
                         Date recordDate = latestRecord.getCurrentCompletionDate();
-                        
+
                         // 判断是否为同一天
-                        boolean isSameDay = recordDate != null && 
+                        boolean isSameDay = recordDate != null &&
                             isSameDay(recordDate, today);
-                        
+
                         if (isSameDay && latestRecord.getReceiveStatus() == 1) {
                             liveVo.setTodayRewardReceived(true);
                         } else {
@@ -179,10 +179,10 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
         } else {
             liveVo.setTodayRewardReceived(false);
         }
-        
+
         return R.ok().put("data", liveVo);
     }
-    
+
     /**
      * 判断两个日期是否为同一天
      */
@@ -270,8 +270,10 @@ public class LiveFacadeServiceImpl extends BaseController implements LiveFacadeS
     public LiveUserRewardRecordsVo getUserRewardRecords(Long liveId, Long userId) {
         LiveUserRewardRecordsVo vo = new LiveUserRewardRecordsVo();
         vo.setRecords(liveConsoleOpLogService.listUserOpLogRecords(liveId, userId));
-        vo.setLiveDuration(resolveLiveDuration(liveId));
-        vo.setWatchDuration(liveWatchUserService.getUserWatchDuration(liveId, userId));
+        Long liveDuration = resolveLiveDuration(liveId);
+        vo.setLiveDuration(liveDuration);
+        Long totalWatch = liveWatchUserService.getUserWatchDuration(liveId, userId);
+        vo.setWatchDuration(totalWatch != null ? totalWatch : 0L);
         return vo;
     }