java springboot 7天签到功能设计 数据库表设计 加代码

实现一个类似于这样的签到功能 (参考的百度网盘签到页面)

 

java springboot 7天签到功能设计 数据库表设计 加代码_第1张图片

数据表是一个用户只有一条签到记录的设计, 没有使用签到一次表中加一条数据, 那样的话数据太多了

表结构:

CREATE TABLE `sign_in` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `user_id` bigint(20) NOT NULL COMMENT '签到用户id',
  `continue_days` int(3) NOT NULL DEFAULT '1' COMMENT '连续签到天数',
  `update_time` datetime DEFAULT NULL COMMENT '更新日期, 最后签到日期',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='用户签到表';

实体对象:

import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;

/**
 * 用户签到表
 *
 * @author lixx
 * @version 1.0
 * @date 2020-06-10 10:36
 */
@Data
@NoArgsConstructor
public class SignIn {


	/**
	 * 主键
	 */
	@TableId(type = IdType.AUTO)
	private Long id;

	/**
	 * 签到用户id
	 */
	private Long userId;

	/**
	 * 连续签到天数
	 */
	private Integer continueDays;

	/**
	 * 更新日期, 最后签到日期
	 */
	@JsonFormat(pattern = "yyyy-MM-dd HH:mm")
	@TableField(fill = FieldFill.UPDATE)
	private LocalDateTime updateTime;

	public SignIn(Long userId, LocalDateTime updateTime) {
		this.userId = userId;
		this.updateTime = updateTime;
	}
}

签到接口:

	/**
	 * 用户签到
	 *
	 * @param userId 用户id
	 * @return
	 */
	public JsonResult signIn(Long userId) {
		// 查询用户是否签过到
		SignIn signIn = signInMapper.selectById(userId);
		/*没有签过到, 直接新增*/
		if (null == signIn) {
			signInMapper.insert(new SignIn(userId, LocalDateTime.now()));
		} else {/*签过到*/
			// 判断最后签到日期与当前日期是否超过一天
			LocalDate signInTime = signIn.getUpdateTime().toLocalDate();
			LocalDate currTime = LocalDate.now();
			long daysDiff = ChronoUnit.DAYS.between(signInTime, currTime);
			if (daysDiff <= 0) {
				return JsonResult.buildSuccess("重复签到");
			}
			if (daysDiff > 1) {
				// 1, 超过一天, 把连续签到的天数重置为 1
				signIn.setContinueDays(1);
			} else {
				// 2, 没有超过一天, 把连续签到的天数+1
				signIn.setContinueDays(signIn.getContinueDays() + 1);
			}
			signIn.setUpdateTime(LocalDateTime.now());
			signInMapper.updateById(signIn);
		}
		return JsonResult.buildSuccess();
	}

这样签到功能就做好了, 数据库数据如下:

java springboot 7天签到功能设计 数据库表设计 加代码_第2张图片

签到列表接口:

需要增加一个接口返回的dto类型(大家用map也行)

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

/**
 * @author lixx
 * @version 1.0
 * @date 2020-06-10 15:09
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class SignInDto implements Serializable {

	/**
	 * 表示签到的天数
	 */
	private Integer day;

	/**
	 * 1表示已经签到, 0表示未签到
	 */
	private Integer flag;

	// 如果还有其他业务字段就加在后面, 如积分, 如金币

}

签到列表接口逻辑代码:

	/**
	 * 用户签到列表
	 *
	 * @param userId 用户id
	 * @return
	 */
	public JsonResult signInList(Long userId) {
		SignIn signIn = signInMapper.selectById(userId);
		List list = new ArrayList<>(7);
		if (null == signIn) {
			// 没有签过到
			for (int i = 1; i < 8; i++) {
				list.add(new SignInDto(i, 0));
			}
		} else {
			// 签过到
			Integer continueDays = signIn.getContinueDays();
			// 1, 前六天的 flag是要固定的
			if (continueDays <= 6) {
				for (int i = 1; i < 8; i++) {
					if (i <= continueDays) {
						list.add(new SignInDto(i, 1));
					} else {
						list.add(new SignInDto(i, 0));
					}
				}
			} else {
				// 2, 6天后的签到天数要跟随日期增加
				for (int i = 5; i > -2; i--) {
					if (i > -1) {
						list.add(new SignInDto(continueDays - i, 1));
					} else {
						list.add(new SignInDto(continueDays + 1, 0));
					}
				}
			}
		}
		return JsonResult.buildSuccess(list);
	}

效果如下:

1:签到第五天的时候

java springboot 7天签到功能设计 数据库表设计 加代码_第3张图片

java springboot 7天签到功能设计 数据库表设计 加代码_第4张图片

2:签到第7天的时候

java springboot 7天签到功能设计 数据库表设计 加代码_第5张图片

java springboot 7天签到功能设计 数据库表设计 加代码_第6张图片

3:签到第N天的时候

java springboot 7天签到功能设计 数据库表设计 加代码_第7张图片

java springboot 7天签到功能设计 数据库表设计 加代码_第8张图片

ps: 每天凌晨要把未连续签到用户的连续签到天数(sign_in表的continue_days字段)设置为0, 我这里使用的是数据库定时任务, 大家也可以使用代码的定时任务,看个人选择

/*定时任务*/
-- 每天凌晨重置超过时间未签到的连续签到天数为0
CREATE EVENT IF NOT EXISTS reset_expired_signins
    ON SCHEDULE EVERY 1 DAY STARTS DATE_ADD(DATE_ADD(CURDATE(), INTERVAL 1 DAY), INTERVAL 5 MINUTE)
    ON COMPLETION PRESERVE ENABLE
    -- 更新语句
    DO UPDATE sign_in SET continue_days = 0 WHERE id IN ( SELECT a.id FROM ( SELECT id FROM sign_in WHERE DATEDIFF(CURDATE(), update_time) > 1 ) AS a )

 

你可能感兴趣的:(java springboot 7天签到功能设计 数据库表设计 加代码)