Explorar o código

提交代码,签到面板接口

wangzhijun hai 1 día
pai
achega
c758fbbee0

+ 0 - 11
nightFragrance-massage/src/main/java/com/ylx/point/mapper/PointUserSignLogMapper.java

@@ -2,10 +2,6 @@ package com.ylx.point.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ylx.point.domain.PointUserSignLog;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
-
-import java.util.List;
 
 /**
  * 用户签到记录Mapper接口
@@ -14,11 +10,4 @@ import java.util.List;
  * @date 2026-03-25
  */
 public interface PointUserSignLogMapper extends BaseMapper<PointUserSignLog> {
-
-
-    @Select("SELECT COUNT(*) FROM point_user_sign_log " +
-            "WHERE open_id = #{openId} " +
-            "AND task_id = #{taskId} " +
-            "AND sign_date = CURDATE()")
-    int countTodaySign(@Param("openId") String openId, @Param("taskId") Long taskId);
 }

+ 0 - 2
nightFragrance-massage/src/main/java/com/ylx/point/service/IPointUserSignLogService.java

@@ -10,6 +10,4 @@ import com.ylx.point.domain.PointUserSignLog;
  * @date 2026-03-25
  */
 public interface IPointUserSignLogService extends IService<PointUserSignLog> {
-
-    int countTodaySign(String openId, Long taskId);
 }

+ 127 - 75
nightFragrance-massage/src/main/java/com/ylx/point/service/impl/PointActivityServiceImpl.java

@@ -347,100 +347,128 @@ public class PointActivityServiceImpl extends ServiceImpl<PointActivityMapper, P
         Long taskId = task.getId();
         Long activityId = task.getActivityId();
 
