signinCalendar+apifix

Change-Id: I9c64341669a4eff45f871f1c7a19045049d4c376
diff --git a/src/main/java/com/example/g8backend/controller/AdminController.java b/src/main/java/com/example/g8backend/controller/AdminController.java
index d8e4314..394e445 100644
--- a/src/main/java/com/example/g8backend/controller/AdminController.java
+++ b/src/main/java/com/example/g8backend/controller/AdminController.java
@@ -38,7 +38,7 @@
             @PathVariable Long reportId,
             @RequestParam String status,
             @RequestParam(required = false) String notes) {
-        Long adminId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
+        Long adminId = (Long) SecurityContextHolder.getContext().getAuthentication().getPrincipal();//这里之前不太对,service改了
         reportService.resolveReport(reportId, adminId, status, notes);
         return ApiResponse.success("举报处理完成");
     }
diff --git a/src/main/java/com/example/g8backend/controller/UserController.java b/src/main/java/com/example/g8backend/controller/UserController.java
index 8019967..f9d0de4 100644
--- a/src/main/java/com/example/g8backend/controller/UserController.java
+++ b/src/main/java/com/example/g8backend/controller/UserController.java
@@ -3,13 +3,16 @@
 import com.example.g8backend.dto.ApiResponse;
 import com.example.g8backend.entity.Message;
 import com.example.g8backend.entity.User;
+import com.example.g8backend.entity.UserSignin;
 import com.example.g8backend.service.IUserService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.format.annotation.DateTimeFormat;
 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.time.LocalDate;
 import java.util.List;
 import java.util.Map;
 
@@ -96,9 +99,20 @@
     private ISigningService signingService; // 修改接口名称
 
     @PostMapping("/signin")
-    public String signIn() {
-        Long userId = getCurrentUserId(); // 假设从安全上下文中获取用户ID
+    public ApiResponse<String> signIn() { // 修改返回类型为 ApiResponse
+        Long userId = getCurrentUserId();
         boolean success = signingService.signIn(userId);
-        return success ? "签到成功" : "今日已签到";
+        String message = success ? "签到成功" : "今日已签到";
+        return ApiResponse.success(message);
+    }
+
+    // 新增获取时间段内的签到记录接口
+    @GetMapping("/signins")
+    public ApiResponse<List<UserSignin>> getSignins(
+            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
+            @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate) {
+        Long userId = getCurrentUserId();
+        List<UserSignin> signins = signingService.getSigninsByDateRange(userId, startDate, endDate);
+        return ApiResponse.success(signins);
     }
 }
diff --git a/src/main/java/com/example/g8backend/service/ISigningService.java b/src/main/java/com/example/g8backend/service/ISigningService.java
index e408e6c..08b1760 100644
--- a/src/main/java/com/example/g8backend/service/ISigningService.java
+++ b/src/main/java/com/example/g8backend/service/ISigningService.java
@@ -1,7 +1,12 @@
 package com.example.g8backend.service;
 
 import com.example.g8backend.dto.ApiResponse;
+import com.example.g8backend.entity.UserSignin;
+
+import java.time.LocalDate;
+import java.util.List;
 
 public interface ISigningService {
     boolean signIn(Long userId);
+    List<UserSignin> getSigninsByDateRange(Long userId, LocalDate startDate, LocalDate endDate);
 }
\ 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
index 1f70520..429efa8 100644
--- a/src/main/java/com/example/g8backend/service/impl/SigninServiceImpl.java
+++ b/src/main/java/com/example/g8backend/service/impl/SigninServiceImpl.java
@@ -10,6 +10,7 @@
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import java.time.LocalDate;
+import java.util.List;
 
 @Service
 @RequiredArgsConstructor
@@ -49,4 +50,13 @@
         userMapper.updateById(user);
         return true;
     }
+
+    @Override
+    public List<UserSignin> getSigninsByDateRange(Long userId, LocalDate startDate, LocalDate endDate) {
+        QueryWrapper<UserSignin> queryWrapper = new QueryWrapper<>();
+        queryWrapper.eq("user_id", userId)
+                .between("signin_date", startDate, endDate)
+                .orderByAsc("signin_date");
+        return userSigninMapper.selectList(queryWrapper);
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/com/example/g8backend/service/SigninServiceImplTest.java b/src/test/java/com/example/g8backend/service/SigninServiceImplTest.java
index 298c4ac..48eec66 100644
--- a/src/test/java/com/example/g8backend/service/SigninServiceImplTest.java
+++ b/src/test/java/com/example/g8backend/service/SigninServiceImplTest.java
@@ -1,5 +1,6 @@
 package com.example.g8backend.service;
 
+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;
@@ -11,6 +12,10 @@
 import org.mockito.Mock;
 import org.mockito.junit.jupiter.MockitoExtension;
 import java.time.LocalDate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.*;
@@ -78,4 +83,104 @@
         assertEquals(10, user.getSigninCount());
         assertEquals("lv3", user.getUserLevel());
     }
