|
@@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.ylx.common.core.domain.model.WxLoginUser;
|
|
import com.ylx.common.core.domain.model.WxLoginUser;
|
|
|
|
|
+import com.ylx.common.exception.ServiceException;
|
|
|
import com.ylx.common.exception.base.BaseException;
|
|
import com.ylx.common.exception.base.BaseException;
|
|
|
import com.ylx.common.utils.DateUtils;
|
|
import com.ylx.common.utils.DateUtils;
|
|
|
import com.ylx.common.utils.SecurityUtils;
|
|
import com.ylx.common.utils.SecurityUtils;
|
|
@@ -24,11 +25,9 @@ import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
-import java.time.DateTimeException;
|
|
|
|
|
-import java.time.LocalDate;
|
|
|
|
|
-import java.time.LocalDateTime;
|
|
|
|
|
-import java.time.ZoneId;
|
|
|
|
|
|
|
+import java.time.*;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
import java.util.*;
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
@@ -293,102 +292,90 @@ public class PointActivityServiceImpl extends ServiceImpl<PointActivityMapper, P
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public List<SignDayVo> getSignInfo(SignDTO dto) {
|
|
public List<SignDayVo> getSignInfo(SignDTO dto) {
|
|
|
- // 1. 获取用户信息
|
|
|
|
|
|
|
+ // ... (前面获取用户、任务、奖励配置的代码保持不变) ...
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 获取用户信息 & 任务 & 奖励列表
|
|
|
WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
|
|
WxLoginUser wxLoginUser = SecurityUtils.getWxLoginUser();
|
|
|
- if (ObjectUtil.isNull(wxLoginUser)) {
|
|
|
|
|
- throw new RuntimeException("用户不存在");
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (ObjectUtil.isNull(wxLoginUser)) throw new ServiceException("用户不存在");
|
|
|
String openId = wxLoginUser.getCOpenid();
|
|
String openId = wxLoginUser.getCOpenid();
|
|
|
|
|
|
|
|
- // 2. 获取任务ID (模拟城市逻辑)
|
|
|
|
|
PointSignTask task = getEnabledTask(dto.getCityCode());
|
|
PointSignTask task = getEnabledTask(dto.getCityCode());
|
|
|
- if (task == null) {
|
|
|
|
|
- throw new RuntimeException("当前城市暂无签到活动");
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ if (task == null) throw new ServiceException("当前城市暂无签到活动");
|
|
|
Long taskId = task.getId();
|
|
Long taskId = task.getId();
|
|
|
|
|
+ Long activityId = task.getActivityId();
|
|
|
|
|
|
|
|
- // 3. 查询奖励配置 (按天数正序查询)
|
|
|
|
|
LambdaQueryWrapper<PointSignReward> rewardQuery = new LambdaQueryWrapper<>();
|
|
LambdaQueryWrapper<PointSignReward> rewardQuery = new LambdaQueryWrapper<>();
|
|
|
rewardQuery.eq(PointSignReward::getSignTaskId, taskId);
|
|
rewardQuery.eq(PointSignReward::getSignTaskId, taskId);
|
|
|
rewardQuery.orderByAsc(PointSignReward::getContinueDays);
|
|
rewardQuery.orderByAsc(PointSignReward::getContinueDays);
|
|
|
rewardQuery.last("LIMIT 7");
|
|
rewardQuery.last("LIMIT 7");
|
|
|
List<PointSignReward> rewardList = pointSignRewardService.list(rewardQuery);
|
|
List<PointSignReward> rewardList = pointSignRewardService.list(rewardQuery);
|
|
|
|
|
|
|
|
- // 4. 获取用户当前状态
|
|
|
|
|
|
|
+ // 2. 获取状态
|
|
|
boolean signedToday = pointUserSignLogService.countTodaySign(openId, taskId) > 0;
|
|
boolean signedToday = pointUserSignLogService.countTodaySign(openId, taskId) > 0;
|
|
|
|
|
+ PointUserSignStatus status = pointUserSignStatusService.selectByOpenIdAndActivityIdForUpdate(openId, activityId);
|
|
|
|
|
+ int continuousDays = (status == null) ? 0 : status.getCurrentContinuousDays();
|
|
|
|
|
|
|
|
- LambdaQueryWrapper<PointUserSignStatus> statusQuery = new LambdaQueryWrapper<>();
|
|
|
|
|
- statusQuery.eq(PointUserSignStatus::getOpenId, openId);
|
|
|
|
|
- statusQuery.eq(PointUserSignStatus::getActivityId, taskId);
|
|
|
|
|
- PointUserSignStatus status = pointUserSignStatusService.getOne(statusQuery);
|
|
|
|
|
|
|
+ // --- 核心修改:计算本周日期 & 状态判断 ---
|
|
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
|
|
|
|
|
- // 修正点:处理空指针,如果没记录则默认为0
|
|
|
|
|
- int continuousDays = (status == null) ? 0 : status.getCurrentContinuousDays();
|
|
|
|
|
|
|
+ // 计算本周周日
|
|
|
|
|
+ DayOfWeek dayOfWeek = today.getDayOfWeek();
|
|
|
|
|
+ int daysSinceSunday = (dayOfWeek.getValue() == 7) ? 0 : dayOfWeek.getValue();
|
|
|
|
|
+ LocalDate thisWeekSunday = today.minusDays(daysSinceSunday);
|
|
|
|
|
+
|
|
|
|
|
+ // 定义“过期”判定阈值:例如,超过 7 天未签视为过期
|
|
|
|
|
+ // 注意:这里的逻辑是,如果是“本周”的视图,通常只有“断签”和“未签”。
|
|
|
|
|
+ // 但如果你的业务是“补签卡”界面,或者需要展示历史状态,这个逻辑才有意义。
|
|
|
|
|
+ // 这里演示:如果漏签日期距离今天超过 7 天,标记为 4。
|
|
|
|
|
+ int expireThresholdDays = 7;
|
|
|
|
|
|
|
|
- // 5. 组装返回数据
|
|
|
|
|
List<SignDayVo> voList = new ArrayList<>();
|
|
List<SignDayVo> voList = new ArrayList<>();
|
|
|
- LocalDate today = LocalDate.now();
|
|
|
|
|
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
|
|
|
|
|
|
|
|
|
|
- // 注意:UI通常要求从左到右是 [过去 -> 今天],所以我们需要倒序循环 (从第6天前 -> 今天)
|
|
|
|
|
- for (int i = 6; i >= 0; i--) {
|
|
|
|
|
- LocalDate date = today.minusDays(i);
|
|
|
|
|
- int dayIndex = 7 - i; // 计算这是第几天 (1, 2, 3... 7)
|
|
|
|
|
|
|
+ for (int i = 0; i < 7; i++) {
|
|
|
|
|
+ LocalDate date = thisWeekSunday.plusDays(i);
|
|
|
|
|
+ int dayIndex = i + 1;
|
|
|
|
|
|
|
|
SignDayVo vo = new SignDayVo();
|
|
SignDayVo vo = new SignDayVo();
|
|
|
-
|
|
|
|
|
- // 修正点:格式化日期为字符串,避免前端处理麻烦
|
|
|
|
|
vo.setDate(date);
|
|
vo.setDate(date);
|
|
|
|
|
|
|
|
- // --- 核心逻辑修正:状态判断 ---
|
|
|
|
|
- // 逻辑:
|
|
|
|
|
- // 1. 如果是今天 (i==0):看 signedToday
|
|
|
|
|
- // 2. 如果是过去 (i>0):看 continuousDays 是否覆盖了这一天
|
|
|
|
|
- // 注意:只有当今天还没签时,continuousDays才代表截止到昨天的进度。
|
|
|
|
|
- // 如果今天已签,continuousDays 包含了今天。
|
|
|
|
|
-
|
|
|
|
|
- boolean isSigned;
|
|
|
|
|
- if (i == 0) {
|
|
|
|
|
- // 今天的情况
|
|
|
|
|
- isSigned = signedToday;
|
|
|
|
|
|
|
+ boolean isToday = date.equals(today);
|
|
|
|
|
+ boolean isPast = date.isBefore(today);
|
|
|
|
|
+
|
|
|
|
|
+ // 查询该天是否已签 (建议优化为批量查询)
|
|
|
|
|
+ boolean actuallySigned = false;
|
|
|
|
|
+ if (isToday) {
|
|
|
|
|
+ actuallySigned = signedToday;
|
|
|
} else {
|
|
} else {
|
|
|
- // 过去的情况
|
|
|
|
|
- // 如果今天已签,continuousDays 包含了今天,所以 i <= continuousDays - 1
|
|
|
|
|
- // 如果今天没签,continuousDays 截止到昨天,所以 i <= continuousDays
|
|
|
|
|
- // 简化逻辑:只要 (i < continuousDays) 或者 (i == continuousDays 且 今天已签)
|
|
|
|
|
- // 最通用的判断:当前的循环索引 i (倒数第几天) 小于 总连续天数,说明已签
|
|
|
|
|
- // 特殊情况:如果今天没签,continuousDays 是昨天的进度。
|
|
|
|
|
-
|
|
|
|
|
- // 简单写法:
|
|
|
|
|
- if (signedToday) {
|
|
|
|
|
- isSigned = i <= continuousDays; // 包含今天在内的已签天数
|
|
|
|
|
- } else {
|
|
|
|
|
- isSigned = i < continuousDays; // 不包含今天
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 模拟查询
|
|
|
|
|
+ actuallySigned = pointUserSignLogService.count(new LambdaQueryWrapper<PointUserSignLog>()
|
|
|
|
|
+ .eq(PointUserSignLog::getOpenId, openId)
|
|
|
|
|
+ .eq(PointUserSignLog::getTaskId, taskId)
|
|
|
|
|
+ .eq(PointUserSignLog::getSignDate, date)) > 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (isSigned) {
|
|
|
|
|
- vo.setStatus(1); // 已签
|
|
|
|
|
- } else if (i == 0) {
|
|
|
|
|
- vo.setStatus(2); // 今天未签 (可签到)
|
|
|
|
|
|
|
+ // --- 状态赋值逻辑 ---
|
|
|
|
|
+ if (isToday && !actuallySigned) {
|
|
|
|
|
+ vo.setStatus(2); // 2: 今天未签到
|
|
|
|
|
+ } else if (actuallySigned) {
|
|
|
|
|
+ vo.setStatus(1); // 1: 已签
|
|
|
} else {
|
|
} else {
|
|
|
- vo.setStatus(0); // 未来/未签
|
|
|
|
|
|
|
+ // 没签到的情况 (且不是今天)
|
|
|
|
|
+ // 计算该日期距离今天的天数
|
|
|
|
|
+ long daysDiff = ChronoUnit.DAYS.between(date, today);
|
|
|
|
|
+
|
|
|
|
|
+ if (daysDiff > expireThresholdDays) {
|
|
|
|
|
+ vo.setStatus(4); // 4: 已过期 (漏签太久,无法补签)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ vo.setStatus(3); // 3: 断签 (漏签在可接受范围内)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// --- 奖励匹配 ---
|
|
// --- 奖励匹配 ---
|
|
|
- // 根据 dayIndex (1-7) 去 rewardList 找对应的配置
|
|
|
|
|
PointSignReward reward = rewardList.stream()
|
|
PointSignReward reward = rewardList.stream()
|
|
|
.filter(r -> r.getContinueDays() == dayIndex)
|
|
.filter(r -> r.getContinueDays() == dayIndex)
|
|
|
.findFirst()
|
|
.findFirst()
|
|
|
.orElse(null);
|
|
.orElse(null);
|
|
|
-
|
|
|
|
|
- if (reward != null) {
|
|
|
|
|
- vo.setPoints(reward.getRewardPoints());
|
|
|
|
|
- // 如果有其他字段如图片,也可以在这里set
|
|
|
|
|
- } else {
|
|
|
|
|
- vo.setPoints(0);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
|
|
+ vo.setPoints(reward != null ? reward.getRewardPoints() : 0);
|
|
|
voList.add(vo);
|
|
voList.add(vo);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -961,7 +948,7 @@ public class PointActivityServiceImpl extends ServiceImpl<PointActivityMapper, P
|
|
|
queryWrapper.eq(PointSignTask::getIsDeleted, 1);
|
|
queryWrapper.eq(PointSignTask::getIsDeleted, 1);
|
|
|
List<PointSignTask> list = pointSignTaskService.list(queryWrapper);
|
|
List<PointSignTask> list = pointSignTaskService.list(queryWrapper);
|
|
|
PointSignTask task = new PointSignTask();
|
|
PointSignTask task = new PointSignTask();
|
|
|
- ;
|
|
|
|
|
|
|
+
|
|
|
if (CollectionUtil.isNotEmpty(list)) {
|
|
if (CollectionUtil.isNotEmpty(list)) {
|
|
|
task = CollectionUtil.getLast(list);
|
|
task = CollectionUtil.getLast(list);
|
|
|
}
|
|
}
|