-        PointActivity entity = this.pointActivityMapper.selectPointActivityById(activityId);
-        if (ObjectUtil.isNull(entity)) {
+        PointActivity activity = this.pointActivityMapper.selectPointActivityById(activityId);
+        if (ObjectUtil.isNull(activity)) {
             throw new IllegalArgumentException("参数有误,活动不存在");
         }
 
-        Date activityStartTime = entity.getStartTime();
+        // 3. 基础配置
+        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
+        LocalDate today = LocalDate.now(zoneId);
         int basePoints = task.getBasePoints() == null ? 0 : task.getBasePoints();
 
-        // 3. 查询连续签到奖励配置(按continue_days升序,保证累加顺序)
-        LambdaQueryWrapper<PointSignReward> rewardQuery = new LambdaQueryWrapper<>();
-        rewardQuery.eq(PointSignReward::getSignTaskId, taskId)
-                .eq(PointSignReward::getIsDeleted, 0)
-                .orderByAsc(PointSignReward::getContinueDays);
-        List<PointSignReward> rewardList = pointSignRewardService.list(rewardQuery);
+        LocalDate activityStartDate = activity.getStartTime() == null ? null
+                : activity.getStartTime().toInstant().atZone(zoneId).toLocalDate();
+        LocalDate activityEndDate = activity.getEndTime() == null ? null
+                : activity.getEndTime().toInstant().atZone(zoneId).toLocalDate();
+        boolean isPermanent = "1".equals(activity.getIsPermanent());
 
-        // 4. 查询用户签到状态 & 当前连续天数
-        boolean signedToday = pointUserSignLogService.countTodaySign(openId, taskId) > 0;
-        PointUserSignStatus status = pointUserSignStatusService.selectByOpenIdAndActivityIdForUpdate(openId, activityId);
-        int currentContinuousDays = (status == null) ? 0 : status.getCurrentContinuousDays();
+        // 4. 阶梯奖励配置(按 continue_days 升序,满足“累加阶梯奖”)
+        List<PointSignReward> rewardList = pointSignRewardService.list(new LambdaQueryWrapper<PointSignReward>()
+                .eq(PointSignReward::getSignTaskId, taskId)
+                .eq(PointSignReward::getIsDeleted, 0)
+                .orderByAsc(PointSignReward::getContinueDays));
 
-        // ==================== 计算本周日期 ====================
-        LocalDate today = LocalDate.now();
+        // 5. 用户当前连续天数(读接口不加锁)
+        PointUserSignStatus status = pointUserSignStatusService.getOne(new LambdaQueryWrapper<PointUserSignStatus>()
+                .eq(PointUserSignStatus::getOpenId, openId)
+                .eq(PointUserSignStatus::getActivityId, activityId)
+                .last("LIMIT 1"));
+        int currentContinuousDays = (status == null || status.getCurrentContinuousDays() == null) ? 0 : status.getCurrentContinuousDays();
+        // 今天是否已签到:直接让 DB 判断 DATE 是否为今天,避免 JDBC/时区导致的跨天偏移
+        boolean signedToday = pointUserSignStatusService.count(new LambdaQueryWrapper<PointUserSignStatus>()
+                .eq(PointUserSignStatus::getOpenId, openId)
+                .eq(PointUserSignStatus::getActivityId, activityId)
+                .apply("last_sign_date = CURDATE()")) > 0;
+
+        // 6. 本周范围(周日-周六)
         DayOfWeek dayOfWeek = today.getDayOfWeek();
         int daysSinceSunday = (dayOfWeek.getValue() == 7) ? 0 : dayOfWeek.getValue();
-        LocalDate thisWeekSunday = today.minusDays(daysSinceSunday);
-
-        // ==================== 查询本周签到记录 ====================
-        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
-        Set<LocalDate> signedDateSet = new HashSet<>();
-        List<PointUserSignLog> signLogList = pointUserSignLogService.list(
-                new LambdaQueryWrapper<PointUserSignLog>()
-                        .eq(PointUserSignLog::getOpenId, openId)
-                        .eq(PointUserSignLog::getTaskId, taskId)
-        );
+        LocalDate weekStart = today.minusDays(daysSinceSunday);
+        LocalDate weekEndExclusive = weekStart.plusDays(7);
+
+        // 7. 本周签到日志(只取本周,避免历史污染)
+        // 注意:历史数据里 PointUserSignLog.points 可能仅存“阶梯加成”(如 5/6/7),
+        // 面板展示需要按 continuousDays + 当前配置重算“基础分+阶梯累加”。
+        Map<LocalDate, PointUserSignLog> signedLogMap = new HashMap<>();
+        Date weekStartDate = Date.from(weekStart.atStartOfDay(zoneId).toInstant());
+        Date weekEndDateExclusive = Date.from(weekEndExclusive.atStartOfDay(zoneId).toInstant());
+        // 显式列名,避免字段映射差异导致过滤失效
+        List<PointUserSignLog> signLogList = pointUserSignLogService.list(new LambdaQueryWrapper<PointUserSignLog>()
+                .eq(PointUserSignLog::getOpenId, openId)
+                .eq(PointUserSignLog::getTaskId, taskId)
+                .ge(PointUserSignLog::getSignDate, weekStartDate)
+                .lt(PointUserSignLog::getSignDate, weekEndDateExclusive));
         if (CollUtil.isNotEmpty(signLogList)) {
-            signedDateSet = signLogList.stream()
-                    .map(log -> log.getSignDate().toInstant().atZone(zoneId).toLocalDate())
-                    .collect(Collectors.toSet());
+            for (PointUserSignLog log : signLogList) {
+                if (log == null || log.getSignDate() == null) {
+                    continue;
+                }
+                LocalDate signDate = log.getSignDate().toInstant().atZone(zoneId).toLocalDate();
+                signedLogMap.put(signDate, log);
+            }
         }
 
-        // ==================== 生成7天签到数据 ====================
-        List<SignDayVo> voList = new ArrayList<>();
-        // 核心:未来连续天数
-        int futureContinues =  1;
+        // 8. 生成 7 天面板数据
+        List<SignDayVo> voList = new ArrayList<>(7);
+        // 面板口径:今天未签到时,今天永远按“连续第 1 天”预估
+        int virtualTodayContinuousDays = signedToday ? currentContinuousDays : 1;
+        int nextContinuousDays = virtualTodayContinuousDays + 1;
 
         for (int i = 0; i < 7; i++) {
-            LocalDate date = thisWeekSunday.plusDays(i);
-            boolean isToday = date.equals(today);
-            boolean signed = signedDateSet.contains(date);
+            LocalDate date = weekStart.plusDays(i);
+            PointUserSignLog signedLog = signedLogMap.get(date);
+            // 今天是否已签,以状态表为准(更权威且是 date 类型)
+            boolean signed = date.equals(today) ? signedToday : signedLog != null;
 
             SignDayVo vo = new SignDayVo();
             vo.setDate(date);
 
-            // 活动未开始
-            if (activityStartTime != null) {
-                LocalDate activityStartDate = activityStartTime.toInstant().atZone(zoneId).toLocalDate();
-                if (date.isBefore(activityStartDate)) {
-                    vo.setStatus(4);
-                    vo.setPoints(basePoints);
-                    voList.add(vo);
-                    continue;
-                }
+            // 8.1 活动有效性校验:不在活动时间范围内,直接过期(status=4)
+            if ((activityStartDate != null && date.isBefore(activityStartDate))
+                    || (!isPermanent && activityEndDate != null && date.isAfter(activityEndDate))) {
+                vo.setStatus(4);
+                vo.setPoints(basePoints);
+                voList.add(vo);
+                continue;
             }
 
-            // 状态判断
-            if (isToday && !signed) {
-                vo.setStatus(2);
-            } else if (signed) {
+            // 8.2 状态计算
+            if (signed) {
                 vo.setStatus(1);
+            } else if (date.equals(today)) {
+                vo.setStatus(2);
             } else if (date.isAfter(today)) {
                 vo.setStatus(0);
             } else {
-                long daysDiff = ChronoUnit.DAYS.between(date, today);
-                vo.setStatus(daysDiff > 1 ? 4 : 3);
+                // 过去未签:昨天算断签(3),更早算过期(4)
+                vo.setStatus(date.equals(today.minusDays(1)) ? 3 : 4);
             }
 
-            // ==================== 积分核心:完全动态累加 ====================
-            int points = basePoints;
-            if (vo.getStatus() == 4) {
-                points = basePoints;
-            } else if (isToday) {
-                points = basePoints;
-            } else if (date.isAfter(today)) {
-                int totalReward = 0;
-                // 累加所有满足「连续天数 ≥ 配置天数」的奖励
-                for (PointSignReward reward : rewardList) {
-                    if (futureContinues >= reward.getContinueDays()) {
-                        totalReward += reward.getRewardPoints();
-                    }
+            // 8.3 积分计算(基础分 + 阶梯累加)
+            int points;
+            if (vo.getStatus() == 1) {
+                Integer continuousDays = (signedLog == null) ? null : signedLog.getContinuousDays();
+                // 优先按连续天数重算(兼容旧数据 points=5/6/7 的情况)
+                if (continuousDays != null) {
+                    points = calcCumulativeSignPoints(basePoints, continuousDays, rewardList);
+                } else if (signedLog != null && signedLog.getPoints() != null) {
+                    // 兜底:如果日志里就是实际发放值(新数据),则直接回显
+                    points = signedLog.getPoints();
+                } else if (date.equals(today) && signedToday) {
+                    // 今天已签但本周日志未查到(极端情况):用状态表连续天数兜底
+                    points = calcCumulativeSignPoints(basePoints, currentContinuousDays, rewardList);
+                } else {
+                    points = basePoints;
                 }
-                points = basePoints + totalReward;
-                futureContinues++;
+            } else if (vo.getStatus() == 2) {
+                points = calcCumulativeSignPoints(basePoints, virtualTodayContinuousDays, rewardList);
+            } else if (vo.getStatus() == 0) {
+                points = calcCumulativeSignPoints(basePoints, nextContinuousDays, rewardList);
+                nextContinuousDays++;
             } else {
-                points = signed ? basePoints : 0;
+                // 断签/过期:未签到不展示可得积分
+                points = 0;
             }
 
             vo.setPoints(points);
@@ -450,6 +478,33 @@ public class PointActivityServiceImpl extends ServiceImpl<PointActivityMapper, P
         return voList;
     }
 
+    /**
+     * 签到积分计算:基础分 + 阶梯奖励累加
+     *
+     * 配置口径:reward.continueDays 表示“本档位需要再连续签到 N 天”,需要做累计阈值:
+     * 例如配置 1/2/3 天,对应阈值为 1、(1+2)=3、(1+2+3)=6。
+     *
+     * 业务规则:首日仅基础分,阶梯奖励从“超过阈值的下一天”开始生效,
+     * 即连续天数满足 (continuousDays > threshold) 才加对应档位奖励。
+     */
+    private int calcCumulativeSignPoints(int basePoints, int continuousDays, List<PointSignReward> rewardList) {
+        int total = Math.max(basePoints, 0);
+        if (continuousDays <= 0 || CollUtil.isEmpty(rewardList)) {
+            return total;
+        }
+        int threshold = 0;
+        for (PointSignReward reward : rewardList) {
+            if (reward == null || reward.getContinueDays() == null || reward.getRewardPoints() == null) {
+                continue;
+            }
+            threshold += reward.getContinueDays();
+            if (continuousDays > threshold) {
+                total += reward.getRewardPoints();
+            }
+        }
+        return total;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void sign(SignDTO dto) {
@@ -504,16 +559,13 @@ public class PointActivityServiceImpl extends ServiceImpl<PointActivityMapper, P
             pointUserSignStatusService.updateById(status);
         }
 
-        // 4. 计算奖励积分
-        int rewardPoints = task.getBasePoints();
-        PointSignReward reward = pointSignRewardService.getOne(new LambdaQueryWrapper<PointSignReward>()
+        // 4. 计算奖励积分(基础分 + 阶梯奖励累加)
+        int basePoints = task.getBasePoints() == null ? 0 : task.getBasePoints();
+        List<PointSignReward> rewardList = pointSignRewardService.list(new LambdaQueryWrapper<PointSignReward>()
                 .eq(PointSignReward::getSignTaskId, taskId)
-                .le(PointSignReward::getContinueDays, newContinuousDays)
-                .orderByDesc(PointSignReward::getContinueDays)
-                .last("LIMIT 1"));
-        if (reward != null) {
-            rewardPoints = reward.getRewardPoints();
-        }
+                .eq(PointSignReward::getIsDeleted, 0)
+                .orderByAsc(PointSignReward::getContinueDays));
+        int rewardPoints = calcCumulativeSignPoints(basePoints, newContinuousDays, rewardList);
 
         // 5. 写入签到流水
         PointUserSignLog signLog = new PointUserSignLog();

+ 0 - 5
nightFragrance-massage/src/main/java/com/ylx/point/service/impl/PointUserSignLogServiceImpl.java

@@ -18,9 +18,4 @@ import javax.annotation.Resource;
 public class PointUserSignLogServiceImpl extends ServiceImpl<PointUserSignLogMapper, PointUserSignLog> implements IPointUserSignLogService {
     @Resource
     private PointUserSignLogMapper pointUserSignLogMapper;
-
-    @Override
-    public int countTodaySign(String openId, Long taskId) {
-        return pointUserSignLogMapper.countTodaySign(openId, taskId);
-    }
 }

+ 1 - 1
nightFragrance-massage/src/main/resources/mapper/point/PointUserSignLogMapper.xml

@@ -6,7 +6,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     
     <resultMap type="PointUserSignLog" id="PointUserSignLogResult">
         <result property="id"    column="id"    />
-        <result property="openId"    column="open_d"    />
+        <result property="openId"    column="open_id"    />
         <result property="activityId"    column="activity_id"    />
         <result property="taskId"    column="task_id"    />
         <result property="signDate"    column="sign_date"    />