diff --git a/api/src/main/java/me/xiaoyan/point/api/controller/SignController.java b/api/src/main/java/me/xiaoyan/point/api/controller/SignController.java index ad8e9e7..be6b06f 100644 --- a/api/src/main/java/me/xiaoyan/point/api/controller/SignController.java +++ b/api/src/main/java/me/xiaoyan/point/api/controller/SignController.java @@ -1,7 +1,9 @@ package me.xiaoyan.point.api.controller; +import cn.dev33.satoken.stp.StpUtil; import io.swagger.annotations.ApiOperation; import me.xiaoyan.point.api.pojo.vo.SignResult; +import me.xiaoyan.point.api.service.SignRecordService; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -9,10 +11,17 @@ import org.springframework.web.bind.annotation.RestController; @RequestMapping("sign") public class SignController { + private SignRecordService signRecordService; @ApiOperation("今日签到") @RequestMapping("today") public SignResult signToday() { - return null; + return signRecordService.signToday(StpUtil.getLoginIdAsInt()); + } + + @ApiOperation("签到信息") + @RequestMapping("info") + public SignResult signInfo() { + return signRecordService.info(StpUtil.getLoginIdAsInt()); } } diff --git a/api/src/main/java/me/xiaoyan/point/api/mapper/SignRecordMapper.java b/api/src/main/java/me/xiaoyan/point/api/mapper/SignRecordMapper.java index fc06de4..5aeaeb8 100644 --- a/api/src/main/java/me/xiaoyan/point/api/mapper/SignRecordMapper.java +++ b/api/src/main/java/me/xiaoyan/point/api/mapper/SignRecordMapper.java @@ -1,10 +1,14 @@ package me.xiaoyan.point.api.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import me.xiaoyan.point.api.pojo.Point; import me.xiaoyan.point.api.pojo.SignRecord; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; @Mapper public interface SignRecordMapper extends BaseMapper { + public int signCountByDate(@Param("uid") int uid, @Param("date") String date); + public List selectRecentDaysRecord(@Param("uid") int uid,@Param("limit")int limit); } diff --git a/api/src/main/java/me/xiaoyan/point/api/pojo/SignRecord.java b/api/src/main/java/me/xiaoyan/point/api/pojo/SignRecord.java index a0685ad..00dd837 100644 --- a/api/src/main/java/me/xiaoyan/point/api/pojo/SignRecord.java +++ b/api/src/main/java/me/xiaoyan/point/api/pojo/SignRecord.java @@ -13,7 +13,7 @@ import java.util.Date; @Data @Accessors(chain = true) -@Builder +@Builder // 如果有builder就需要设置 @NoArgsConstructor @AllArgsConstructor @NoArgsConstructor @AllArgsConstructor public class SignRecord implements Serializable { diff --git a/api/src/main/java/me/xiaoyan/point/api/pojo/vo/SignResult.java b/api/src/main/java/me/xiaoyan/point/api/pojo/vo/SignResult.java index ccc35c3..6db39c7 100644 --- a/api/src/main/java/me/xiaoyan/point/api/pojo/vo/SignResult.java +++ b/api/src/main/java/me/xiaoyan/point/api/pojo/vo/SignResult.java @@ -8,4 +8,12 @@ import lombok.experimental.Accessors; @Builder @Accessors(chain = true) public class SignResult { + /** + * 今日是否已经签到 + */ + private boolean signToday; + /** + * 连续签到天数 + */ + private int continuousDays; } diff --git a/api/src/main/java/me/xiaoyan/point/api/service/SignRecordService.java b/api/src/main/java/me/xiaoyan/point/api/service/SignRecordService.java index 1dd8966..dadb86e 100644 --- a/api/src/main/java/me/xiaoyan/point/api/service/SignRecordService.java +++ b/api/src/main/java/me/xiaoyan/point/api/service/SignRecordService.java @@ -3,7 +3,20 @@ package me.xiaoyan.point.api.service; import com.baomidou.mybatisplus.extension.service.IService; import me.xiaoyan.point.api.pojo.SignRecord; import me.xiaoyan.point.api.pojo.UserInfo; +import me.xiaoyan.point.api.pojo.vo.SignResult; public interface SignRecordService extends IService { + /** + * 今日是否签到 + * + * @return + */ + public SignResult signToday(int uid); + /** + * 签到信息 + * + * @return + */ + public SignResult info(int uid); } diff --git a/api/src/main/java/me/xiaoyan/point/api/service/impl/SignRecordServiceImpl.java b/api/src/main/java/me/xiaoyan/point/api/service/impl/SignRecordServiceImpl.java index 330c515..05351b6 100644 --- a/api/src/main/java/me/xiaoyan/point/api/service/impl/SignRecordServiceImpl.java +++ b/api/src/main/java/me/xiaoyan/point/api/service/impl/SignRecordServiceImpl.java @@ -1,12 +1,69 @@ package me.xiaoyan.point.api.service.impl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import me.xiaoyan.point.api.error.BizException; import me.xiaoyan.point.api.mapper.SignRecordMapper; import me.xiaoyan.point.api.pojo.SignRecord; +import me.xiaoyan.point.api.pojo.vo.SignResult; +import me.xiaoyan.point.api.service.PointRecordService; import me.xiaoyan.point.api.service.SignRecordService; +import me.xiaoyan.point.api.util.DateUtils; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import javax.annotation.Resource; +import java.util.*; @Service public class SignRecordServiceImpl extends ServiceImpl implements SignRecordService { + + @Resource + private PointRecordService pointRecordService; + + public boolean todayIsSign(int uid) { + return this.getBaseMapper().signCountByDate(uid, DateUtils.today()) > 0; + } + + @Transactional + @Override + public SignResult signToday(int uid) { + if (todayIsSign(uid)) throw BizException.create("今日已经签过了"); + // 计算连续的签到天数 连续签到积分的公式 = 天数 * 5 + int days = continuousDays(uid, true); + // TODO 完成签到 + SignRecord record = SignRecord.builder() + .uid(uid) + .point(5 * days) + .build(); + pointRecordService.record(uid, 5 * days, "签到" + days + "天,获得积分"); + save(record); + // 封装签到信息 + return SignResult.builder() + .signToday(true) + .continuousDays(days) + .build(); + } + + public int continuousDays(int uid, boolean isSign) { + // 如果是签到数据则只查6天,否则查询7天 + final List signRecords = this.getBaseMapper().selectRecentDaysRecord(uid, isSign ? 6 : 7); + List dates = new ArrayList<>(); + if (isSign) { + dates.add(new Date()); + } + signRecords.forEach(it -> dates.add(it.getCreateTime())); + Date[] dateArr = new Date[dates.size()]; + return DateUtils.continuousDays(dates.toArray(dateArr)); + } + + @Override + public SignResult info(int uid) { + return SignResult.builder() + .signToday(todayIsSign(uid)) // 今天是否签到 + .continuousDays(continuousDays(uid, false)) + .build(); + } + + } diff --git a/api/src/main/java/me/xiaoyan/point/api/util/DateUtils.java b/api/src/main/java/me/xiaoyan/point/api/util/DateUtils.java new file mode 100644 index 0000000..389691c --- /dev/null +++ b/api/src/main/java/me/xiaoyan/point/api/util/DateUtils.java @@ -0,0 +1,54 @@ +package me.xiaoyan.point.api.util; + +import lombok.SneakyThrows; + +import java.text.SimpleDateFormat; +import java.util.Date; + +public class DateUtils { + private final static SimpleDateFormat full = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private final static SimpleDateFormat date = new SimpleDateFormat("yyyy-MM-dd"); + + public static String today() { + return date.format(new Date()); + } + + public static String now() { + return full.format(new Date()); + } + + public static String formatDate(Date d) { + return date.format(d); + } + + public static String formatDatetime(Date d) { + return full.format(d); + } + + @SneakyThrows + public static Date parse(String str) { + return full.parse(str); + } + + public static int continuousDays(Date[] dates) { + int totalDays = 1; + for (int i = 1;i < dates.length; i ++){ + Date d1 = dates[i-1]; + Date d2 = dates[i]; + if(!isBetween(d1,d2)){ + break; + } + totalDays ++; + } + return totalDays; + } + + public static boolean isBetween(Date d1,Date d2){ + // 直接获取两个日期之间的毫秒,计算 + Date date1 = parse(formatDate(d1) + " 00:00:00"); + Date date2 = parse(formatDate(d2) + " 00:00:00"); + // 两个日期之间相差的毫秒数 + long diffTimes = Math.abs(date1.getTime() - date2.getTime()); + return diffTimes <= 24 * 3600 * 1000; + } +} diff --git a/api/src/main/resources/docs/每日签到.jpg b/api/src/main/resources/docs/每日签到.jpg new file mode 100644 index 0000000..cb8b2dc Binary files /dev/null and b/api/src/main/resources/docs/每日签到.jpg differ diff --git a/api/src/main/resources/mapper/SignRecordMapper.xml b/api/src/main/resources/mapper/SignRecordMapper.xml new file mode 100644 index 0000000..667a3ea --- /dev/null +++ b/api/src/main/resources/mapper/SignRecordMapper.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/api/src/test/java/me/xiaoyan/point/api/DateTests.java b/api/src/test/java/me/xiaoyan/point/api/DateTests.java new file mode 100644 index 0000000..cbcee3e --- /dev/null +++ b/api/src/test/java/me/xiaoyan/point/api/DateTests.java @@ -0,0 +1,38 @@ +package me.xiaoyan.point.api; + +import me.xiaoyan.point.api.util.DateUtils; +import org.junit.jupiter.api.Test; +import org.springframework.util.Assert; + +import java.util.Date; + +public class DateTests { + @Test + void testBetween() { + Date d1 = DateUtils.parse("2022-11-21 12:12:12"); + Date d2 = DateUtils.parse("2022-11-20 11:11:11"); + Date d3 = DateUtils.parse("2022-11-22 11:11:11"); + Assert.isTrue( + DateUtils.isBetween(d1, d2), "不是相邻的" + ); + Assert.isTrue( + !DateUtils.isBetween(d3, d2), "是相邻的" + ); + } + + @Test + void testContinuousDays() { + Date d1 = DateUtils.parse("2022-11-22 12:12:12"); + Date d2 = DateUtils.parse("2022-11-21 11:11:11"); + Date d3 = DateUtils.parse("2022-11-20 11:11:11"); + Date d4 = DateUtils.parse("2022-11-18 11:11:11"); + Date d5 = DateUtils.parse("2022-11-17 11:11:11"); + // 连续天数 + int days = DateUtils.continuousDays( + new Date[]{d1, d2, d3, d4, d5} + ); + System.out.println("连续天数" + days); + Assert.isTrue(days == 3, "连续天数不正确"); + + } +}