|
@@ -5,8 +5,11 @@ import com.etotem.cfc.entity.EmotionCheckin;
|
|
|
import com.etotem.cfc.mapper.DailyCheckinMapper;
|
|
import com.etotem.cfc.mapper.DailyCheckinMapper;
|
|
|
import com.etotem.cfc.mapper.EmotionCheckinMapper;
|
|
import com.etotem.cfc.mapper.EmotionCheckinMapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
|
|
+import com.etotem.cfc.util.IdempotencyUtil;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
|
|
+import java.time.LocalDate;
|
|
|
|
|
+
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import java.util.Date;
|
|
import java.util.Date;
|
|
@@ -29,6 +32,9 @@ public class DailyCheckinService {
|
|
|
@Resource
|
|
@Resource
|
|
|
private ChallengeService challengeService;
|
|
private ChallengeService challengeService;
|
|
|
|
|
|
|
|
|
|
+ @Resource
|
|
|
|
|
+ private IdempotencyUtil idempotencyUtil;
|
|
|
|
|
+
|
|
|
public List<DailyHealthCheckin> getCheckinsByMember(Long memberId) {
|
|
public List<DailyHealthCheckin> getCheckinsByMember(Long memberId) {
|
|
|
return dailyCheckinMapper.selectList(new LambdaQueryWrapper<DailyHealthCheckin>()
|
|
return dailyCheckinMapper.selectList(new LambdaQueryWrapper<DailyHealthCheckin>()
|
|
|
.eq(DailyHealthCheckin::getMemberId, memberId)
|
|
.eq(DailyHealthCheckin::getMemberId, memberId)
|
|
@@ -40,6 +46,29 @@ public class DailyCheckinService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public DailyHealthCheckin createCheckin(DailyHealthCheckin checkin) {
|
|
public DailyHealthCheckin createCheckin(DailyHealthCheckin checkin) {
|
|
|
|
|
+ // 每日幂等:同一天同一成员只允许打卡一次(防重复提交重复发积分)
|
|
|
|
|
+ String idemKey = "checkin:" + checkin.getMemberId() + ":" + LocalDate.now();
|
|
|
|
|
+ if (!idempotencyUtil.tryAcquire(idemKey, 24 * 3600)) {
|
|
|
|
|
+ log.warn("成员{}今日已打卡,跳过重复提交", checkin.getMemberId());
|
|
|
|
|
+ DailyHealthCheckin existing = dailyCheckinMapper.selectOne(
|
|
|
|
|
+ new LambdaQueryWrapper<DailyHealthCheckin>()
|
|
|
|
|
+ .eq(DailyHealthCheckin::getMemberId, checkin.getMemberId())
|
|
|
|
|
+ .eq(DailyHealthCheckin::getCheckinDate, new java.sql.Date(System.currentTimeMillis()))
|
|
|
|
|
+ .last("LIMIT 1"));
|
|
|
|
|
+ if (existing != null) {
|
|
|
|
|
+ return existing;
|
|
|
|
|
+ }
|
|
|
|
|
+ throw new RuntimeException("今日已打卡");
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ return doCreateCheckin(checkin);
|
|
|
|
|
+ } catch (RuntimeException e) {
|
|
|
|
|
+ idempotencyUtil.release(idemKey);
|
|
|
|
|
+ throw e;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private DailyHealthCheckin doCreateCheckin(DailyHealthCheckin checkin) {
|
|
|
checkin.setCreatedAt(new Date());
|
|
checkin.setCreatedAt(new Date());
|
|
|
checkin.setUpdatedAt(new Date());
|
|
checkin.setUpdatedAt(new Date());
|
|
|
dailyCheckinMapper.insert(checkin);
|
|
dailyCheckinMapper.insert(checkin);
|