signin+userlevelsystem
Change-Id: I4d2b2660b23521817ae2ed6a55c6c322a20385ec
diff --git a/src/main/java/com/example/g8backend/controller/UserController.java b/src/main/java/com/example/g8backend/controller/UserController.java
index 121bc1a..8019967 100644
--- a/src/main/java/com/example/g8backend/controller/UserController.java
+++ b/src/main/java/com/example/g8backend/controller/UserController.java
@@ -8,6 +8,7 @@
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;
+import com.example.g8backend.service.ISigningService;
import java.util.List;
import java.util.Map;
@@ -90,4 +91,14 @@
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return (Long) authentication.getPrincipal();
}
+
+ @Autowired
+ private ISigningService signingService; // 修改接口名称
+
+ @PostMapping("/signin")
+ public String signIn() {
+ Long userId = getCurrentUserId(); // 假设从安全上下文中获取用户ID
+ boolean success = signingService.signIn(userId);
+ return success ? "签到成功" : "今日已签到";
+ }
}
diff --git a/src/main/java/com/example/g8backend/entity/User.java b/src/main/java/com/example/g8backend/entity/User.java
index 64f4f10..4c4a465 100644
--- a/src/main/java/com/example/g8backend/entity/User.java
+++ b/src/main/java/com/example/g8backend/entity/User.java
@@ -6,6 +6,8 @@
import lombok.Data;
import lombok.experimental.Accessors;
+import java.time.LocalDate;
+
@Data
@TableName("users")
@Accessors(chain = true)
@@ -17,6 +19,9 @@
private String password;
private String userName;
private String email;
+ private String userLevel; // 用户等级(lv1/lv2/lv3/vip)
+ private Integer signinCount;
+ private LocalDate lastSigninDate;
@Override
public String toString() {
diff --git a/src/main/java/com/example/g8backend/entity/UserSignin.java b/src/main/java/com/example/g8backend/entity/UserSignin.java
new file mode 100644
index 0000000..1af4b6c
--- /dev/null
+++ b/src/main/java/com/example/g8backend/entity/UserSignin.java
@@ -0,0 +1,17 @@
+package com.example.g8backend.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.time.LocalDate;
+
+@Data
+@TableName("user_signin")
+public class UserSignin {
+ @TableId(type = IdType.AUTO)
+ private Long signinId;
+ private Long userId;
+ private LocalDate signinDate;
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/g8backend/mapper/UserMapper.java b/src/main/java/com/example/g8backend/mapper/UserMapper.java
index 0a9e562..98e6c67 100644
--- a/src/main/java/com/example/g8backend/mapper/UserMapper.java
+++ b/src/main/java/com/example/g8backend/mapper/UserMapper.java
@@ -4,10 +4,18 @@
import com.example.g8backend.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
@Mapper
public interface UserMapper extends BaseMapper<User> {
User getUserByName(@Param("userName") String userName);
User getUserByEmail(@Param("email") String email);
User getUserByPasskey(@Param("passkey") String passkey);
+
+ @Select("SELECT * FROM users WHERE user_name = #{name}")
+ User selectByUserName(@Param("name") String name);
+
+ @Update("UPDATE users SET user_level = #{userLevel} WHERE user_id = #{userId}")
+ int updateUserLevel(@Param("userId") Long userId, @Param("userLevel") String userLevel);
}
diff --git a/src/main/java/com/example/g8backend/mapper/UserSigninMapper.java b/src/main/java/com/example/g8backend/mapper/UserSigninMapper.java
new file mode 100644
index 0000000..42a4736
--- /dev/null
+++ b/src/main/java/com/example/g8backend/mapper/UserSigninMapper.java
@@ -0,0 +1,14 @@
+package com.example.g8backend.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.example.g8backend.entity.UserSignin;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+@Mapper
+public interface UserSigninMapper extends BaseMapper<UserSignin> {
+
+ @Select("SELECT COUNT(*) FROM user_signin WHERE user_id = #{userId} AND signin_date = #{date}")
+ boolean existsByUserIdAndDate(@Param("userId") Long userId, @Param("date") String date);
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/g8backend/service/ISigningService.java b/src/main/java/com/example/g8backend/service/ISigningService.java
new file mode 100644
index 0000000..e408e6c
--- /dev/null
+++ b/src/main/java/com/example/g8backend/service/ISigningService.java
@@ -0,0 +1,7 @@
+package com.example.g8backend.service;
+
+import com.example.g8backend.dto.ApiResponse;
+
+public interface ISigningService {
+ boolean signIn(Long userId);
+}
\ No newline at end of file
diff --git a/src/main/java/com/example/g8backend/service/impl/SigninServiceImpl.java b/src/main/java/com/example/g8backend/service/impl/SigninServiceImpl.java
new file mode 100644
index 0000000..1f70520
--- /dev/null
+++ b/src/main/java/com/example/g8backend/service/impl/SigninServiceImpl.java
@@ -0,0 +1,52 @@
+package com.example.g8backend.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.example.g8backend.entity.User;
+import com.example.g8backend.entity.UserSignin;
+import com.example.g8backend.mapper.UserMapper;
+import com.example.g8backend.mapper.UserSigninMapper;
+import com.example.g8backend.service.ISigningService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import java.time.LocalDate;
+
+@Service
+@RequiredArgsConstructor
+public class SigninServiceImpl implements ISigningService{
+ private final UserMapper userMapper;
+ private final UserSigninMapper userSigninMapper;
+
+ @Override
+ @Transactional
+ public boolean signIn(Long userId) {
+ LocalDate today = LocalDate.now();
+ String todayStr = today.toString();
+
+ // 检查今日是否已签到
+ if (userSigninMapper.existsByUserIdAndDate(userId, todayStr)) {
+ return false; // 已签到
+ }
+
+ // 插入签到记录
+ UserSignin signin = new UserSignin();
+ signin.setUserId(userId);
+ signin.setSigninDate(today);
+ userSigninMapper.insert(signin);
+
+ // 更新用户信息
+ User user = userMapper.selectById(userId);
+ user.setSigninCount(user.getSigninCount() + 1);
+ user.setLastSigninDate(today);
+
+ // 根据签到次数升级等级 默认lv1 三次签到lv2 十次签到lv3
+ if (user.getSigninCount() >= 10) {
+ user.setUserLevel("lv3");
+ } else if (user.getSigninCount() >= 3) {
+ user.setUserLevel("lv2");
+ }
+
+ userMapper.updateById(user);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/schema.sql b/src/main/resources/schema.sql
index 1ee0c87..051ce5e 100644
--- a/src/main/resources/schema.sql
+++ b/src/main/resources/schema.sql
@@ -4,7 +4,11 @@
`user_name` VARCHAR(255) NOT NULL,
`password` VARCHAR(255) NOT NULL,
`email` VARCHAR(255) NOT NULL UNIQUE,
- `passkey` VARCHAR(255) NOT NULL UNIQUE
+ `passkey` VARCHAR(255) NOT NULL UNIQUE,
+ `user_level` ENUM('lv1', 'lv2', 'lv3', 'vip') DEFAULT 'lv1',
+ `signin_count` INT DEFAULT 0,
+ `last_signin_date` DATE,
+ INDEX `idx_user_level` (`user_level`) -- 按等级查询优化
);
-- 用户统计表
CREATE TABLE IF NOT EXISTS `user_stats` (
@@ -158,4 +162,12 @@
FOREIGN KEY (`post_id`) REFERENCES `posts`(`post_id`),
FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`),
FOREIGN KEY (`resolved_by`) REFERENCES `users`(`user_id`)
-);
\ No newline at end of file
+);
+
+CREATE TABLE IF NOT EXISTS `user_signin` (
+ `signin_id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '签到记录ID',
+ `user_id` BIGINT NOT NULL COMMENT '用户ID',
+ `signin_date` DATE NOT NULL COMMENT '签到日期',
+ FOREIGN KEY (`user_id`) REFERENCES `users`(`user_id`) ON DELETE CASCADE,
+ UNIQUE KEY `unique_user_daily_signin` (`user_id`, `signin_date`) -- 唯一约束:用户每日只能签到一次
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
\ No newline at end of file