表
用户签到表
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);
}
}