签到得积分功能实现

发布于:2023-01-02 ⋅ 阅读:(706) ⋅ 点赞:(0)

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表需要更新签到连续天数,以及如果是第一次签到的话还要更新签到起始天数。


网站公告

今日签到

点亮在社区的每一天
去签到