package com.designhub.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.designhub.entity.CheckIn; import com.designhub.exception.BusinessException; import com.designhub.mapper.CheckInMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; import java.time.temporal.ChronoUnit; import java.util.List; /** * 签到Service */ @Slf4j @Service @RequiredArgsConstructor public class CheckInService { private final CheckInMapper checkInMapper; private final NotificationService notificationService; private final SystemConfigService systemConfigService; /** * 用户签到 */ @Transactional(rollbackFor = Exception.class) public CheckIn checkIn(Long userId) { LocalDate today = LocalDate.now(); // 检查今天是否已签到 int count = checkInMapper.countTodayCheckIn(userId, today); if (count > 0) { throw new BusinessException("今天已经签到过了"); } // 获取最近一次签到记录 CheckIn lastCheckIn = checkInMapper.getLatestCheckIn(userId); int continuousDays = 1; if (lastCheckIn != null) { LocalDate lastDate = lastCheckIn.getCheckInDate(); long daysBetween = ChronoUnit.DAYS.between(lastDate, today); if (daysBetween == 1) { // 连续签到 continuousDays = lastCheckIn.getContinuousDays() + 1; } else if (daysBetween > 1) { // 中断了,重新开始 continuousDays = 1; } } // 计算奖励积分(连续签到越多,奖励越高) int baseScore = systemConfigService.getIntValue("incentive.daily_checkin_score", 5); int rewardScore = calculateRewardScore(baseScore, continuousDays); // 创建签到记录 CheckIn checkIn = new CheckIn(); checkIn.setUserId(userId); checkIn.setCheckInDate(today); checkIn.setContinuousDays(continuousDays); checkIn.setRewardScore(rewardScore); checkIn.setRemark("连续签到" + continuousDays + "天"); checkInMapper.insert(checkIn); // TODO: 实际发放积分奖励 log.info("用户签到成功: userId={}, continuousDays={}, rewardScore={}", userId, continuousDays, rewardScore); // 发送通知 String message = String.format("签到成功!连续签到%d天,获得%d积分", continuousDays, rewardScore); if (continuousDays >= 7) { message += "。坚持得真棒!🎉"; } notificationService.sendSystemNotification(userId, "每日签到", message, "normal"); // 检查签到成就 if (continuousDays == 7 || continuousDays == 30 || continuousDays == 100) { notificationService.sendSystemNotification( userId, "🏆 签到成就达成", String.format("恭喜您达成连续签到%d天的成就!", continuousDays), "high" ); } return checkIn; } /** * 检查用户今天是否已签到 */ public boolean hasCheckedInToday(Long userId) { LocalDate today = LocalDate.now(); return checkInMapper.countTodayCheckIn(userId, today) > 0; } /** * 获取用户签到记录 */ public List getUserCheckInHistory(Long userId, Integer limit) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(CheckIn::getUserId, userId); queryWrapper.orderByDesc(CheckIn::getCheckInDate); if (limit != null && limit > 0) { queryWrapper.last("LIMIT " + limit); } return checkInMapper.selectList(queryWrapper); } /** * 获取用户连续签到天数 */ public int getContinuousDays(Long userId) { CheckIn lastCheckIn = checkInMapper.getLatestCheckIn(userId); if (lastCheckIn != null) { LocalDate today = LocalDate.now(); LocalDate lastDate = lastCheckIn.getCheckInDate(); long daysBetween = ChronoUnit.DAYS.between(lastDate, today); if (daysBetween == 0) { // 今天已签到 return lastCheckIn.getContinuousDays(); } else if (daysBetween == 1) { // 今天还没签到,但昨天签了 return lastCheckIn.getContinuousDays(); } } return 0; } /** * 获取用户总签到天数 */ public long getTotalCheckInDays(Long userId) { return checkInMapper.selectCount( new LambdaQueryWrapper() .eq(CheckIn::getUserId, userId) ); } /** * 计算奖励积分 * 基础分值 + 连续签到加成 */ private int calculateRewardScore(int baseScore, int continuousDays) { if (continuousDays >= 30) { return baseScore * 3; // 30天以上,3倍奖励 } else if (continuousDays >= 14) { return (int) (baseScore * 2.5); // 14天以上,2.5倍奖励 } else if (continuousDays >= 7) { return baseScore * 2; // 7天以上,2倍奖励 } else if (continuousDays >= 3) { return (int) (baseScore * 1.5); // 3天以上,1.5倍奖励 } else { return baseScore; // 基础奖励 } } }