165 lines
5.5 KiB
Java
165 lines
5.5 KiB
Java
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<CheckIn> getUserCheckInHistory(Long userId, Integer limit) {
|
||
LambdaQueryWrapper<CheckIn> 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<CheckIn>()
|
||
.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; // 基础奖励
|
||
}
|
||
}
|
||
}
|
||
|