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

58eb561c12bdf1467ff642608efc9ff9.png

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

表结构:

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();

}

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

7bfc81dafbe2b5f3e0f2c382228337f6.png

签到列表接口:

需要增加一个接口返回的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);

Listlist = 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:签到第五天的时候

ddcd7f7e721a04bb81b0791e5596c359.png

65c208030f81fff9a284ba103f803350.png

2:签到第7天的时候

abbe9479fa8e2eeddc94608a0f6a8b03.png

d1b2c5b621d288fe165b643c9f65334a.png

3:签到第N天的时候

a8799cbc92a64346f18daecc7058a2ec.png

167ff6f7116ad4998be687f85f9a48b6.png

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 )

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