+    @Test
+    public void testGetSigninsByDateRange_NormalCase() {
+        // 模拟输入参数
+        Long userId = 1L;
+        LocalDate startDate = LocalDate.of(2023, 10, 1);
+        LocalDate endDate = LocalDate.of(2023, 10, 31);
+
+        // 构建模拟数据
+        UserSignin signin1 = new UserSignin();
+        signin1.setSigninId(1L);
+        signin1.setUserId(userId);
+        signin1.setSigninDate(LocalDate.of(2023, 10, 5));
+
+        UserSignin signin2 = new UserSignin();
+        signin2.setSigninId(2L);
+        signin2.setUserId(userId);
+        signin2.setSigninDate(LocalDate.of(2023, 10, 15));
+
+        List<UserSignin> mockSignins = Arrays.asList(signin1, signin2);
+
+        when(userSigninMapper.selectList(any(QueryWrapper.class))).thenReturn(mockSignins);
+
+        // 执行方法
+        List<UserSignin> result = signinService.getSigninsByDateRange(userId, startDate, endDate);
+
+        // 断言结果
+        assertEquals(2, result.size());
+        assertEquals(LocalDate.of(2023, 10, 5), result.get(0).getSigninDate());
+        assertEquals(LocalDate.of(2023, 10, 15), result.get(1).getSigninDate());
+        verify(userSigninMapper).selectList(any(QueryWrapper.class));
+    }
+
+    @Test
+    public void testGetSigninsByDateRange_NoRecords() {
+        Long userId = 1L;
+        LocalDate startDate = LocalDate.of(2023, 11, 1);
+        LocalDate endDate = LocalDate.of(2023, 11, 30);
+
+        when(userSigninMapper.selectList(any())).thenReturn(Collections.emptyList());
+
+        List<UserSignin> result = signinService.getSigninsByDateRange(userId, startDate, endDate);
+
+        assertTrue(result.isEmpty());
+    }
+
+    @Test
+    public void testGetSigninsByDateRange_SingleDay() {
+        Long userId = 1L;
+        LocalDate date = LocalDate.of(2023, 10, 10);
+
+        UserSignin signin = new UserSignin();
+        signin.setSigninId(3L);
+        signin.setUserId(userId);
+        signin.setSigninDate(date);
+
+        // 修正:返回包含模拟数据的列表
+        when(userSigninMapper.selectList(any(QueryWrapper.class))).thenReturn(Collections.singletonList(signin));
+
+        List<UserSignin> result = signinService.getSigninsByDateRange(userId, date, date);
+
+        assertEquals(1, result.size());
+        assertEquals(date, result.get(0).getSigninDate());
+    }
+    @Test
+    public void testGetSigninsByDateRange_InvalidDateOrder() {
+        Long userId = 1L;
+        LocalDate startDate = LocalDate.of(2023, 10, 31);
+        LocalDate endDate = LocalDate.of(2023, 10, 1);
+
+        when(userSigninMapper.selectList(any())).thenReturn(Collections.emptyList());
+
+        List<UserSignin> result = signinService.getSigninsByDateRange(userId, startDate, endDate);
+
+        assertTrue(result.isEmpty());
+    }
+
+    public void testGetSigninsByDateRange_SortedOrder() {
+        Long userId = 1L;
+        LocalDate startDate = LocalDate.of(2023, 10, 1);
+        LocalDate endDate = LocalDate.of(2023, 10, 31);
+
+        // 模拟数据并按日期升序排列
+        UserSignin signin1 = new UserSignin();
+        signin1.setSigninId(1L);
+        signin1.setSigninDate(LocalDate.of(2023, 10, 5));
+
+        UserSignin signin2 = new UserSignin();
+        signin2.setSigninId(2L);
+        signin2.setSigninDate(LocalDate.of(2023, 10, 15));
+
+        List<UserSignin> mockSignins = Arrays.asList(signin1, signin2); // 直接提供已排序的数据
+
+        when(userSigninMapper.selectList(any(QueryWrapper.class))).thenReturn(mockSignins);
+
+        List<UserSignin> result = signinService.getSigninsByDateRange(userId, startDate, endDate);
+
+        // 验证顺序
+        assertEquals(LocalDate.of(2023, 10, 5), result.get(0).getSigninDate());
+        assertEquals(LocalDate.of(2023, 10, 15), result.get(1).getSigninDate());
+    }
 }
\ No newline at end of file