马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
1.基础签到实现
- @Service
- @Slf4j
- public class SignInService {
- @Autowired
- private StringRedisTemplate redisTemplate;
-
- private static final String SIGN_KEY_PREFIX = "sign:";
-
- /**
- * 用户签到
- * @param userId 用户ID
- * @param date 签到日期
- */
- public boolean signIn(Long userId, LocalDate date) {
- try {
- String key = buildSignKey(userId, date);
- // 获取当月的第几天
- int dayOfMonth = date.getDayOfMonth();
-
- return Boolean.TRUE.equals(redisTemplate.opsForValue()
- .setBit(key, dayOfMonth - 1, true));
- } catch (Exception e) {
- log.error("签到失败", e);
- throw new RuntimeException("签到失败", e);
- }
- }
-
- /**
- * 检查用户是否签到
- */
- public boolean isSignedIn(Long userId, LocalDate date) {
- try {
- String key = buildSignKey(userId, date);
- int dayOfMonth = date.getDayOfMonth();
-
- return Boolean.TRUE.equals(redisTemplate.opsForValue()
- .getBit(key, dayOfMonth - 1));
- } catch (Exception e) {
- log.error("检查签到状态失败", e);
- throw new RuntimeException("检查签到状态失败", e);
- }
- }
-
- /**
- * 获取用户当月签到次数
- */
- public long getMonthSignCount(Long userId, LocalDate date) {
- try {
- String key = buildSignKey(userId, date);
- return redisTemplate.execute((RedisCallback<Long>) con ->
- con.bitCount(key.getBytes()));
- } catch (Exception e) {
- log.error("获取签到次数失败", e);
- throw new RuntimeException("获取签到次数失败", e);
- }
- }
-
- private String buildSignKey(Long userId, LocalDate date) {
- return String.format("%s%d:%s",
- SIGN_KEY_PREFIX, userId, date.format(DateTimeFormatter.ofPattern("yyyyMM")));
- }
- }
复制代码 2. 进阶功能实现
- @Service
- @Slf4j
- public class AdvancedSignInService {
- @Autowired
- private StringRedisTemplate redisTemplate;
-
- /**
- * 获取当月连续签到天数
- */
- public int getContinuousSignCount(Long userId, LocalDate date) {
- try {
- String key = buildSignKey(userId, date);
- int dayOfMonth = date.getDayOfMonth();
- int count = 0;
-
- // 从当天开始往前查找连续签到
- for (int i = dayOfMonth - 1; i >= 0; i--) {
- if (Boolean.TRUE.equals(redisTemplate.opsForValue().getBit(key, i))) {
- count++;
- } else {
- break;
- }
- }
- return count;
- } catch (Exception e) {
- log.error("获取连续签到天数失败", e);
- throw new RuntimeException("获取连续签到天数失败", e);
- }
- }
-
- /**
- * 获取当月签到日历
- */
- public List<Boolean> getMonthSignList(Long userId, LocalDate date) {
- try {
- String key = buildSignKey(userId, date);
- int dayCount = date.lengthOfMonth();
- List<Boolean> result = new ArrayList<>(dayCount);
-
- for (int i = 0; i < dayCount; i++) {
- result.add(Boolean.TRUE.equals(
- redisTemplate.opsForValue().getBit(key, i)));
- }
- return result;
- } catch (Exception e) {
- log.error("获取签到日历失败", e);
- throw new RuntimeException("获取签到日历失败", e);
- }
- }
-
- /**
- * 补签
- */
- public boolean retroactiveSign(Long userId, LocalDate date) {
- try {
- // 检查是否可以补签
- if (isSignedIn(userId, date) || date.isAfter(LocalDate.now())) {
- return false;
- }
-
- String key = buildSignKey(userId, date);
- int dayOfMonth = date.getDayOfMonth();
-
- return Boolean.TRUE.equals(redisTemplate.opsForValue()
- .setBit(key, dayOfMonth - 1, true));
- } catch (Exception e) {
- log.error("补签失败", e);
- throw new RuntimeException("补签失败", e);
- }
- }
-
- /**
- * 获取首次签到日期
- */
- public LocalDate getFirstSignDate(Long userId, LocalDate date) {
- try {
- String key = buildSignKey(userId, date);
- int dayCount = date.lengthOfMonth();
-
- for (int i = 0; i < dayCount; i++) {
- if (Boolean.TRUE.equals(
- redisTemplate.opsForValue().getBit(key, i))) {
- return date.withDayOfMonth(i + 1);
- }
- }
- return null;
- } catch (Exception e) {
- log.error("获取首次签到日期失败", e);
- throw new RuntimeException("获取首次签到日期失败", e);
- }
- }
- }
复制代码 3. 签到统计和嘉奖体系
- @Service
- @Slf4j
- public class SignInRewardService {
- @Autowired
- private AdvancedSignInService signInService;
-
- /**
- * 计算签到奖励
- */
- public SignInReward calculateReward(Long userId, LocalDate date) {
- int continuousDays = signInService.getContinuousSignCount(userId, date);
- long monthTotal = signInService.getMonthSignCount(userId, date);
-
- SignInReward reward = new SignInReward();
- reward.setPoints(calculatePoints(continuousDays));
- reward.setBonus(calculateBonus(monthTotal));
-
- return reward;
- }
-
- /**
- * 计算连续签到积分
- */
- private int calculatePoints(int continuousDays) {
- if (continuousDays >= 30) return 100;
- if (continuousDays >= 20) return 50;
- if (continuousDays >= 10) return 30;
- if (continuousDays >= 7) return 20;
- if (continuousDays >= 3) return 10;
- return 5;
- }
-
- /**
- * 计算月度签到奖励
- */
- private BigDecimal calculateBonus(long monthTotal) {
- if (monthTotal >= 28) return new BigDecimal("100");
- if (monthTotal >= 20) return new BigDecimal("50");
- if (monthTotal >= 15) return new BigDecimal("30");
- if (monthTotal >= 10) return new BigDecimal("20");
- return BigDecimal.ZERO;
- }
- }
- @Data
- public class SignInReward {
- private int points;
- private BigDecimal bonus;
- }
复制代码 4. Controller层实现
- @RestController
- @RequestMapping("/api/sign")
- @Slf4j
- public class SignInController {
- @Autowired
- private SignInService signInService;
-
- @Autowired
- private AdvancedSignInService advancedSignInService;
-
- @Autowired
- private SignInRewardService rewardService;
-
- @PostMapping("/in")
- public ResponseEntity<?> signIn(@RequestParam Long userId) {
- try {
- LocalDate today = LocalDate.now();
- boolean success = signInService.signIn(userId, today);
-
- if (success) {
- SignInReward reward = rewardService.calculateReward(userId, today);
- return ResponseEntity.ok(reward);
- }
-
- return ResponseEntity.badRequest().body("签到失败");
- } catch (Exception e) {
- log.error("签到异常", e);
- return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
- .body("系统错误");
- }
- }
-
- @GetMapping("/calendar")
- public ResponseEntity<?> getSignCalendar(
- @RequestParam Long userId,
- @RequestParam(required = false) String monthStr) {
- try {
- LocalDate date = monthStr != null ?
- YearMonth.parse(monthStr).atDay(1) : LocalDate.now();
-
- List<Boolean> calendar = advancedSignInService.getMonthSignList(userId, date);
- return ResponseEntity.ok(calendar);
- } catch (Exception e) {
- log.error("获取签到日历异常", e);
- return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
- .body("系统错误");
- }
- }
-
- @PostMapping("/retroactive")
- public ResponseEntity<?> retroactiveSign(
- @RequestParam Long userId,
- @RequestParam String dateStr) {
- try {
- LocalDate date = LocalDate.parse(dateStr);
- boolean success = advancedSignInService.retroactiveSign(userId, date);
-
- if (success) {
- return ResponseEntity.ok().build();
- }
-
- return ResponseEntity.badRequest().body("补签失败");
- } catch (Exception e) {
- log.error("补签异常", e);
- return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
- .body("系统错误");
- }
- }
- }
复制代码 5. 性能优化发起
- public List<Boolean> getMonthSignListWithPipeline(Long userId, LocalDate date) {
- String key = buildSignKey(userId, date);
- int dayCount = date.lengthOfMonth();
-
- List<Boolean> result = new ArrayList<>(dayCount);
- redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
- for (int i = 0; i < dayCount; i++) {
- connection.getBit(key.getBytes(), i);
- }
- return null;
- }).forEach(b -> result.add((Boolean) b));
-
- return result;
- }
复制代码- @Cacheable(value = "sign_calendar", key = "#userId + ':' + #date.format(T(java.time.format.DateTimeFormatter).ofPattern('yyyyMM'))")
- public List<Boolean> getMonthSignList(Long userId, LocalDate date) {
- // 实现逻辑
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |