您的当前位置:首页正文

签到打卡功能,7天一个周期,中间断签重新开始

2024-11-26 来源:个人技术集锦

用户签到表
CREATE TABLE `t_user_sign` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `count` int(11) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `last_modify_time` datetime DEFAULT NULL,
  `sign_count` int(11) DEFAULT NULL,
  `user_id` bigint(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `id` (`id`),
  KEY `user_id` (`user_id`),
  KEY `last_modify_time` (`last_modify_time`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

用户签到日志表
CREATE TABLE `t_user_sign_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `create_time` datetime DEFAULT NULL,
  `sign_status` char(1) NOT NULL,
  `update_time` datetime DEFAULT NULL,
  `user_sign_id` bigint(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `user_sign_id` (`user_sign_id`),
  KEY `sign_status` (`sign_status`,`user_sign_id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

简单的代码体现

使用的是JPA方式,可以根据情况自己转换

**
 * 描述:
 *
 * @author 哈哈哈
 * @date 2019/5/9 13:53
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "t_user_sign")
public class UserSign {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 关联用户ID
     */
    @Column(nullable = false)
    private Long userId;


    /**
     * 创建时间
     */
    @Column
    private Date createTime;


    /**
     * 最后签到时间
     */
    @Column
    private Date lastModifyTime;


    /**
     * 连续签到次数
     */
    @Column
    private Integer signCount;

    /**
     * 签到次数
     */
    @Column
    private Integer count;


}
/**
 * 描述:用户签到记录表
 *
 * @author 哈哈哈
 * @date 2019/5/9 14:52
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Entity
@Table(name = "t_user_sign_log")
public class UserSignLog {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;


    /**
     * 关联签到id
     */
    @Column
    private Long userSignId;


    @Column
    private Date createTime;

    @Column
    private Date updateTime;


    /**
     * 是否可用
     */
    @Column(nullable = false, columnDefinition = "char(1)")
    @Type(type = "yes_no")
    private Boolean signStatus;

}

DAO层

@Repository
public interface UserSignRepository extends JpaRepository<UserSign, Long>, JpaSpecificationExecutor<UserSign> {

    UserSign findUserSignByUserId(Long userId);

}


/**
 * 描述:
 *
 * @author 
 * @date 2019/5/9 14:55
 */

@Repository
public interface UserSignLogRepository extends JpaRepository<UserSignLog, Long>, JpaSpecificationExecutor<UserSignLog> {

    @Modifying
    @Query("update UserSignLog set signStatus=false  where userSignId =(?1)")
    int updateUserSignLogSignStatus(Long userSignId);


    List<UserSignLog> findUserSignLogsByUserSignIdAndSignStatusIsTrue(Long userSignId);


}

service

 


/**
 * 描述:用户签到
 *
 * @author 哈哈哈
 * @date 2019/5/9 14:00
 */
@Service
public class UserSignService {


    private final UserSignRepository userSignRepository;
    private final UserSignLogRepository userSignLogRepository;

    @Autowired
    public UserSignService(UserSignRepository userSignRepository, UserSignLogRepository userSignLogRepository) {
        this.userSignRepository = userSignRepository;
        this.userSignLogRepository = userSignLogRepository;
    }

