1. 需求分析
动态生成日历
签到可以获得积分,礼券,小样,正品等
连续签到,需要显示给用户,已经连续签到多少天
若中断签到,将重置签到,从第一天开始计算
签到对于时间的精确度要求比较高,当天签到的,那么记录的签到时间是当天,如果还有后续的一系列操作,比如计算积分,那后续操作的时间必须和签到的时间一致
对于凌晨,跨天之类的场景,特别需要注意
2.表结构设计
用户每日签到表user_day_sign
签到奖励表sign_reward
以及积分表user_point和积分变动流水账单表user_point_stream,是以前就有的,只需要对相应的积分增加和流水账单数据的增加

3. 后台代码实现
Controller
/ * 签到相关 */ @Slf4j @RestController @RequestMapping("/api") public class UserDaySignController extends BaseController { @Resource private UserDaySignService userDaySignService; / * 签到日历 */ @GetMapping(value = "/user/daySignInfo") @LogonRequired public AppResult<UserDaySignInfoRes> daySignInfo() { UserDaySignInfoRes userDaySignInfoRes = userDaySignService.daySignInfo(getUid()); return AppResultUtils.normal(userDaySignInfoRes); } / * 日签到 */ @GetMapping(value = "/user/daySignIn") @LogonRequired public AppResult<Boolean> daySignIn(@Validated UserSignInReq userSignInReq) { return AppResultUtils.normal(userDaySignService.daySignIn(getUid(),userSignInReq)); }
讯享网
service
讯享网 public interface UserDaySignService extends IService<UserDaySign> { / * 签到日历 * @param uid 用户id * @return */ UserDaySignInfoRes daySignInfo(Integer uid); / * 日签到 * @param uid 用户id * @param userSignInReq 用户签到信息请求 * @return */ Boolean daySignIn(Integer uid, UserSignInReq userSignInReq); }
具体实现impl:
@Service public class UserDaySignImpl extends ServiceImpl<UserDaySignMapper, UserDaySign> implements UserDaySignService { @Resource private SignRewardMapper signRewardMapper; @Resource private UserPointMapper userPointMapper; @Resource private UserPointStreamMapper userPointStreamMapper; @Override public UserDaySignInfoRes daySignInfo(Integer uid) { QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("uid",uid); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String today = sdf.format(new Date()); queryWrapper.orderByDesc("sign_day"); queryWrapper.last("limit 1"); UserDaySign userDaySign = baseMapper.selectOne(queryWrapper); if (userDaySign == null) {//day_sign无数据 userDaySign = new UserDaySign(); userDaySign.setSignDay(today); userDaySign.setConsecutiveDays(0); userDaySign.setUid(uid); userDaySign.setSignStatus(0); baseMapper.insert(userDaySign); } else { if (!userDaySign.getSignDay().equals(today)) {//有数据但不是今天的,沿用前一天的连续签到时间和开始签到日期 UserDaySign userDaySign1 = new UserDaySign(); if (userDaySign.getConsecutiveDays() > 0) { userDaySign1.setConsecutiveDays(userDaySign.getConsecutiveDays()); userDaySign1.setFirstSignDay(userDaySign.getFirstSignDay()); } else { userDaySign.setConsecutiveDays(0); } userDaySign1.setSignDay(today); userDaySign1.setUid(uid); userDaySign1.setSignStatus(0); baseMapper.insert(userDaySign1); } } UserPoint userPoint = userPointMapper.selectOne(new QueryWrapper<UserPoint>().eq("uid",uid)); queryWrapper = new QueryWrapper(); queryWrapper.orderByAsc("consecutive_days"); List<SignReward> signRewards = signRewardMapper.selectList(queryWrapper); UserDaySignInfoRes userDaySignInfoRes = new UserDaySignInfoRes(); if (userPoint != null) { userDaySignInfoRes.setConsecutiveDays(userDaySign.getConsecutiveDays()); userDaySignInfoRes.setRewardTotal(userPoint.getTotalBalance()); List<UserDaySignRes> calendar = new ArrayList<>(); for (SignReward signReward : signRewards) { UserDaySignRes userDaySignRes = new UserDaySignRes(); userDaySignRes.setConsecutiveDays(signReward.getConsecutiveDays()); userDaySignRes.setRewardAmount(signReward.getRewardAmount()); if (userDaySign.getConsecutiveDays() > 0 && userDaySign.getConsecutiveDays() >= signReward.getConsecutiveDays()) { userDaySignRes.setIsConsecutive(true); } else { userDaySignRes.setIsConsecutive(false); } calendar.add(userDaySignRes); } userDaySignInfoRes.setCalendar(calendar); } return userDaySignInfoRes; } @Override public Boolean daySignIn(Integer uid, UserSignInReq userSignInReq) { //用户签到,更新user_day_sign记录 QueryWrapper queryWrapper = new QueryWrapper<UserDaySign>(); queryWrapper.eq("uid",uid); SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd"); String today = sdf.format(new Date()); queryWrapper.eq("sign_day",today); UserDaySign userDaySign = baseMapper.selectOne(queryWrapper); if (userDaySign != null) { userDaySign.setConsecutiveDays(userSignInReq.getConsecutiveDays()); if (userSignInReq.getConsecutiveDays() == 0) { userDaySign.setFirstSignDay(today); } userDaySign.setRewardAmount(userSignInReq.getRewardAmount()); userDaySign.setSignStatus(1); baseMapper.updateById(userDaySign); } else { return false; } UserPoint userPoint = userPointMapper.selectOne(new QueryWrapper<UserPoint>().eq("uid",uid)); userPoint.setTotalBalance(userPoint.getTotalBalance().add(userSignInReq.getRewardAmount())); UserPointStream userPointStream = new UserPointStream(); userPointStream.setAmount(userSignInReq.getRewardAmount()); userPointStream.setPurpose(1); userPointStream.setType(2); userPointStream.setUid(uid); userPointStream.setRemainAmount(userPoint.getTotalBalance()); userPointStream.setTotalAmount(userPoint.getTotalBalance()); if (userPointMapper.updateById(userPoint) == 1 && userPointStreamMapper.insert(userPointStream) == 1) { return true; } return false; } }
其中用到的数据返回有两个类:
UserDaySignRes
讯享网/ * 签到日历 */ @Data public class UserDaySignRes { / * 天数 */ private int consecutiveDays; / * 是否已签到 */ private Boolean isConsecutive; / * 积分 */ private BigDecimal rewardAmount; }
UserDaySignInfoRes
/ * 签到日历 */ @Data public class UserDaySignInfoRes { / * 连续天数 */ private int consecutiveDays; / * 总积分 */ private BigDecimal rewardTotal; / * 签到日历 */ private List<UserDaySignRes> calendar; }
用户签到请求:
UserSignInReq
讯享网/ * 用户签到信息请求 */ @Data public class UserSignInReq { @NotNull(message = "连续签到天数不能为空") private int consecutiveDays; @NotNull(message = "签到奖励积分不能为空") private BigDecimal rewardAmount; }
一共有两个接口,一个是查询接口,查询总积分+签到日历+当前连续签到天数。 一个是签到接口:返回签到是否成功,签到目前是增加了明细变更,更新了总积分额度。还有一个user_day_sign表需要更新签到连续天数,以及如果是第一次签到的话还要更新签到起始天数。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/124232.html