    /****
     * 打卡
     * @param userId 用户id
     * @return
     */
    @Transactional()
    public int createSign(Long userId) {
        UserSign userSign = userSignRepository.findUserSignByUserId(userId);
        Date now = new Date();
        /*判断是否是第一次签到*/
        if (userSign == null) {
            System.out.println("用户第一次签到");
            userSign = UserSign.builder()
                    .createTime(now)
                    .lastModifyTime(now)
                    .count(1)
                    .userId(userId)
                    .signCount(1)
                    .build();
            userSignRepository.save(userSign);
            UserSignLog userSignLog = UserSignLog.builder()
                    .createTime(now)
                    .updateTime(now)
                    .userSignId(userSign.getId())
                    .signStatus(true)
                    .build();
            userSignLogRepository.save(userSignLog);
            return 1;

        } else {
            //今天已经签到过了
            if (userSign.getLastModifyTime().getTime() > getStartOfDay(now).getTime()
                    && userSign.getLastModifyTime().getTime() < getEndOfDay(now).getTime()) {
                System.out.println("用户已经签到过了");
                return userSign.getSignCount();
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            calendar.add(Calendar.DATE, -1);

            //非连续签到
            if (userSign.getLastModifyTime().getTime() < getStartOfDay(calendar.getTime()).getTime()) {
                System.out.println("已经不是连续签到");
                //签到次数重新开始
                //修改签到log表中的状态
                userSignLogRepository.updateUserSignLogSignStatus(userSign.getId());
                userSign.setCount(userSign.getCount() + 1);
                userSign.setSignCount(1);
                userSign.setLastModifyTime(now);
                UserSignLog userSignLog = UserSignLog.builder()
                        .createTime(now)
                        .updateTime(now)
                        .signStatus(true)
                        .userSignId(userSign.getId())
                        .build();
                userSignLogRepository.save(userSignLog);
                userSignRepository.save(userSign);
                return 1;
            } else {
                System.out.println("连续签到");
                //正常打卡
                userSign.setSignCount(userSign.getSignCount() + 1);
                userSign.setCount(userSign.getCount() + 1);
                userSign.setLastModifyTime(now);

                userSignRepository.save(userSign);
                UserSignLog userSignLog = UserSignLog.builder()
                        .signStatus(true)
                        .createTime(now)
                        .updateTime(now)
                        .userSignId(userSign.getId())
                        .build();
                userSignLogRepository.save(userSignLog);
                return userSign.getSignCount();
            }
        }
    }

    /****
     * 用户每天第一次进入签到打卡页面初始化一下数据
     * @param userId
     */
    @Transactional()
    public void init(Long userId) {
        UserSign userSign = userSignRepository.findUserSignByUserId(userId);
        Date now = new Date();
        //曾经签到过
        if (userSign != null) {
            //判断今天是否签到过
            if (userSign.getLastModifyTime().getTime() > getStartOfDay(now).getTime()
                    && userSign.getLastModifyTime().getTime() < getEndOfDay(now).getTime()) {
                System.out.println("用户今天已经签到过了,正常使用");
                return;
            }
            //判断昨天是否签到过
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            calendar.add(Calendar.DATE, -1);
            if (userSign.getLastModifyTime().getTime() < getStartOfDay(calendar.getTime()).getTime()) {
                System.out.println("昨天没有签到");
                //昨天没有连续签到
                if (userSign.getSignCount() == 7) {
                    System.out.println("签到次数为7的时候初始化数据");
                    //初始化数据
                    userSign.setSignCount(0);
                    userSignLogRepository.updateUserSignLogSignStatus(userSign.getId());
                    userSignRepository.save(userSign);
                    return;
                }
                System.out.println("签到次正常");
            } else {
                System.out.println("昨天签到了");
                //昨天签到过
                if (userSign.getSignCount() == 7) {
                    System.out.println("签到次数为7的时候初始化数据");
                    //初始化数据
                    userSign.setSignCount(0);
                    userSignLogRepository.updateUserSignLogSignStatus(userSign.getId());
                    userSignRepository.save(userSign);
                    return;
                }
                System.out.println("签到次正常");
            }
        }

    }


    /*根据用户id查询签到list*/
    public List<UserSignLog> data(Long userId) {
        UserSign userSign = userSignRepository.findUserSignByUserId(userId);
        //没有签到过,返回null
        if (userSign != null) {
            //如果今天签到过
            return userSignLogRepository.findUserSignLogsByUserSignIdAndSignStatusIsTrue(userSign.getId());
        }
        return new ArrayList<>();
    }

    public Boolean isOrSign(Long userId) {
        Date now = new Date();
        UserSign userSign = userSignRepository.findUserSignByUserId(userId);
        //没有签到过,返回null
        //如果今天签到过
        return userSign != null && userSign.getLastModifyTime().getTime() > getStartOfDay(now).getTime() && userSign.getLastModifyTime().getTime() < getEndOfDay(now).getTime();
    }


    /****
     * 获得某天最大时间 2019-05-09 23:59:59
     * @param date 日期
     * @return
     */

    public static Date getEndOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /****
     * 获得某天最小时间 2019-05-09 00:00:00
     * @param date 日期
     * @return
     */
    public static Date getStartOfDay(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }


}

 

接下来就是controller

@RestController
@RequestMapping("/sign")
@Api(tags = {"用户签到打卡API"})
public class UserSignController {


    private final UserSignService userSignService;



    @Autowired
    public UserSignController(UserSignService userSignService) {
        this.userSignService = userSignService;
    }

    @ApiOperation(value = "用户签到")
    @PostMapping("/createSign")
    public List<UserSignLog> createSign(@RequestParam Long userId) {
       //首先要初始化数据
        userSignService.init(userId);
        userSignService.createSign(userId);
        return userSignService.data(userId);
    }


    @ApiOperation(value = "打卡数据")
    @GetMapping("/data")
    public List<UserSignLog> data(@RequestParam Long userId) {
        userSignService.init(userId);
        return userSignService.data(userId);
    }

    @ApiOperation(value = "判断今天是否已经打过卡")
    @GetMapping("/isOrSign")
    public Boolean isOrSign(@RequestParam Long userId) {
        return userSignService.isOrSign(userId);
    }


}

 

显示全文