Selaa lähdekoodia

chore: auto bump version and changelog [skip ci]

iwt 1 kuukausi sitten
vanhempi
sitoutus
869f27a9db
100 muutettua tiedostoa jossa 835 lisäystä ja 239 poistoa
  1. 35 0
      cfc-backend/src/main/java/com/etotem/cfc/config/SortInterceptor.java
  2. 19 0
      cfc-backend/src/main/java/com/etotem/cfc/config/WebSortConfig.java
  3. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/HealthExerciseController.java
  4. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/HealthMealController.java
  5. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/HealthMeditationController.java
  6. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/HealthSleepController.java
  7. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/HealthWaterController.java
  8. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminButlerController.java
  9. 29 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminController.java
  10. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminCouponController.java
  11. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminNoticeController.java
  12. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminSubscriptionController.java
  13. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminSupplierController.java
  14. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminVendorController.java
  15. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/DimensionAdminController.java
  16. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/ReportParserAdminController.java
  17. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/SupplyManageController.java
  18. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/assessment/AssessmentResultController.java
  19. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/butler/ButlerController.java
  20. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideOrderController.java
  21. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideTeamController.java
  22. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/PlanReviewController.java
  23. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/notice/NoticeController.java
  24. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/stats/StatsController.java
  25. 10 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AIService.java
  26. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ActivityAdminService.java
  27. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ActivityFeedbackService.java
  28. 6 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ActivityRegistrationService.java
  29. 2 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ActivityService.java
  30. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AfterSalesService.java
  31. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ArticleCommentService.java
  32. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ArticleService.java
  33. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentAppointmentService.java
  34. 13 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentOrderService.java
  35. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentPermissionService.java
  36. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentQuotaService.java
  37. 16 0
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentService.java
  38. 9 0
      cfc-backend/src/main/java/com/etotem/cfc/service/BeijingNutritionService.java
  39. 6 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ButlerService.java
  40. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ButlerSessionService.java
  41. 6 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ChatMirrorService.java
  42. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CircleChallengeService.java
  43. 19 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CircleMatchService.java
  44. 8 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CircleService.java
  45. 2 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CognitiveService.java
  46. 9 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CommissionDistService.java
  47. 6 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java
  48. 10 0
      cfc-backend/src/main/java/com/etotem/cfc/service/CompatibilityService.java
  49. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ContactService.java
  50. 13 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ContentRecommendService.java
  51. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/DanKnowledgeBaseService.java
  52. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/DanReportUploadService.java
  53. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/DietRecordService.java
  54. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/service/DiscountService.java
  55. 1 0
      cfc-backend/src/main/java/com/etotem/cfc/service/DistributionService.java
  56. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/EcomSupplierService.java
  57. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/EmotionAlertService.java
  58. 10 0
      cfc-backend/src/main/java/com/etotem/cfc/service/EmotionCheckinService.java
  59. 21 0
      cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java
  60. 14 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FamilyChallengeService.java
  61. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FamilyCommissionService.java
  62. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FamilyEarningsService.java
  63. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FamilyHealthScoreService.java
  64. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FamilyMemberService.java
  65. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FinanceCheckinService.java
  66. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FiveDimensionScoreService.java
  67. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FiveDimensionSelfCheckService.java
  68. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/FoodService.java
  69. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/GameRecordService.java
  70. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/GrowthPlanService.java
  71. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/GrowthTaskService.java
  72. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/GuideApplicationService.java
  73. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/service/HealthCheckinService.java
  74. 13 0
      cfc-backend/src/main/java/com/etotem/cfc/service/HealthCircleService.java
  75. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/HealthInteractionService.java
  76. 8 0
      cfc-backend/src/main/java/com/etotem/cfc/service/HealthReportService.java
  77. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/IndicatorService.java
  78. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/InsurancePlanningService.java
  79. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/InsurancePolicyService.java
  80. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/InteractionLogService.java
  81. 9 0
      cfc-backend/src/main/java/com/etotem/cfc/service/InventoryService.java
  82. 2 0
      cfc-backend/src/main/java/com/etotem/cfc/service/MentalHealthScreenService.java
  83. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/service/NutritionDeficiencyService.java
  84. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/NutritionProductService.java
  85. 4 0
      cfc-backend/src/main/java/com/etotem/cfc/service/PendingRefundService.java
  86. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/PointsExchangeService.java
  87. 242 239
      cfc-backend/src/main/java/com/etotem/cfc/service/PointsService.java
  88. 6 0
      cfc-backend/src/main/java/com/etotem/cfc/service/PpointConfigService.java
  89. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/PpointService.java
  90. 10 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java
  91. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ProductRecommendationService.java
  92. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ProductService.java
  93. 3 0
      cfc-backend/src/main/java/com/etotem/cfc/service/PromotionMaterialService.java
  94. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/RecommendationService.java
  95. 8 0
      cfc-backend/src/main/java/com/etotem/cfc/service/RelationshipQualityService.java
  96. 8 0
      cfc-backend/src/main/java/com/etotem/cfc/service/RelationshipQuestionnaireService.java
  97. 5 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ReportSummaryService.java
  98. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/SupplyHierarchyService.java
  99. 8 0
      cfc-backend/src/main/java/com/etotem/cfc/service/SupplySettlementService.java
  100. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/SupplySystemService.java

+ 35 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/SortInterceptor.java

@@ -0,0 +1,35 @@
+package com.etotem.cfc.config;
+
+import com.etotem.cfc.util.SortContext;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class SortInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        String sortJson = request.getParameter("sort");
+        if (sortJson != null && !sortJson.isEmpty()) {
+            try {
+                @SuppressWarnings("unchecked")
+                List<Map<String, String>> sortSpecs = new com.fasterxml.jackson.databind.ObjectMapper()
+                        .readValue(sortJson, List.class);
+                SortContext.set(sortSpecs);
+            } catch (Exception e) {
+                // ignore invalid sort param
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        SortContext.clear();
+    }
+}

+ 19 - 0
cfc-backend/src/main/java/com/etotem/cfc/config/WebSortConfig.java

@@ -0,0 +1,19 @@
+package com.etotem.cfc.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+public class WebSortConfig implements WebMvcConfigurer {
+    @Autowired
+    private SortInterceptor sortInterceptor;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(sortInterceptor)
+                .addPathPatterns("/api/admin/**")
+                .addPathPatterns("/api/health/**");
+    }
+}

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthExerciseController.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "运动打卡")
 @RestController

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthMealController.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "饮食打卡")
 @RestController

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthMeditationController.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "冥想打卡")
 @RestController

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthSleepController.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "睡眠打卡")
 @RestController

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/HealthWaterController.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "喝水打卡")
 @RestController

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminButlerController.java

@@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import java.util.HashMap;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController
 @RequestMapping("/api/admin/butler")
@@ -55,6 +56,8 @@ public class AdminButlerController {
         }
         wrapper.orderByDesc(ButlerProfile::getCreatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ButlerProfile> result = butlerProfileMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();
@@ -132,6 +135,8 @@ public class AdminButlerController {
         }
         wrapper.orderByDesc(ButlerServiceRecord::getCreatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ButlerServiceRecord> result = butlerServiceRecordMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();
@@ -161,6 +166,8 @@ public class AdminButlerController {
         }
         wrapper.orderByDesc(ButlerCommissionSettlement::getCreatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ButlerCommissionSettlement> result = butlerCommissionSettlementMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();

+ 29 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminController.java

@@ -23,6 +23,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.ArrayList;
 import java.util.Collections;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController
 @RequestMapping("/api/admin")
@@ -96,6 +97,8 @@ public class AdminController {
         if (params.containsKey("phone") && params.get("phone") != null && !params.get("phone").toString().isEmpty()) {
             wrapper.like(User::getPhone, String.valueOf(params.get("phone")));
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -182,6 +185,8 @@ public class AdminController {
             }
         }
         wrapper.orderByDesc(User::getUpdatedAt).last("LIMIT 50");
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<User> users = userMapper.selectList(wrapper);
         // 清除密码
         for (User u : users) {
@@ -270,6 +275,8 @@ public class AdminController {
             wrapper.eq(Task::getFamilyId, familyId);
         }
         wrapper.orderByDesc(Task::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<Task> result = taskMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -305,6 +312,8 @@ public class AdminController {
             wrapper.eq(Reward::getFamilyId, familyId);
         }
         wrapper.orderByDesc(Reward::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<Reward> result = rewardMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -456,6 +465,8 @@ public class AdminController {
             wrapper.eq(PointsLog::getType, type);
         }
         wrapper.orderByDesc(PointsLog::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<PointsLog> result = pointsLogMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -488,6 +499,8 @@ public class AdminController {
             wrapper.like(Family::getName, name);
         }
         wrapper.orderByDesc(Family::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<Family> result = familyMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -515,11 +528,15 @@ public class AdminController {
         // 查询家长
         LambdaQueryWrapper<User> parentWrapper = new LambdaQueryWrapper<>();
         parentWrapper.eq(User::getFamilyId, id).eq(User::getRole, "parent");
+        SortUtil.applySort(parentWrapper);
+        SortUtil.applySort(parentWrapper);
         java.util.List<User> parents = userMapper.selectList(parentWrapper);
 
         // 查询孩子
         LambdaQueryWrapper<FamilyMember> childWrapper = new LambdaQueryWrapper<>();
         childWrapper.eq(FamilyMember::getFamilyId, id);
+        SortUtil.applySort(childWrapper);
+        SortUtil.applySort(childWrapper);
         java.util.List<FamilyMember> children = familyMemberMapper.selectList(childWrapper);
 
         Map<String, Object> result = new HashMap<>();
@@ -640,6 +657,8 @@ public class AdminController {
             wrapper.eq(TaskTemplate::getIsActive, isActive);
         }
         wrapper.orderByDesc(TaskTemplate::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<TaskTemplate> result = taskTemplateMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -692,6 +711,8 @@ public class AdminController {
             .isNotNull(User::getRealName)
             .orderByDesc(User::getUpdatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -798,6 +819,8 @@ public class AdminController {
             .isNotNull(User::getRealName)
             .orderByDesc(User::getUpdatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -1114,6 +1137,8 @@ public class AdminController {
         wrapper.orderByDesc(MemberUpgradeRecord::getCreatedAt);
 
         Page<MemberUpgradeRecord> pageParam = new Page<>(page, size);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<MemberUpgradeRecord> result = memberUpgradeRecordMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }
@@ -1327,6 +1352,8 @@ public class AdminController {
             String kw = params.get("keyword").toString();
             LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
             userWrapper.like(User::getNickname, kw).select(User::getId);
+            SortUtil.applySort(userWrapper);
+            SortUtil.applySort(userWrapper);
             java.util.List<User> matchedUsers = userMapper.selectList(userWrapper);
             java.util.List<Long> matchedIds = new java.util.ArrayList<>();
             for (User u : matchedUsers) { matchedIds.add(u.getId()); }
@@ -1338,6 +1365,8 @@ public class AdminController {
         }
         wrapper.orderByDesc(AssessmentAppointment::getCreatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<AssessmentAppointment> result = assessmentAppointmentMapper.selectPage(pageParam, wrapper);
 
         java.util.List<Map<String, Object>> list = new java.util.ArrayList<>();

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminCouponController.java

@@ -13,6 +13,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController
 @RequestMapping("/api/admin/coupon")

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminNoticeController.java

@@ -11,6 +11,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "公告管理", description = "平台公告的增删改查")
 @RestController
@@ -35,6 +36,8 @@ public class AdminNoticeController {
         q.orderByDesc(Notice::getCreatedAt);
         q.last("LIMIT " + ((page - 1) * size) + "," + size);
 
+        SortUtil.applySort(q);
+        SortUtil.applySort(q);
         List<Notice> list = noticeMapper.selectList(q);
         return Result.success(list);
     }

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminSubscriptionController.java

@@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController
 @RequestMapping("/api/admin/subscription")
@@ -39,6 +40,8 @@ public class AdminSubscriptionController {
         }
         wrapper.orderByDesc(MemberSubscription::getCreatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<MemberSubscription> subs = subscriptionMapper.selectList(wrapper);
         List<Map<String, Object>> list = new ArrayList<>();
         for (MemberSubscription sub : subs) {

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminSupplierController.java

@@ -13,6 +13,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "管理端-电商供应商管理")
 @RestController
@@ -35,6 +36,8 @@ public class AdminSupplierController {
             wrapper.like(EcomSupplier::getName, keyword);
         }
         wrapper.orderByDesc(EcomSupplier::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<EcomSupplier> result = ecomSupplierMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminVendorController.java

@@ -11,6 +11,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController
 @RequestMapping("/api/admin/vendor")
@@ -42,6 +43,8 @@ public class AdminVendorController {
         }
 
         wrapper.orderByDesc(User::getUpdatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/DimensionAdminController.java

@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "管理端-健康维度配置")
 @RestController
@@ -65,6 +66,8 @@ public class DimensionAdminController {
         Page<HealthDataSourceRecord> pageParam = new Page<>(page, size);
         LambdaQueryWrapper<HealthDataSourceRecord> wrapper = new LambdaQueryWrapper<HealthDataSourceRecord>()
             .orderByDesc(HealthDataSourceRecord::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<HealthDataSourceRecord> result = dataSourceRecordMapper.selectPage(pageParam, wrapper);
         return Result.success(result);
     }

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/ReportParserAdminController.java

@@ -17,6 +17,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController
 @RequestMapping("/api/admin/report-parser")

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/SupplyManageController.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 供应商管理控制器 - 供应商管理员角色专用
@@ -54,6 +55,8 @@ public class SupplyManageController {
         }
 
         wrapper.orderByDesc(User::getUpdatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/assessment/AssessmentResultController.java

@@ -15,6 +15,7 @@ import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "测评结果", description = "DAN认知测评结果查询")
 @RestController
@@ -80,6 +81,8 @@ public class AssessmentResultController {
                 .eq(DanAssessmentResult::getStatus, "completed")
                 .orderByDesc(DanAssessmentResult::getAssessmentDate)
                 .last("LIMIT " + size);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<DanAssessmentResult> results = danAssessmentResultMapper.selectList(wrapper);
 
         List<AssessmentHistoryItemDTO> list = new ArrayList<>();

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/butler/ButlerController.java

@@ -14,6 +14,7 @@ import javax.servlet.http.HttpServletRequest;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @RestController("butlerController")
 @RequestMapping("/api/butler")
@@ -71,6 +72,8 @@ public class ButlerController {
                 .eq(User::getReferrerId, userId)
                 .orderByDesc(User::getUpdatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideOrderController.java

@@ -13,6 +13,7 @@ import javax.annotation.Resource;
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "成长规划师订单", description = "成长规划师订单与佣金接口")
 @RestController
@@ -38,6 +39,8 @@ public class GuideOrderController {
         wrapper.orderByDesc(PackageOrder::getCreatedAt);
 
         Page<PackageOrder> pagination = new Page<>(page, size);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<PackageOrder> result = packageOrderMapper.selectPage(pagination, wrapper);
 
         Map<String, Object> response = new HashMap<>();
@@ -55,6 +58,7 @@ public class GuideOrderController {
         LambdaQueryWrapper<PackageOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(PackageOrder::getGuideId, guideId);
 
+        SortUtil.applySort(wrapper);
         Long totalOrders = packageOrderMapper.selectCount(wrapper);
         Long paidOrders = packageOrderMapper.selectCount(new LambdaQueryWrapper<PackageOrder>()
                 .eq(PackageOrder::getGuideId, guideId)

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideTeamController.java

@@ -14,6 +14,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "成长规划师团队", description = "成长规划师团队管理接口")
 @RestController
@@ -110,6 +111,7 @@ public class GuideTeamController {
             LambdaQueryWrapper<GuideHierarchy> teamCheck = new LambdaQueryWrapper<>();
             teamCheck.eq(GuideHierarchy::getChildId, userId)
                      .eq(GuideHierarchy::getStatus, "active");
+            SortUtil.applySort(teamCheck);
             GuideHierarchy existingTeam = guideHierarchyService.getOne(teamCheck);
 
             result.put("inTeam", existingTeam != null);
@@ -169,6 +171,7 @@ public class GuideTeamController {
         LambdaQueryWrapper<GuideHierarchy> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GuideHierarchy::getChildId, userId)
                .eq(GuideHierarchy::getStatus, "active");
+        SortUtil.applySort(wrapper);
         GuideHierarchy hierarchy = guideHierarchyService.getOne(wrapper);
 
         if (hierarchy == null) {

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/PlanReviewController.java

@@ -17,6 +17,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "指导师-方案审核", description = "指导师查看/审核/激活测评方案")
 @RestController

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/notice/NoticeController.java

@@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "公告", description = "前端公告列表")
 @RestController

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/stats/StatsController.java

@@ -35,6 +35,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import com.etotem.cfc.util.SortUtil;
 
 @Tag(name = "任务统计", description = "任务完成率分析")
 @RestController
@@ -94,6 +95,8 @@ public class StatsController {
                 .eq("status", "pending")), taskExecutor);
         CompletableFuture<List<Task>> recentTasksFuture = CompletableFuture.supplyAsync(() -> {
             QueryWrapper<Task> q = new QueryWrapper<Task>().orderByDesc("created_at").last("LIMIT 5");
+            SortUtil.applySort(q);
+            SortUtil.applySort(q);
             return taskMapper.selectList(q);
         }, taskExecutor);
 

+ 10 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AIService.java

@@ -19,6 +19,7 @@ import org.springframework.scheduling.annotation.Async;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * Dify AI API 封装
@@ -389,6 +390,7 @@ public class AIService {
         summaryQ.eq(AiConversationSummary::getConversationId, conversationId);
         summaryQ.orderByDesc(AiConversationSummary::getCreatedAt);
         summaryQ.last("LIMIT 1");
+        SortUtil.applySort(summaryQ);
         AiConversationSummary currentSummary = aiConversationSummaryMapper.selectOne(summaryQ);
         if (currentSummary != null) {
             ctx.put("conversation_summary", currentSummary.getSummaryText());
@@ -399,6 +401,8 @@ public class AIService {
         recentQ.eq(AiConversationSummary::getUserId, userId);
         recentQ.orderByDesc(AiConversationSummary::getCreatedAt);
         recentQ.last("LIMIT 5");
+        SortUtil.applySort(recentQ);
+        SortUtil.applySort(recentQ);
         List<AiConversationSummary> recentList = aiConversationSummaryMapper.selectList(recentQ);
         List<String> summaries = recentList.stream()
                 .map(AiConversationSummary::getSummaryText)
@@ -411,6 +415,8 @@ public class AIService {
         // 用户关键事实
         LambdaQueryWrapper<AiUserFact> factQ = new LambdaQueryWrapper<>();
         factQ.eq(AiUserFact::getUserId, userId);
+        SortUtil.applySort(factQ);
+        SortUtil.applySort(factQ);
         List<AiUserFact> facts = aiUserFactMapper.selectList(factQ);
         if (!facts.isEmpty()) {
             Map<String, String> factMap = new LinkedHashMap<>();
@@ -480,6 +486,8 @@ public class AIService {
         recentQ.eq(AiConversationSummary::getUserId, userId);
         recentQ.orderByDesc(AiConversationSummary::getCreatedAt);
         recentQ.last("LIMIT 3");
+        SortUtil.applySort(recentQ);
+        SortUtil.applySort(recentQ);
         List<AiConversationSummary> recentList = aiConversationSummaryMapper.selectList(recentQ);
         List<String> summaries = recentList.stream()
                 .map(AiConversationSummary::getSummaryText)
@@ -492,6 +500,8 @@ public class AIService {
         // 用户事实
         LambdaQueryWrapper<AiUserFact> factQ = new LambdaQueryWrapper<>();
         factQ.eq(AiUserFact::getUserId, userId);
+        SortUtil.applySort(factQ);
+        SortUtil.applySort(factQ);
         List<AiUserFact> facts = aiUserFactMapper.selectList(factQ);
         if (!facts.isEmpty()) {
             StringBuilder factSb = new StringBuilder();

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ActivityAdminService.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 后台活动管理业务逻辑
@@ -47,6 +48,8 @@ public class ActivityAdminService {
         }
         wrapper.orderByDesc(Activity::getUpdatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<Activity> pageResult = activityMapper.selectPage(new Page<>(page, size), wrapper);
         Map<String, Object> data = new HashMap<>();
         data.put("records", pageResult.getRecords());

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ActivityFeedbackService.java

@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ActivityFeedbackService {
@@ -33,6 +34,8 @@ public class ActivityFeedbackService {
         QueryWrapper<ActivityFeedback> wrapper = new QueryWrapper<>();
         wrapper.eq("activity_id", activityId)
                .orderByDesc("created_at");
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ActivityFeedback> list = activityFeedbackMapper.selectList(wrapper);
         return Result.success(list);
     }
@@ -44,6 +47,7 @@ public class ActivityFeedbackService {
             wrapper.eq("child_id", memberId);
         }
         wrapper.orderByDesc("created_at").last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         ActivityFeedback feedback = activityFeedbackMapper.selectOne(wrapper);
         return Result.success(feedback);
     }

+ 6 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ActivityRegistrationService.java

@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -130,6 +131,8 @@ public class ActivityRegistrationService {
                 .or().isNull(ActivityRegistration::getChildId));
         }
         wrapper.orderByDesc(ActivityRegistration::getRegisteredAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ActivityRegistration> pageResult = registrationMapper.selectPage(new Page<>(page, size), wrapper);
         List<Map<String, Object>> records = pageResult.getRecords().stream().map(reg -> {
             Map<String, Object> item = new HashMap<>();
@@ -155,6 +158,8 @@ public class ActivityRegistrationService {
         LambdaQueryWrapper<ActivityRegistration> wrapper = new LambdaQueryWrapper<ActivityRegistration>()
             .eq(ActivityRegistration::getActivityId, activityId).orderByDesc(ActivityRegistration::getRegisteredAt);
         if (status != null && !status.isEmpty()) wrapper.eq(ActivityRegistration::getStatus, status);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ActivityRegistration> list = registrationMapper.selectList(wrapper);
         List<Map<String, Object>> result = list.stream().map(reg -> {
             Map<String, Object> item = new HashMap<>();
@@ -249,6 +254,7 @@ public class ActivityRegistrationService {
             .eq(ActivityRegistration::getUserId, userId);
         if (status != null) wrapper.eq(ActivityRegistration::getStatus, status);
         wrapper.last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         return registrationMapper.selectOne(wrapper);
     }
 }

+ 2 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ActivityService.java

@@ -30,6 +30,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -80,6 +81,7 @@ public class ActivityService extends ServiceImpl<ActivityMapper, Activity> {
                     .or().eq(Activity::getVisibility, "all")
                     .or().isNull(Activity::getVisibility));
         }
+        SortUtil.applySort(query);
         Page<Activity> pageResult = this.page(new Page<>(page, size), query);
         boolean isGuest = (userId == null || userId <= 0);
         Long effectiveUserId = isGuest ? null : userId;

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AfterSalesService.java

@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class AfterSalesService {
@@ -62,6 +63,8 @@ public class AfterSalesService {
         if (status != null && !status.isEmpty()) {
             wrapper.eq(AfterSalesRequest::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<AfterSalesRequest> list = afterSalesRequestMapper.selectList(wrapper);
         return Result.success(list);
     }

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ArticleCommentService.java

@@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ArticleCommentService {
@@ -151,6 +152,8 @@ public class ArticleCommentService {
             wrapper.eq(ArticleComment::getArticleId, articleId);
         }
         wrapper.orderByDesc(ArticleComment::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return articleCommentMapper.selectList(wrapper);
     }
 
@@ -173,6 +176,8 @@ public class ArticleCommentService {
         }
 
         wrapper.orderByDesc(ArticleComment::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ArticleComment> comments = articleCommentMapper.selectList(wrapper);
 
         Map<Long, User> userCache = new HashMap<>();
@@ -221,6 +226,8 @@ public class ArticleCommentService {
         }
         wrapper.orderByDesc(ArticleComment::getCreatedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ArticleComment> p = articleCommentMapper.selectPage(new Page<>(page, size), wrapper);
         Page<Map<String, Object>> result = new Page<>(p.getCurrent(), p.getSize(), p.getTotal());
 

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ArticleService.java

@@ -28,6 +28,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -169,6 +170,8 @@ public class ArticleService {
                 .eq(Article::getId, articleId);
         articleMapper.update(null, wrapper);
 
+        SortUtil.applySort(wrapper);
+
         // 2. Save reading record
         ArticleReadingRecord record = new ArticleReadingRecord();
         record.setUserId(userId);

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentAppointmentService.java

@@ -12,6 +12,7 @@ import java.util.Date;
 import java.util.List;
 
 import lombok.extern.slf4j.Slf4j;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -94,6 +95,8 @@ public class AssessmentAppointmentService extends ServiceImpl<AssessmentAppointm
         LambdaQueryWrapper<AssessmentAppointment> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentAppointment::getUserId, userId);
         wrapper.orderByDesc(AssessmentAppointment::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return assessmentAppointmentMapper.selectList(wrapper);
     }
 
@@ -101,6 +104,8 @@ public class AssessmentAppointmentService extends ServiceImpl<AssessmentAppointm
         LambdaQueryWrapper<AssessmentAppointment> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentAppointment::getGuideId, guideId);
         wrapper.orderByDesc(AssessmentAppointment::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return assessmentAppointmentMapper.selectList(wrapper);
     }
 
@@ -108,6 +113,8 @@ public class AssessmentAppointmentService extends ServiceImpl<AssessmentAppointm
         LambdaQueryWrapper<AssessmentAppointment> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentAppointment::getAssessorId, assessorId);
         wrapper.orderByDesc(AssessmentAppointment::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return assessmentAppointmentMapper.selectList(wrapper);
     }
 

+ 13 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentOrderService.java

@@ -18,6 +18,7 @@ import java.util.Date;
 import java.util.List;
 
 import lombok.extern.slf4j.Slf4j;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -62,6 +63,7 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
     public boolean paySuccess(String orderNo, String transactionId, String payType) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        SortUtil.applySort(wrapper);
         AssessmentOrder order = this.getOne(wrapper);
         if (order == null) return false;
         order.setStatus("paid");
@@ -80,6 +82,7 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
     public boolean cancelOrder(String orderNo) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        SortUtil.applySort(wrapper);
         AssessmentOrder order = this.getOne(wrapper);
         if (order == null) return false;
         if (!"pending".equals(order.getStatus())) return false;
@@ -91,6 +94,7 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
     public boolean refundOrder(String orderNo) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        SortUtil.applySort(wrapper);
         AssessmentOrder order = this.getOne(wrapper);
         if (order == null) return false;
         if (!"paid".equals(order.getStatus())) return false;
@@ -102,6 +106,7 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
     public AssessmentOrder getByOrderNo(String orderNo) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        SortUtil.applySort(wrapper);
         return this.getOne(wrapper);
     }
 
@@ -109,18 +114,21 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getFamilyId, familyId);
         wrapper.orderByDesc(AssessmentOrder::getCreatedAt);
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
     public AssessmentOrder getByAppointmentId(Long appointmentId) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getAppointmentId, appointmentId);
+        SortUtil.applySort(wrapper);
         return this.getOne(wrapper);
     }
 
     public boolean markResultsReady(String orderNo) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        SortUtil.applySort(wrapper);
         AssessmentOrder order = this.getOne(wrapper);
         if (order == null || !"paid".equals(order.getStatus())) return false;
         order.setStatus("results_ready");
@@ -132,6 +140,7 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getUserId, userId);
         wrapper.orderByDesc(AssessmentOrder::getCreatedAt);
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
@@ -143,12 +152,14 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
         wrapper.eq(AssessmentOrder::getFamilyId, familyId);
         wrapper.in(AssessmentOrder::getStatus, "paid", "results_ready");
         wrapper.orderByDesc(AssessmentOrder::getCreatedAt);
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
     public boolean payOrder(String orderNo, String payType) {
         LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        SortUtil.applySort(wrapper);
         AssessmentOrder order = this.getOne(wrapper);
         if (order == null || !"pending".equals(order.getStatus())) return false;
         order.setStatus("paid");
@@ -234,6 +245,8 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
                    .eq(AssessmentAppointment::getStatus, 0)
                    .orderByDesc(AssessmentAppointment::getCreatedAt)
                    .last("LIMIT 1");
+            SortUtil.applySort(wrapper);
+            SortUtil.applySort(wrapper);
             List<AssessmentAppointment> list = assessmentAppointmentMapper.selectList(wrapper);
             if (list != null && !list.isEmpty()) {
                 order.setAppointmentId(list.get(0).getId());

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentPermissionService.java

@@ -13,6 +13,7 @@ import org.springframework.stereotype.Service;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 测评报告权限服务
@@ -65,6 +66,8 @@ public class AssessmentPermissionService {
                .eq(DanAssessmentResult::getStatus, "completed")
                .orderByDesc(DanAssessmentResult::getAssessmentDate);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return danAssessmentResultMapper.selectList(wrapper);
     }
 
@@ -77,6 +80,8 @@ public class AssessmentPermissionService {
                .eq(DanAssessmentResult::getStatus, "completed")
                .orderByDesc(DanAssessmentResult::getAssessmentDate);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return danAssessmentResultMapper.selectList(wrapper);
     }
 

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentQuotaService.java

@@ -14,6 +14,7 @@ import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.List;
 import java.util.Random;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class AssessmentQuotaService {
@@ -79,6 +80,8 @@ public class AssessmentQuotaService {
                 .gt(AssessmentQuota::getRemainingSessions, 0)
                 .gt(AssessmentQuota::getValidityEnd, new Date())
                 .orderByDesc(AssessmentQuota::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return mapper.selectList(wrapper);
     }
 

+ 16 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentService.java

@@ -31,6 +31,7 @@ import java.util.Date;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -63,12 +64,14 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
     public AssessmentMaterial getActiveMaterial() {
         LambdaQueryWrapper<AssessmentMaterial> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentMaterial::getStatus, "active");
+        SortUtil.applySort(wrapper);
         return this.getOne(wrapper);
     }
 
     public List<AssessmentMaterial> getMaterialList() {
         LambdaQueryWrapper<AssessmentMaterial> wrapper = new LambdaQueryWrapper<>();
         wrapper.orderByDesc(AssessmentMaterial::getCreatedAt);
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
@@ -87,6 +90,7 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
     public AssessmentPointsConfig getPointsConfig() {
         LambdaQueryWrapper<AssessmentPointsConfig> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentPointsConfig::getIsActive, 1);
+        SortUtil.applySort(wrapper);
         return pointsConfigMapper.selectOne(wrapper);
     }
 
@@ -110,6 +114,7 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
     public FamilyAssessmentConfig getFamilyConfig(Long familyId) {
         LambdaQueryWrapper<FamilyAssessmentConfig> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyAssessmentConfig::getFamilyId, familyId);
+        SortUtil.applySort(wrapper);
         return familyConfigMapper.selectOne(wrapper);
     }
 
@@ -155,6 +160,8 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
     public List<FamilyAssessmentConfig> getEnabledConfigs() {
         LambdaQueryWrapper<FamilyAssessmentConfig> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyAssessmentConfig::getIsEnabled, 1);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return familyConfigMapper.selectList(wrapper);
     }
 
@@ -164,6 +171,8 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         }
         LambdaQueryWrapper<FamilyAssessmentConfig> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyAssessmentConfig::getCreatedBy, teacherId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return familyConfigMapper.selectList(wrapper);
     }
 
@@ -192,6 +201,8 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         LambdaQueryWrapper<AssessmentRecord> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentRecord::getFamilyId, familyId);
         wrapper.orderByDesc(AssessmentRecord::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return recordMapper.selectList(wrapper);
     }
 
@@ -201,6 +212,7 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         wrapper.eq(AssessmentRecord::getStatus, "pending");
         wrapper.orderByDesc(AssessmentRecord::getCreatedAt);
         wrapper.last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         return recordMapper.selectOne(wrapper);
     }
 
@@ -270,6 +282,8 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         LambdaQueryWrapper<DanAssessmentResult> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(DanAssessmentResult::getTeacherId, guideId);
         wrapper.orderByDesc(DanAssessmentResult::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return danAssessmentResultMapper.selectList(wrapper);
     }
 
@@ -277,6 +291,7 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         LambdaQueryWrapper<DanAssessmentResult> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(DanAssessmentResult::getAppointmentId, appointmentId);
         wrapper.last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         return danAssessmentResultMapper.selectOne(wrapper);
     }
 
@@ -293,6 +308,7 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         wrapper.eq(DanAssessmentResult::getStatus, "completed");
         wrapper.orderByDesc(DanAssessmentResult::getAssessmentDate);
         wrapper.last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         return danAssessmentResultMapper.selectOne(wrapper);
     }
 }

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/BeijingNutritionService.java

@@ -23,6 +23,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 北京菌群报告 — 精准营养推荐服务
@@ -255,6 +256,8 @@ public class BeijingNutritionService {
         LambdaQueryWrapper<MealConfig> configWrapper = new LambdaQueryWrapper<>();
         configWrapper.eq(MealConfig::getFamilyId, familyId);
         configWrapper.eq(MealConfig::getConfigDateType, isWeekend(date) ? "weekend" : "weekday");
+        SortUtil.applySort(configWrapper);
+        SortUtil.applySort(configWrapper);
         List<MealConfig> mealConfigs = mealConfigMapper.selectList(configWrapper);
         
         // 2. 收集参与成员
@@ -279,6 +282,8 @@ public class BeijingNutritionService {
         if (participantIds.isEmpty()) {
             LambdaQueryWrapper<FamilyMember> memberWrapper = new LambdaQueryWrapper<>();
             memberWrapper.eq(FamilyMember::getFamilyId, familyId);
+            SortUtil.applySort(memberWrapper);
+            SortUtil.applySort(memberWrapper);
             List<FamilyMember> allMembers = familyMemberMapper.selectList(memberWrapper);
             for (FamilyMember m : allMembers) {
                 participantIds.add(m.getId());
@@ -299,6 +304,7 @@ public class BeijingNutritionService {
             // 查调研表
             LambdaQueryWrapper<com.etotem.cfc.entity.DietPreferences> prefWrapper = new LambdaQueryWrapper<>();
             prefWrapper.eq(com.etotem.cfc.entity.DietPreferences::getFamilyMemberId, memberId);
+            SortUtil.applySort(prefWrapper);
             com.etotem.cfc.entity.DietPreferences prefs = dietPreferencesMapper.selectOne(prefWrapper);
             
             if (prefs != null) {
@@ -326,11 +332,14 @@ public class BeijingNutritionService {
                          .eq(HealthReport::getReportType, "gut_flora")
                          .orderByDesc(HealthReport::getReportDate)
                          .last("LIMIT 1");
+            SortUtil.applySort(reportWrapper);
             HealthReport report = healthReportMapper.selectOne(reportWrapper);
             
             if (report != null) {
                 LambdaQueryWrapper<HealthGutFlora> floraWrapper = new LambdaQueryWrapper<>();
                 floraWrapper.eq(HealthGutFlora::getReportId, report.getId());
+                SortUtil.applySort(floraWrapper);
+                SortUtil.applySort(floraWrapper);
                 List<HealthGutFlora> floraList = healthGutFloraMapper.selectList(floraWrapper);
                 
                 Map<String, String> bacteriaStatus = new HashMap<>();

+ 6 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ButlerService.java

@@ -17,6 +17,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ButlerService {
@@ -180,6 +181,8 @@ public class ButlerService {
                 .isNotNull(User::getButlerStatus)
                 .eq(User::getButlerStatus, "approved")
                 .orderByDesc(User::getUpdatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         java.util.List<User> butlers = userMapper.selectList(wrapper);
         return Result.success(butlers);
     }
@@ -207,6 +210,8 @@ public class ButlerService {
         }
 
         wrapper.orderByDesc(User::getUpdatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<User> result = userMapper.selectPage(pageParam, wrapper);
 
         Map<String, Object> data = new HashMap<>();
@@ -296,6 +301,7 @@ public class ButlerService {
              .orderByAsc(ButlerProfile::getCreatedAt)  // round-robin by created_at
              .last("LIMIT 1");
 
+        SortUtil.applySort(query);
         ButlerProfile butler = butlerProfileMapper.selectOne(query);
 
         if (butler == null) {

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ButlerSessionService.java

@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ButlerSessionService {
@@ -88,6 +89,8 @@ public class ButlerSessionService {
         if (status != null && !status.isEmpty()) {
             wrapper.eq(ButlerSession::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return butlerSessionMapper.selectPage(pageParam, wrapper);
     }
 

+ 6 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ChatMirrorService.java

@@ -13,6 +13,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -37,6 +38,7 @@ public class ChatMirrorService {
         LambdaQueryWrapper<ChatConversation> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(ChatConversation::getDifyConversationId, difyConversationId);
         
+        SortUtil.applySort(queryWrapper);
         ChatConversation existing = chatConversationMapper.selectOne(queryWrapper);
         
         if (existing != null) {
@@ -101,6 +103,8 @@ public class ChatMirrorService {
         queryWrapper.eq(ChatConversation::getUserId, userId)
                    .orderByDesc(ChatConversation::getLastMessageAt);
         
+        SortUtil.applySort(queryWrapper);
+        SortUtil.applySort(queryWrapper);
         return chatConversationMapper.selectList(queryWrapper);
     }
 
@@ -114,6 +118,8 @@ public class ChatMirrorService {
         queryWrapper.eq(ChatMessage::getConversationId, conversationId)
                    .orderByAsc(ChatMessage::getCreatedAt);
         
+        SortUtil.applySort(queryWrapper);
+        SortUtil.applySort(queryWrapper);
         return chatMessageMapper.selectList(queryWrapper);
     }
 }

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CircleChallengeService.java

@@ -9,6 +9,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -22,9 +23,13 @@ public class CircleChallengeService {
         LambdaQueryWrapper<CircleChallenge> cw = new LambdaQueryWrapper<CircleChallenge>()
                 .eq(CircleChallenge::getCircleId, circleId)
                 .eq(CircleChallenge::getStatus, "active");
+        SortUtil.applySort(cw);
+        SortUtil.applySort(cw);
         List<CircleChallenge> active = circleChallengeMapper.selectList(cw);
         if (active.isEmpty()) {
             autoCreateChallenges(circleId);
+            SortUtil.applySort(cw);
+            SortUtil.applySort(cw);
             active = circleChallengeMapper.selectList(cw);
         }
         return active;
@@ -74,6 +79,8 @@ public class CircleChallengeService {
                 .eq(CircleChallenge::getCircleId, circleId)
                 .eq(CircleChallenge::getStatus, "completed")
                 .orderByDesc(CircleChallenge::getEndDate);
+        SortUtil.applySort(cw);
+        SortUtil.applySort(cw);
         return circleChallengeMapper.selectList(cw);
     }
 }

+ 19 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CircleMatchService.java

@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 圈子匹配引擎
@@ -128,6 +129,8 @@ public class CircleMatchService {
             // 查找孩子参与的活动
             LambdaQueryWrapper<ActivityRegistration> regWrapper = new LambdaQueryWrapper<ActivityRegistration>()
                     .eq(ActivityRegistration::getChildId, memberId);
+            SortUtil.applySort(regWrapper);
+            SortUtil.applySort(regWrapper);
             List<ActivityRegistration> myRegs = activityRegistrationMapper.selectList(regWrapper);
 
             for (ActivityRegistration reg : myRegs) {
@@ -137,6 +140,8 @@ public class CircleMatchService {
                 LambdaQueryWrapper<ActivityRegistration> sameActWrapper = new LambdaQueryWrapper<ActivityRegistration>()
                         .eq(ActivityRegistration::getActivityId, reg.getActivityId())
                         .ne(ActivityRegistration::getChildId, memberId);
+                SortUtil.applySort(sameActWrapper);
+                SortUtil.applySort(sameActWrapper);
                 List<ActivityRegistration> sameAct = activityRegistrationMapper.selectList(sameActWrapper);
 
                 if (!sameAct.isEmpty()) {
@@ -170,6 +175,8 @@ public class CircleMatchService {
                     .eq(DanAssessmentResult::getStatus, "completed")
                     .ne(DanAssessmentResult::getChildId, memberId)
                     .orderByDesc(DanAssessmentResult::getAssessmentDate);
+            SortUtil.applySort(qw);
+            SortUtil.applySort(qw);
             List<DanAssessmentResult> others = danAssessmentResultMapper.selectList(qw);
 
             // 按memberId去重取最新
@@ -210,6 +217,8 @@ public class CircleMatchService {
                     .eq(DanAssessmentResult::getStatus, "completed")
                     .ne(DanAssessmentResult::getChildId, memberId)
                     .orderByDesc(DanAssessmentResult::getAssessmentDate);
+            SortUtil.applySort(qw);
+            SortUtil.applySort(qw);
             List<DanAssessmentResult> others = danAssessmentResultMapper.selectList(qw);
 
             Map<Long, DanAssessmentResult> latestByChild = new HashMap<>();
@@ -248,6 +257,7 @@ public class CircleMatchService {
                     .eq(HealthReport::getStatus, "active")
                     .orderByDesc(HealthReport::getReportDate)
                     .last("LIMIT 1");
+            SortUtil.applySort(myHw);
             HealthReport myReport = healthReportMapper.selectOne(myHw);
             if (myReport == null || myReport.getOverallScore() == null) return result;
 
@@ -256,6 +266,8 @@ public class CircleMatchService {
                     .eq(HealthReport::getStatus, "active")
                     .ne(HealthReport::getUserId, memberId)
                     .orderByDesc(HealthReport::getReportDate);
+            SortUtil.applySort(othersHw);
+            SortUtil.applySort(othersHw);
             List<HealthReport> others = healthReportMapper.selectList(othersHw);
 
             Map<Long, HealthReport> latestByUser = new HashMap<>();
@@ -361,6 +373,7 @@ public class CircleMatchService {
             // 查找孩子所在的家庭
             LambdaQueryWrapper<FamilyMember> fmw = new LambdaQueryWrapper<FamilyMember>()
                     .eq(FamilyMember::getId, memberId);
+            SortUtil.applySort(fmw);
             FamilyMember member = familyMemberMapper.selectOne(fmw);
             if (member == null || member.getFamilyId() == null) return result;
 
@@ -374,11 +387,15 @@ public class CircleMatchService {
             LambdaQueryWrapper<Family> familyQw = new LambdaQueryWrapper<Family>()
                     .eq(Family::getTeacherId, teacherId)
                     .ne(Family::getId, member.getFamilyId());
+            SortUtil.applySort(familyQw);
+            SortUtil.applySort(familyQw);
             List<Family> sameTeacherFamilies = familyMapper.selectList(familyQw);
 
             for (Family f : sameTeacherFamilies) {
                 LambdaQueryWrapper<FamilyMember> childQw = new LambdaQueryWrapper<FamilyMember>()
                         .eq(FamilyMember::getFamilyId, f.getId());
+                SortUtil.applySort(childQw);
+                SortUtil.applySort(childQw);
                 List<FamilyMember> siblings = familyMemberMapper.selectList(childQw);
                 if (!siblings.isEmpty()) {
                     Map<String, Object> circle = getOrCreateRecommendation(
@@ -410,6 +427,7 @@ public class CircleMatchService {
             LambdaQueryWrapper<SocialCircle> qw = new LambdaQueryWrapper<SocialCircle>()
                     .eq(SocialCircle::getSourceId, sourceId)
                     .eq(SocialCircle::getType, type);
+            SortUtil.applySort(qw);
             SocialCircle existing = circleService.getOne(qw);
 
             if (existing != null) {
@@ -449,6 +467,7 @@ public class CircleMatchService {
                 .eq(DanAssessmentResult::getStatus, "completed")
                 .orderByDesc(DanAssessmentResult::getAssessmentDate)
                 .last("LIMIT 1");
+        SortUtil.applySort(qw);
         return danAssessmentResultMapper.selectOne(qw);
     }
 

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CircleService.java

@@ -17,6 +17,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class CircleService extends ServiceImpl<SocialCircleMapper, SocialCircle> {
@@ -36,6 +37,8 @@ public class CircleService extends ServiceImpl<SocialCircleMapper, SocialCircle>
         LambdaQueryWrapper<SocialCircleMember> mw = new LambdaQueryWrapper<SocialCircleMember>()
                 .eq(SocialCircleMember::getMemberId, memberId)
                 .eq(SocialCircleMember::getMemberType, memberType);
+        SortUtil.applySort(mw);
+        SortUtil.applySort(mw);
         List<SocialCircleMember> myMemberships = socialCircleMemberMapper.selectList(mw);
 
         if (myMemberships.isEmpty()) {
@@ -49,6 +52,7 @@ public class CircleService extends ServiceImpl<SocialCircleMapper, SocialCircle>
         // 查询圈子详情
         LambdaQueryWrapper<SocialCircle> cw = new LambdaQueryWrapper<SocialCircle>()
                 .in(SocialCircle::getId, circleIds);
+        SortUtil.applySort(cw);
         List<SocialCircle> circles = this.list(cw);
 
         // 组装结果
@@ -79,6 +83,8 @@ public class CircleService extends ServiceImpl<SocialCircleMapper, SocialCircle>
         LambdaQueryWrapper<SocialCircleMember> mw = new LambdaQueryWrapper<SocialCircleMember>()
                 .eq(SocialCircleMember::getMemberId, memberId)
                 .eq(SocialCircleMember::getMemberType, "child");
+        SortUtil.applySort(mw);
+        SortUtil.applySort(mw);
         List<SocialCircleMember> existing = socialCircleMemberMapper.selectList(mw);
         List<Long> joinedCircleIds = existing.stream()
                 .map(SocialCircleMember::getCircleId)
@@ -107,6 +113,7 @@ public class CircleService extends ServiceImpl<SocialCircleMapper, SocialCircle>
         LambdaQueryWrapper<SocialCircleMember> check = new LambdaQueryWrapper<SocialCircleMember>()
                 .eq(SocialCircleMember::getCircleId, circleId)
                 .eq(SocialCircleMember::getMemberId, memberId);
+        SortUtil.applySort(check);
         SocialCircleMember existing = socialCircleMemberMapper.selectOne(check);
         if (existing != null) {
             return true; // 已加入,视为成功
@@ -140,6 +147,7 @@ public class CircleService extends ServiceImpl<SocialCircleMapper, SocialCircle>
                 .eq(SocialCircleMember::getCircleId, circleId)
                 .eq(SocialCircleMember::getMemberId, memberId)
                 .eq(SocialCircleMember::getMemberType, memberType);
+        SortUtil.applySort(wrapper);
         int deleted = socialCircleMemberMapper.delete(wrapper);
         if (deleted > 0) {
             // 更新圈子成员数

+ 2 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CognitiveService.java

@@ -12,6 +12,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 认知维度服务 — 六维认知体系(感知、专注、记忆、逻辑、空间、加工速度)
@@ -41,6 +42,7 @@ public class CognitiveService {
                 .eq(DanAssessmentResult::getStatus, "completed")
                 .orderByDesc(DanAssessmentResult::getAssessmentDate)
                 .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         return danAssessmentResultMapper.selectOne(wrapper);
     }
 

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionDistService.java

@@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * P点分润服务
@@ -79,6 +80,8 @@ public class CommissionDistService {
                 .eq(ReferralTree::getChildId, buyerId)
                 .in(ReferralTree::getLevel, 1, 2)
                 .orderByAsc(ReferralTree::getLevel);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ReferralTree> referrals = referralTreeMapper.selectList(wrapper);
 
         if (referrals == null || referrals.isEmpty()) {
@@ -173,6 +176,8 @@ public class CommissionDistService {
                 .or()
                 .eq(CommissionDistLog::getLevel2UserId, userId)
                 .orderByDesc(CommissionDistLog::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return commissionDistLogMapper.selectList(wrapper);
     }
 
@@ -184,6 +189,8 @@ public class CommissionDistService {
                 .eq(CommissionDistLog::getStatus, "completed")
                 .and(w -> w.eq(CommissionDistLog::getLevel1UserId, userId)
                         .or().eq(CommissionDistLog::getLevel2UserId, userId));
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<CommissionDistLog> list = commissionDistLogMapper.selectList(wrapper);
         return list.stream()
                 .mapToInt(r -> {
@@ -211,6 +218,8 @@ public class CommissionDistService {
             wrapper.and(w -> w.eq(CommissionDistLog::getLevel1UserId, levelUserId)
                     .or().eq(CommissionDistLog::getLevel2UserId, levelUserId));
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return commissionDistLogMapper.selectPage(pageParam, wrapper);
     }
 }

+ 6 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java

@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Random;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class CommissionService {
@@ -428,6 +429,8 @@ public class CommissionService {
             wrapper.eq(CommissionRecord::getLevel, 2);
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<CommissionRecord> allRecords = commissionRecordMapper.selectList(wrapper);
 
         Map<Long, Map<String, Object>> memberMap = new LinkedHashMap<>();
@@ -462,6 +465,7 @@ public class CommissionService {
             } else if ("L2".equals(level)) {
                 orderWrapper.eq(CommissionRecord::getLevel, 2);
             }
+            SortUtil.applySort(orderWrapper);
             Long orderCount = commissionRecordMapper.selectCount(orderWrapper);
             memberInfo.put("orderCount", orderCount != null ? orderCount.intValue() : 0);
 
@@ -680,6 +684,8 @@ public class CommissionService {
 
         LambdaQueryWrapper<CommissionRecord> purchaseWrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId);
+        SortUtil.applySort(purchaseWrapper);
+        SortUtil.applySort(purchaseWrapper);
         List<CommissionRecord> allRecords = commissionRecordMapper.selectList(purchaseWrapper);
 
         long distinctBuyers = allRecords.stream()

+ 10 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/CompatibilityService.java

@@ -15,6 +15,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class CompatibilityService {
@@ -97,6 +98,8 @@ public class CompatibilityService {
         // Get all family members
         LambdaQueryWrapper<FamilyMember> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyMember::getFamilyId, familyId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyMember> members = familyMemberMapper.selectList(wrapper);
         if (members.isEmpty()) return dashboard;
 
@@ -145,12 +148,14 @@ public class CompatibilityService {
         // Look up both orderings
         qw.eq(ZodiacPairing::getZodiacCode1, zodiac1);
         qw.eq(ZodiacPairing::getZodiacCode2, zodiac2);
+        SortUtil.applySort(qw);
         ZodiacPairing pairing = zodiacPairingMapper.selectOne(qw);
         if (pairing == null) {
             // Try reverse order
             LambdaQueryWrapper<ZodiacPairing> reverseQw = new LambdaQueryWrapper<>();
             reverseQw.eq(ZodiacPairing::getZodiacCode1, zodiac2);
             reverseQw.eq(ZodiacPairing::getZodiacCode2, zodiac1);
+            SortUtil.applySort(reverseQw);
             pairing = zodiacPairingMapper.selectOne(reverseQw);
         }
 
@@ -240,11 +245,13 @@ public class CompatibilityService {
         LambdaQueryWrapper<BloodTypePairing> qw = new LambdaQueryWrapper<>();
         qw.eq(BloodTypePairing::getBloodType1, bt1);
         qw.eq(BloodTypePairing::getBloodType2, bt2);
+        SortUtil.applySort(qw);
         BloodTypePairing pairing = bloodTypePairingMapper.selectOne(qw);
         if (pairing == null) {
             LambdaQueryWrapper<BloodTypePairing> reverseQw = new LambdaQueryWrapper<>();
             reverseQw.eq(BloodTypePairing::getBloodType1, bt2);
             reverseQw.eq(BloodTypePairing::getBloodType2, bt1);
+            SortUtil.applySort(reverseQw);
             pairing = bloodTypePairingMapper.selectOne(reverseQw);
         }
 
@@ -413,11 +420,14 @@ public class CompatibilityService {
             LambdaQueryWrapper<ZodiacPairing> qw = new LambdaQueryWrapper<>();
             qw.eq(ZodiacPairing::getZodiacCode1, m1.getZodiac());
             qw.eq(ZodiacPairing::getZodiacCode2, m2.getZodiac());
+            SortUtil.applySort(qw);
             ZodiacPairing p = zodiacPairingMapper.selectOne(qw);
             if (p == null) {
                 LambdaQueryWrapper<ZodiacPairing> rqw = new LambdaQueryWrapper<>();
                 rqw.eq(ZodiacPairing::getZodiacCode1, m2.getZodiac());
                 rqw.eq(ZodiacPairing::getZodiacCode2, m1.getZodiac());
+                SortUtil.applySort(qw);
+                SortUtil.applySort(rqw);
                 p = zodiacPairingMapper.selectOne(rqw);
             }
             if (p != null) {

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ContactService.java

@@ -14,6 +14,7 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ContactService {
@@ -25,6 +26,8 @@ public class ContactService {
         LambdaQueryWrapper<Contact> query = new LambdaQueryWrapper<Contact>()
             .eq(Contact::getUserId, userId)
             .orderByDesc(Contact::getIntimacyLevel);
+        SortUtil.applySort(query);
+        SortUtil.applySort(query);
         List<Contact> list = contactMapper.selectList(query);
         return Result.success(toDTOList(list));
     }
@@ -80,6 +83,7 @@ public class ContactService {
         LambdaQueryWrapper<Contact> query = new LambdaQueryWrapper<Contact>()
             .eq(Contact::getUserId, userId)
             .eq(Contact::getPhone, phone);
+        SortUtil.applySort(query);
         Contact existing = contactMapper.selectOne(query);
         if (existing != null) {
             return Result.error("该联系人已在您的关系列表中");

+ 13 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ContentRecommendService.java

@@ -12,6 +12,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -125,6 +126,8 @@ public class ContentRecommendService {
                     .or().like(Article::getRelatedDimensions, dimensionCode.trim()));
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<Article> allArticles = articleMapper.selectList(wrapper);
         if (allArticles.isEmpty()) return new ArrayList<>();
 
@@ -217,6 +220,8 @@ public class ContentRecommendService {
                     .or().like(Article::getRelatedDimensions, dimensionCode.trim()));
         }
 
+        SortUtil.applySort(articleWrapper);
+        SortUtil.applySort(articleWrapper);
         List<Article> articles = articleMapper.selectList(articleWrapper);
         for (Article a : articles) {
             if (excludeIds.contains(a.getId())) continue;
@@ -264,6 +269,8 @@ private List<RecommendItemVO> recommendProducts(String dimensionCode, Long userI
                 .or().eq(Product::getDomain, dimensionCode.trim()));
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<Product> allProducts = productMapper.selectList(wrapper);
         if (allProducts.isEmpty()) return new ArrayList<>();
 
@@ -289,6 +296,8 @@ private List<RecommendItemVO> recommendProducts(String dimensionCode, Long userI
             } else {
                 orderWrapper.eq(ProductOrder::getBuyerId, userId);
             }
+            SortUtil.applySort(orderWrapper);
+            SortUtil.applySort(orderWrapper);
             userOrders = productOrderMapper.selectList(orderWrapper);
         }
 
@@ -366,6 +375,8 @@ private List<RecommendItemVO> recommendProducts(String dimensionCode, Long userI
                 .or().eq(Activity::getDimensionCode, dimensionCode.trim()));
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<Activity> allActivities = activityMapper.selectList(wrapper);
         if (allActivities.isEmpty()) return new ArrayList<>();
 
@@ -486,6 +497,8 @@ private List<RecommendItemVO> recommendProducts(String dimensionCode, Long userI
         } else {
             return ids;
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ProductOrder> orders = productOrderMapper.selectList(wrapper);
         for (ProductOrder o : orders) {
             ids.add(o.getProductId());

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/DanKnowledgeBaseService.java

@@ -19,6 +19,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class DanKnowledgeBaseService extends ServiceImpl<DanKnowledgeBaseMapper, DanKnowledgeBase> {
@@ -47,6 +48,8 @@ public class DanKnowledgeBaseService extends ServiceImpl<DanKnowledgeBaseMapper,
         }
         wrapper.orderByAsc(DanKnowledgeBase::getSort);
         this.page(p, wrapper);
+
+        SortUtil.applySort(wrapper);
         Map<String, Object> data = new HashMap<>();
         data.put("records", p.getRecords());
         data.put("total", p.getTotal());

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/DanReportUploadService.java

@@ -24,6 +24,7 @@ import java.util.Date;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class DanReportUploadService {
@@ -270,6 +271,8 @@ if (!DanReportUpload.DIM_MIND.equals(dimension) && !DanReportUpload.DIM_WISDOM.e
         if (dimension != null && !dimension.isEmpty()) {
             q.eq(DanReportUpload::getDimension, dimension);
         }
+        SortUtil.applySort(q);
+        SortUtil.applySort(q);
         List<DanReportUpload> list = uploadMapper.selectList(q);
         java.util.List<DanReportUploadVO> result = new java.util.ArrayList<>();
         for (DanReportUpload u : list) {

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/DietRecordService.java

@@ -18,6 +18,7 @@ import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -104,6 +105,8 @@ public class DietRecordService {
         LambdaQueryWrapper<DietRecord> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(DietRecord::getMemberId, memberId)
                .eq(DietRecord::getRecordDate, date);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<DietRecord> records = dietRecordMapper.selectList(wrapper);
         summary.put("records", records);
         return summary;
@@ -125,6 +128,8 @@ public class DietRecordService {
         wrapper.eq(DietRecord::getMemberId, memberId)
                .ge(DietRecord::getRecordDate, startDate)
                .le(DietRecord::getRecordDate, endDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<DietRecord> records = dietRecordMapper.selectList(wrapper);
         trend.put("records", records);
         trend.put("days", records.size());

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/DiscountService.java

@@ -10,6 +10,7 @@ import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class DiscountService {

+ 1 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/DistributionService.java

@@ -12,6 +12,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class DistributionService {

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/EcomSupplierService.java

@@ -12,6 +12,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class EcomSupplierService {
@@ -26,6 +27,8 @@ public class EcomSupplierService {
         if (keyword != null && !keyword.trim().isEmpty()) {
             wrapper.like(EcomSupplier::getName, keyword.trim());
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<EcomSupplier> result = supplierMapper.selectPage(pageParam, wrapper);
         Map<String, Object> data = new HashMap<>();
         data.put("records", result.getRecords());

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/EmotionAlertService.java

@@ -16,6 +16,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 情绪风险告警服务 —— 在每次情绪打卡完成后自动检查风险模式:
@@ -145,6 +146,8 @@ public class EmotionAlertService {
         LambdaQueryWrapper<EmotionAlert> wrapper = new LambdaQueryWrapper<EmotionAlert>()
                 .eq(resolved != null, EmotionAlert::getResolved, resolved)
                 .orderByDesc(EmotionAlert::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<EmotionAlert> all = emotionAlertMapper.selectList(wrapper);
         int total = all.size();
         int fromIndex = (page - 1) * size;

+ 10 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/EmotionCheckinService.java

@@ -19,6 +19,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -88,6 +89,8 @@ public class EmotionCheckinService {
         LambdaQueryWrapper<EmotionCheckin> wrapper = new LambdaQueryWrapper<EmotionCheckin>()
                 .eq(EmotionCheckin::getChildId, childId)
                 .orderByDesc(EmotionCheckin::getCheckinDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<EmotionCheckin> list = emotionCheckinMapper.selectList(wrapper);
 
         FamilyMember child = familyMemberMapper.selectById(childId);
@@ -110,6 +113,7 @@ public class EmotionCheckinService {
                 .eq(EmotionCheckin::getChildId, childId)
                 .orderByDesc(EmotionCheckin::getCreatedAt)
                 .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         EmotionCheckin checkin = emotionCheckinMapper.selectOne(wrapper);
         if (checkin == null) return null;
 
@@ -123,6 +127,8 @@ public class EmotionCheckinService {
         LambdaQueryWrapper<EmotionCheckin> wrapper = new LambdaQueryWrapper<EmotionCheckin>()
                 .eq(EmotionCheckin::getChildId, childId)
                 .orderByDesc(EmotionCheckin::getCheckinDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<EmotionCheckin> all = emotionCheckinMapper.selectList(wrapper);
 
         Calendar cal = Calendar.getInstance();
@@ -200,6 +206,8 @@ public class EmotionCheckinService {
         LambdaQueryWrapper<EmotionCheckin> wrapper = new LambdaQueryWrapper<EmotionCheckin>()
                 .eq(EmotionCheckin::getChildId, childId)
                 .orderByDesc(EmotionCheckin::getCheckinDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<EmotionCheckin> all = emotionCheckinMapper.selectList(wrapper);
 
         Map<String, Integer> breakdown = new HashMap<>();
@@ -229,6 +237,8 @@ public class EmotionCheckinService {
         LambdaQueryWrapper<EmotionCheckin> wrapper = new LambdaQueryWrapper<EmotionCheckin>()
                 .eq(EmotionCheckin::getChildId, childId)
                 .orderByDesc(EmotionCheckin::getCheckinDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<EmotionCheckin> all = emotionCheckinMapper.selectList(wrapper);
 
         Calendar cal = Calendar.getInstance();

+ 21 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java

@@ -17,6 +17,7 @@ import javax.annotation.Resource;
 
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 家庭能量沙盘 — 核心计算服务
@@ -234,6 +235,7 @@ public class EnergyService {
                         .last("LIMIT 1");
                 HealthReport report = null;
                 try {
+                    SortUtil.applySort(hrWrapper);
                     report = healthReportMapper.selectOne(hrWrapper);
                 } catch (Exception e) {
                     log.warn("健康报告查询异常, userIds={}: {}", childUserIds, e.getMessage());
@@ -310,6 +312,8 @@ public class EnergyService {
                 .eq(Task::getExecutorType, "parent")
                 .gt(Task::getCreatedAt, cal.getTime())
                 .ne(Task::getIsTemplate, 1);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<Task> tasks = taskMapper.selectList(wrapper);
         if (tasks.isEmpty()) return 0;
         long completed = tasks.stream().filter(t -> "completed".equals(t.getStatus())).count();
@@ -536,6 +540,7 @@ public class EnergyService {
                 .eq(DanAssessmentResult::getStatus, "completed")
                 .orderByDesc(DanAssessmentResult::getAssessmentDate)
                 .last("LIMIT 1");
+        SortUtil.applySort(qw);
         return danAssessmentResultMapper.selectOne(qw);
     }
 
@@ -569,6 +574,8 @@ public class EnergyService {
         // Game performance (±5%)
         LambdaQueryWrapper<GameRecord> gw = new LambdaQueryWrapper<GameRecord>()
                 .eq(GameRecord::getChildId, memberId);
+        SortUtil.applySort(gw);
+        SortUtil.applySort(gw);
         List<GameRecord> games = gameRecordMapper.selectList(gw);
         if (!games.isEmpty()) {
             double avgScore = games.stream()
@@ -592,6 +599,8 @@ public class EnergyService {
         // 1. 游戏得分 (0-100, 平均分)
         LambdaQueryWrapper<GameRecord> gw = new LambdaQueryWrapper<GameRecord>()
                 .eq(GameRecord::getChildId, memberId);
+        SortUtil.applySort(gw);
+        SortUtil.applySort(gw);
         List<GameRecord> games = gameRecordMapper.selectList(gw);
         if (!games.isEmpty()) {
             double avgScore = games.stream()
@@ -641,6 +650,8 @@ public class EnergyService {
         LambdaQueryWrapper<StreakMilestone> mw = new LambdaQueryWrapper<StreakMilestone>()
                 .orderByDesc(StreakMilestone::getDays)
                 .last("LIMIT 1");
+        SortUtil.applySort(mw);
+        SortUtil.applySort(mw);
         List<StreakMilestone> milestones = streakMilestoneMapper.selectList(mw);
         int maxMilestone = 30;
         if (!milestones.isEmpty() && milestones.get(0).getDays() != null) {
@@ -676,6 +687,8 @@ public class EnergyService {
                 .eq(DanAssessmentResult::getStatus, "completed")
                 .orderByDesc(DanAssessmentResult::getAssessmentDate)
                 .last("LIMIT 3");
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         List<DanAssessmentResult> results = danAssessmentResultMapper.selectList(qw);
         if (results.isEmpty()) return 0;
 
@@ -715,6 +728,8 @@ public class EnergyService {
                 .eq(PointsLog::getChildId, memberId)
                 .gt(PointsLog::getAmount, 0)
                 .gt(PointsLog::getCreatedAt, oneYearAgo);
+        SortUtil.applySort(earnedWrapper);
+        SortUtil.applySort(earnedWrapper);
         List<PointsLog> earnedLogs = pointsLogMapper.selectList(earnedWrapper);
         int earned = earnedLogs.stream()
                 .mapToInt(pl -> pl.getAmount() != null ? pl.getAmount() : 0)
@@ -725,6 +740,8 @@ public class EnergyService {
                 .ne(Task::getIsTemplate, 1)
                 .ne(Task::getStatus, "cancelled")
                 .gt(Task::getCreatedAt, oneYearAgo);
+        SortUtil.applySort(taskWrapper);
+        SortUtil.applySort(taskWrapper);
         List<Task> tasks = taskMapper.selectList(taskWrapper);
         int available = tasks.stream()
                 .mapToInt(t -> t.getPoints() != null ? t.getPoints() : 0)
@@ -1071,6 +1088,8 @@ public class EnergyService {
                 .ne(Task::getStatus, "cancelled")
                 .gt(Task::getCreatedAt, since);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<Task> tasks = taskMapper.selectList(wrapper);
 
         long total = tasks.size();
@@ -1455,6 +1474,8 @@ public class EnergyService {
             if (dim != null) wrapper.eq(EnergyLog::getDimensionId, dim.getId());
         }
         wrapper.orderByDesc(EnergyLog::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return energyLogMapper.selectPage(pageParam, wrapper);
     }
 

+ 14 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyChallengeService.java

@@ -18,6 +18,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -51,6 +52,8 @@ public class FamilyChallengeService {
                 .eq(FamilyChallenge::getFamilyId, familyId)
                 .in(FamilyChallenge::getStatus, "active", "pending")
                 .orderByDesc(FamilyChallenge::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyChallenge> active = familyChallengeMapper.selectList(wrapper);
 
         for (FamilyChallenge c : active) {
@@ -61,6 +64,8 @@ public class FamilyChallengeService {
             }
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         active = familyChallengeMapper.selectList(wrapper);
 
         fillProgress(active);
@@ -124,6 +129,8 @@ public class FamilyChallengeService {
             // 系统创建:写 participant 行(全员 agreed,与存量迁移口径一致)
             LambdaQueryWrapper<FamilyMember> mw = new LambdaQueryWrapper<FamilyMember>()
                     .eq(FamilyMember::getFamilyId, familyId);
+            SortUtil.applySort(mw);
+            SortUtil.applySort(mw);
             List<FamilyMember> members = familyMemberMapper.selectList(mw);
             for (FamilyMember m : members) {
                 FamilyChallengeParticipant participant = new FamilyChallengeParticipant();
@@ -289,6 +296,7 @@ public class FamilyChallengeService {
         LambdaQueryWrapper<FamilyChallengeProgress> wrapper = new LambdaQueryWrapper<FamilyChallengeProgress>()
                 .eq(FamilyChallengeProgress::getChallengeId, challengeId)
                 .eq(FamilyChallengeProgress::getChildId, childId);
+        SortUtil.applySort(wrapper);
         FamilyChallengeProgress progress = familyChallengeProgressMapper.selectOne(wrapper);
 
         // 5. 每日限次:同一 challengeId+childId 当天只能打卡一次(按 updatedAt 判断)
@@ -338,6 +346,8 @@ public class FamilyChallengeService {
         boolean isCompleted = false;
         LambdaQueryWrapper<FamilyChallengeProgress> pw = new LambdaQueryWrapper<FamilyChallengeProgress>()
                 .eq(FamilyChallengeProgress::getChallengeId, challenge.getId());
+        SortUtil.applySort(pw);
+        SortUtil.applySort(pw);
         List<FamilyChallengeProgress> progresses = familyChallengeProgressMapper.selectList(pw);
         int totalProgress = 0;
         for (FamilyChallengeProgress p : progresses) {
@@ -418,6 +428,8 @@ public class FamilyChallengeService {
                 .eq(FamilyChallenge::getFamilyId, familyId)
                 .eq(FamilyChallenge::getStatus, "completed")
                 .orderByDesc(FamilyChallenge::getEndDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyChallenge> history = familyChallengeMapper.selectList(wrapper);
         fillProgress(history);
         return history;
@@ -435,6 +447,8 @@ public class FamilyChallengeService {
 
             LambdaQueryWrapper<FamilyChallengeProgress> pw = new LambdaQueryWrapper<FamilyChallengeProgress>()
                     .eq(FamilyChallengeProgress::getChallengeId, c.getId());
+            SortUtil.applySort(pw);
+            SortUtil.applySort(pw);
             List<FamilyChallengeProgress> progresses = familyChallengeProgressMapper.selectList(pw);
 
             int total = 0;

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyCommissionService.java

@@ -13,6 +13,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class FamilyCommissionService {
@@ -76,6 +77,8 @@ public class FamilyCommissionService {
         LambdaQueryWrapper<FamilyCommission> wrapper = new LambdaQueryWrapper<FamilyCommission>()
                 .eq(FamilyCommission::getPromoterFamilyId, familyId)
                 .eq(FamilyCommission::getStatus, "paid");
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyCommission> list = familyCommissionMapper.selectList(wrapper);
         BigDecimal total = BigDecimal.ZERO;
         for (FamilyCommission c : list) {

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyEarningsService.java

@@ -12,6 +12,7 @@ import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class FamilyEarningsService {
@@ -278,6 +279,8 @@ public class FamilyEarningsService {
         }
         
         wrapper.orderByDesc(FamilyEarningsRecord::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return familyEarningsRecordMapper.selectList(wrapper);
     }
     

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyHealthScoreService.java

@@ -11,6 +11,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -34,6 +35,8 @@ public class FamilyHealthScoreService {
 
         LambdaQueryWrapper<FamilyMember> wrapper = new LambdaQueryWrapper<FamilyMember>()
                 .eq(FamilyMember::getFamilyId, familyId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyMember> allMembers = familyMemberMapper.selectList(wrapper);
 
         List<FamilyMember> children = new ArrayList<>();

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyMemberService.java

@@ -28,6 +28,7 @@ import java.util.Comparator;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class FamilyMemberService {
@@ -594,6 +595,8 @@ public class FamilyMemberService {
         if (memberId != null) {
             query.eq(FamilyMemberLog::getMemberId, memberId);
         }
+        SortUtil.applySort(query);
+        SortUtil.applySort(query);
         List<FamilyMemberLog> logs = familyMemberLogMapper.selectList(query);
         return Result.success(logs);
     }

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FinanceCheckinService.java

@@ -12,6 +12,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -42,6 +43,8 @@ public class FinanceCheckinService {
             wrapper.eq(FinanceCheckin::getChildId, memberId);
         }
         wrapper.orderByDesc(FinanceCheckin::getCheckinDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return financeCheckinMapper.selectList(wrapper);
     }
 
@@ -168,6 +171,8 @@ task.setExecutorId(memberId);
             wrapper.eq(FinanceCheckin::getChildId, memberId);
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FinanceCheckin> all = financeCheckinMapper.selectList(wrapper);
         long totalCheckins = all.size();
         long totalEnergy = all.stream()

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FiveDimensionScoreService.java

@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class FiveDimensionScoreService {
@@ -69,6 +70,8 @@ public class FiveDimensionScoreService {
                 .eq(FiveDimensionScore::getDimensionCode, dimensionCode)
                 .orderByDesc(FiveDimensionScore::getAssessedAt)
                 .last("LIMIT " + Math.min(limit, 100));
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         return fiveDimensionScoreMapper.selectList(qw);
     }
 
@@ -77,6 +80,8 @@ public class FiveDimensionScoreService {
         LambdaQueryWrapper<FiveDimensionScore> qw = new LambdaQueryWrapper<FiveDimensionScore>()
                 .eq(FiveDimensionScore::getFamilyId, familyId)
                 .orderByDesc(FiveDimensionScore::getAssessedAt);
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         List<FiveDimensionScore> all = fiveDimensionScoreMapper.selectList(qw);
         // 按 dimensionCode 分组取最新一条
         Map<String, Optional<FiveDimensionScore>> grouped = all.stream()
@@ -99,6 +104,8 @@ public class FiveDimensionScoreService {
         if (fromDate != null) qw.ge(FiveDimensionScore::getAssessedAt, fromDate);
         if (toDate != null) qw.le(FiveDimensionScore::getAssessedAt, toDate);
         qw.orderByAsc(FiveDimensionScore::getAssessedAt);
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         return fiveDimensionScoreMapper.selectList(qw);
     }
 }

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FiveDimensionSelfCheckService.java

@@ -22,6 +22,7 @@ import java.util.Date;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 五维家庭自检问卷服务(P0-1)
@@ -236,6 +237,7 @@ public class FiveDimensionSelfCheckService {
                 .eq(FiveDimensionSelfCheck::getUserId, userId)
                 .orderByDesc(FiveDimensionSelfCheck::getCreatedAt)
                 .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         FiveDimensionSelfCheck record = selfCheckMapper.selectOne(wrapper);
         return record != null ? toVO(record) : null;
     }
@@ -249,6 +251,8 @@ public class FiveDimensionSelfCheckService {
                 .eq(FiveDimensionSelfCheck::getUserId, userId)
                 .orderByDesc(FiveDimensionSelfCheck::getCreatedAt)
                 .last("LIMIT " + limit);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FiveDimensionSelfCheck> records = selfCheckMapper.selectList(wrapper);
         List<SelfCheckResultVO> result = new ArrayList<>();
         for (FiveDimensionSelfCheck record : records) {

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/FoodService.java

@@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -38,6 +39,8 @@ public class FoodService {
         } else {
             wrapper.orderByAsc(Food::getSortOrder);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return foodMapper.selectList(wrapper);
     }
 
@@ -85,6 +88,8 @@ public class FoodService {
         } else {
             wrapper.orderByAsc(Food::getSortOrder).orderByAsc(Food::getId);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return foodMapper.selectPage(new Page<>(page, size), wrapper);
     }
 

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/GameRecordService.java

@@ -13,6 +13,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -76,6 +77,8 @@ log.warn("游戏能量发放失败: memberId={}, gameCode={}, error={}",
         int offset = (page - 1) * size;
         wrapper.last("LIMIT " + size + " OFFSET " + offset);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<GameRecord> records = gameRecordMapper.selectList(wrapper);
 
         LambdaQueryWrapper<GameRecord> countWrapper = new LambdaQueryWrapper<GameRecord>()
@@ -83,6 +86,7 @@ log.warn("游戏能量发放失败: memberId={}, gameCode={}, error={}",
         if (gameCode != null && !gameCode.isEmpty()) {
             countWrapper.eq(GameRecord::getGameCode, gameCode);
         }
+        SortUtil.applySort(countWrapper);
         long total = gameRecordMapper.selectCount(countWrapper);
 
         Map<String, Object> result = new HashMap<>();
@@ -111,8 +115,11 @@ log.warn("游戏能量发放失败: memberId={}, gameCode={}, error={}",
     public Map<String, Object> getStats(Long memberId) {
         LambdaQueryWrapper<GameRecord> wrapper = new LambdaQueryWrapper<GameRecord>()
                 .eq(GameRecord::getChildId, memberId);
+        SortUtil.applySort(wrapper);
         long totalGames = gameRecordMapper.selectCount(wrapper);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<GameRecord> all = gameRecordMapper.selectList(wrapper);
         int totalPoints = 0;
         int bestScore = 0;

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/GrowthPlanService.java

@@ -8,6 +8,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class GrowthPlanService {
@@ -34,6 +35,8 @@ public class GrowthPlanService {
         LambdaQueryWrapper<GrowthPlan> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GrowthPlan::getChildId, memberId);
         wrapper.orderByDesc(GrowthPlan::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return growthPlanMapper.selectList(wrapper);
     }
 
@@ -41,6 +44,8 @@ public class GrowthPlanService {
         LambdaQueryWrapper<GrowthPlan> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GrowthPlan::getTeacherId, teacherId);
         wrapper.orderByDesc(GrowthPlan::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return growthPlanMapper.selectList(wrapper);
     }
 
@@ -50,6 +55,8 @@ public class GrowthPlanService {
         wrapper.eq(GrowthPlan::getStatus, "active");
         wrapper.orderByDesc(GrowthPlan::getCreatedAt);
         wrapper.last("LIMIT 1");
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<GrowthPlan> list = growthPlanMapper.selectList(wrapper);
         return list.isEmpty() ? null : list.get(0);
     }

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/GrowthTaskService.java

@@ -15,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -55,6 +56,8 @@ public List<Map<String, Object>> getTaskList(Long userId, Map<String, String> pa
 		queryWrapper.eq(GrowthTask::getDimension, dimension);
 	}
 
+	SortUtil.applySort(queryWrapper);
+	SortUtil.applySort(queryWrapper);
 	List<GrowthTask> tasks = growthTaskMapper.selectList(queryWrapper);
 
         String today = new SimpleDateFormat("yyyy-MM-dd").format(new Date());

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/GuideApplicationService.java

@@ -16,6 +16,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class GuideApplicationService extends ServiceImpl<GuideApplicationMapper, GuideApplication> {
@@ -158,6 +159,7 @@ public class GuideApplicationService extends ServiceImpl<GuideApplicationMapper,
         LambdaQueryWrapper<GuideApplication> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GuideApplication::getStatus, "pending")
                .orderByAsc(GuideApplication::getCreatedAt);
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
@@ -165,6 +167,7 @@ public class GuideApplicationService extends ServiceImpl<GuideApplicationMapper,
         LambdaQueryWrapper<GuideApplication> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GuideApplication::getUserId, userId)
                .orderByDesc(GuideApplication::getCreatedAt);
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
@@ -212,6 +215,8 @@ public class GuideApplicationService extends ServiceImpl<GuideApplicationMapper,
         LambdaQueryWrapper<GuideApplicationRecord> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GuideApplicationRecord::getApplicationId, applicationId)
                .orderByAsc(GuideApplicationRecord::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return guideApplicationRecordMapper.selectList(wrapper);
     }
 

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/HealthCheckinService.java

@@ -18,6 +18,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -57,6 +58,8 @@ public class HealthCheckinService {
             wrapper.eq(HealthCheckin::getChildId, childId);
         }
         wrapper.orderByDesc(HealthCheckin::getCheckinDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<HealthCheckin> list = healthCheckinMapper.selectList(wrapper);
         // Filter by yearMonth if provided (format: "2024-01")
         if (yearMonth != null && yearMonth.length() == 7) {
@@ -188,6 +191,7 @@ public class HealthCheckinService {
         if (childId != null) {
             wrapper.eq(HealthCheckin::getChildId, childId);
         }
+        SortUtil.applySort(wrapper);
         return healthCheckinMapper.selectCount(wrapper);
     }
 }

+ 13 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/HealthCircleService.java

@@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -36,6 +37,8 @@ public class HealthCircleService {
         LambdaQueryWrapper<HealthCircleMember> mw = new LambdaQueryWrapper<HealthCircleMember>()
                 .eq(HealthCircleMember::getFamilyId, familyId)
                 .eq(HealthCircleMember::getStatus, "active");
+        SortUtil.applySort(mw);
+        SortUtil.applySort(mw);
         List<HealthCircleMember> memberships = healthCircleMemberMapper.selectList(mw);
         if (memberships.isEmpty()) return new ArrayList<>();
 
@@ -46,6 +49,8 @@ public class HealthCircleService {
         LambdaQueryWrapper<HealthCircle> cw = new LambdaQueryWrapper<HealthCircle>()
                 .in(HealthCircle::getId, circleIds)
                 .eq(HealthCircle::getStatus, "active");
+        SortUtil.applySort(cw);
+        SortUtil.applySort(cw);
         return healthCircleMapper.selectList(cw);
     }
 
@@ -90,6 +95,7 @@ public class HealthCircleService {
         LambdaQueryWrapper<HealthCircle> cw = new LambdaQueryWrapper<HealthCircle>()
                 .eq(HealthCircle::getInviteCode, inviteCode)
                 .eq(HealthCircle::getStatus, "active");
+        SortUtil.applySort(cw);
         HealthCircle circle = healthCircleMapper.selectOne(cw);
         if (circle == null) {
             return Result.error("邀请码无效或圈已解散");
@@ -132,6 +138,7 @@ public class HealthCircleService {
                 .eq(HealthCircleMember::getCircleId, circleId)
                 .eq(HealthCircleMember::getFamilyId, familyId)
                 .eq(HealthCircleMember::getStatus, "active");
+        SortUtil.applySort(mw);
         HealthCircleMember membership = healthCircleMemberMapper.selectOne(mw);
         if (membership == null) {
             return Result.error("不在该圈中");
@@ -150,6 +157,8 @@ public class HealthCircleService {
         LambdaQueryWrapper<HealthCircleMember> mw = new LambdaQueryWrapper<HealthCircleMember>()
                 .eq(HealthCircleMember::getCircleId, circleId)
                 .eq(HealthCircleMember::getStatus, "active");
+        SortUtil.applySort(mw);
+        SortUtil.applySort(mw);
         List<HealthCircleMember> members = healthCircleMemberMapper.selectList(mw);
 
         List<Map<String, Object>> familyScores = new ArrayList<>();
@@ -179,6 +188,8 @@ public class HealthCircleService {
         LambdaQueryWrapper<CircleChallenge> cw = new LambdaQueryWrapper<CircleChallenge>()
                 .eq(CircleChallenge::getCircleId, circleId)
                 .orderByDesc(CircleChallenge::getCreatedAt);
+        SortUtil.applySort(cw);
+        SortUtil.applySort(cw);
         return circleChallengeMapper.selectList(cw);
     }
 
@@ -186,6 +197,7 @@ public class HealthCircleService {
         LambdaQueryWrapper<HealthCircleMember> mw = new LambdaQueryWrapper<HealthCircleMember>()
                 .eq(HealthCircleMember::getFamilyId, familyId)
                 .eq(HealthCircleMember::getStatus, "active");
+        SortUtil.applySort(mw);
         Long count = healthCircleMemberMapper.selectCount(mw);
         return count != null ? count.intValue() : 0;
     }
@@ -194,6 +206,7 @@ public class HealthCircleService {
         LambdaQueryWrapper<HealthCircleMember> mw = new LambdaQueryWrapper<HealthCircleMember>()
                 .eq(HealthCircleMember::getCircleId, circleId)
                 .eq(HealthCircleMember::getStatus, "active");
+        SortUtil.applySort(mw);
         Long count = healthCircleMemberMapper.selectCount(mw);
         return count != null ? count.intValue() : 0;
     }

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/HealthInteractionService.java

@@ -13,6 +13,7 @@ import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -55,6 +56,8 @@ public class HealthInteractionService {
                 .eq(HealthInteraction::getActionId, actionId)
                 .gt(HealthInteraction::getCreatedAt, sinceDate);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<HealthInteraction> existing = healthInteractionMapper.selectList(wrapper);
         return existing != null && !existing.isEmpty();
     }

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/HealthReportService.java

@@ -28,6 +28,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 健康检测报告服务 — 管理体检报告/菌群检测报告的录入与查询
@@ -728,6 +729,7 @@ public class HealthReportService {
         reportWrapper.eq(HealthReport::getReportType, "gut_flora");
         reportWrapper.orderByDesc(HealthReport::getCreatedAt);
         reportWrapper.last("LIMIT 1");
+        SortUtil.applySort(reportWrapper);
         HealthReport report = healthReportMapper.selectOne(reportWrapper);
         if (report == null) {
             return Collections.emptyList();
@@ -738,6 +740,8 @@ public class HealthReportService {
         indicatorWrapper.eq(HealthIndicator::getReportId, report.getId());
         indicatorWrapper.in(HealthIndicator::getCategory, "神经递质与激素", "短链脂肪酸");
         indicatorWrapper.orderByAsc(HealthIndicator::getSortOrder);
+        SortUtil.applySort(indicatorWrapper);
+        SortUtil.applySort(indicatorWrapper);
         return healthIndicatorMapper.selectList(indicatorWrapper);
     }
 
@@ -779,6 +783,8 @@ public class HealthReportService {
         LambdaQueryWrapper<HealthReport> wrapper = new LambdaQueryWrapper<HealthReport>()
                 .eq(HealthReport::getStatus, "active")
                 .orderByDesc(HealthReport::getReportDate);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         p = healthReportMapper.selectPage(p, wrapper);
 
         List<Map<String, Object>> records = new ArrayList<>();
@@ -985,6 +991,8 @@ public class HealthReportService {
         LambdaQueryWrapper<HealthReportDraft> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(HealthReportDraft::getStatus, "pending")
                 .orderByDesc(HealthReportDraft::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         p = draftMapper.selectPage(p, wrapper);
         return p.getRecords();
     }

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/IndicatorService.java

@@ -8,6 +8,7 @@ import com.etotem.cfc.mapper.IndicatorValueMapper;
 import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class IndicatorService {
@@ -24,12 +25,15 @@ public class IndicatorService {
         if (category != null) qw.eq(IndicatorDefinition::getCategory, category);
         if (status != null) qw.eq(IndicatorDefinition::getStatus, status);
         qw.orderByAsc(IndicatorDefinition::getSortOrder);
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         return indicatorDefinitionMapper.selectList(qw);
     }
 
     public IndicatorDefinition getDefinitionByCode(String code) {
         LambdaQueryWrapper<IndicatorDefinition> qw = new LambdaQueryWrapper<>();
         qw.eq(IndicatorDefinition::getCode, code);
+        SortUtil.applySort(qw);
         return indicatorDefinitionMapper.selectOne(qw);
     }
 
@@ -51,6 +55,8 @@ public class IndicatorService {
         LambdaQueryWrapper<IndicatorValue> qw = new LambdaQueryWrapper<>();
         qw.eq(IndicatorValue::getSourceType, sourceType);
         qw.eq(IndicatorValue::getSourceId, sourceId);
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         return indicatorValueMapper.selectList(qw);
     }
 
@@ -58,6 +64,7 @@ public class IndicatorService {
         LambdaQueryWrapper<IndicatorValue> qw = new LambdaQueryWrapper<>();
         qw.eq(IndicatorValue::getSourceType, sourceType);
         qw.eq(IndicatorValue::getSourceId, sourceId);
+        SortUtil.applySort(qw);
         indicatorValueMapper.delete(qw);
         for (IndicatorValue v : values) {
             v.setSourceType(sourceType);

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/InsurancePlanningService.java

@@ -17,6 +17,7 @@ import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 家庭保险规划服务
@@ -75,6 +76,8 @@ public class InsurancePlanningService {
                                     .stream()
                                     .map(m -> m.getId())
                                     .collect(Collectors.toList()));
+            SortUtil.applySort(policyWrapper);
+            SortUtil.applySort(policyWrapper);
             allPolicies = insurancePolicyMapper.selectList(policyWrapper);
         }
 

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/InsurancePolicyService.java

@@ -10,6 +10,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -28,6 +29,8 @@ public class InsurancePolicyService {
             wrapper.eq(InsurancePolicy::getStatus, status);
         }
         wrapper.orderByDesc(InsurancePolicy::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return insurancePolicyMapper.selectList(wrapper);
     }
 

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/InteractionLogService.java

@@ -20,6 +20,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class InteractionLogService {
@@ -103,6 +104,8 @@ public class InteractionLogService {
         }
         wrapper.orderByDesc(InteractionLog::getHappenedAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<InteractionLog> pageResult = interactionLogMapper.selectPage(new Page<>(page, size), wrapper);
         Page<InteractionLogVO> voPage = new Page<>(pageResult.getCurrent(), pageResult.getSize(), pageResult.getTotal());
 

+ 9 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/InventoryService.java

@@ -11,6 +11,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class InventoryService {
@@ -143,6 +144,8 @@ public class InventoryService {
         if (status != null && !status.isEmpty()) {
             wrapper.eq(InventoryInboundOrder::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<InventoryInboundOrder> result = inboundOrderMapper.selectPage(pageParam, wrapper);
         Map<String, Object> data = new HashMap<>();
         data.put("records", result.getRecords());
@@ -186,6 +189,8 @@ public class InventoryService {
                 wrapper.lt(InventoryTransaction::getCreatedAt, cal.getTime());
             } catch (Exception ignored) {}
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<InventoryTransaction> result = transactionMapper.selectPage(pageParam, wrapper);
         // 补充商品名称
         List<Map<String, Object>> enrichedRecords = new ArrayList<>();
@@ -348,6 +353,8 @@ public class InventoryService {
         if (status != null && !status.isEmpty()) {
             wrapper.eq(InventoryCountingRecord::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<InventoryCountingRecord> result = countingRecordMapper.selectPage(pageParam, wrapper);
         Map<String, Object> data = new HashMap<>();
         data.put("records", result.getRecords());
@@ -554,6 +561,8 @@ public class InventoryService {
                 wrapper.lt(InventoryTransaction::getCreatedAt, cal.getTime());
             } catch (Exception ignored) {}
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<InventoryTransaction> result = transactionMapper.selectPage(pageParam, wrapper);
         List<Map<String, Object>> enrichedRecords = new ArrayList<>();
         for (InventoryTransaction tx : result.getRecords()) {

+ 2 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/MentalHealthScreenService.java

@@ -21,6 +21,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -171,6 +172,7 @@ public class MentalHealthScreenService {
                 .eq(MentalHealthScreen::getScreenType, screenType)
                 .orderByDesc(MentalHealthScreen::getCompletedAt)
                 .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         MentalHealthScreen screen = mentalHealthScreenMapper.selectOne(wrapper);
         return screen != null ? toVO(screen) : null;
     }

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/NutritionDeficiencyService.java

@@ -15,6 +15,7 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -55,6 +56,8 @@ public class NutritionDeficiencyService {
             wrapper.eq(NutritionDeficiencyRecord::getReportId, reportId);
         }
         wrapper.orderByDesc(NutritionDeficiencyRecord::getSeverity);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return recordMapper.selectList(wrapper);
     }
 
@@ -196,6 +199,7 @@ public class NutritionDeficiencyService {
         LambdaQueryWrapper<NutritionDeficiencyRecord> wrapper = new LambdaQueryWrapper<NutritionDeficiencyRecord>()
             .eq(NutritionDeficiencyRecord::getChildId, childId)
             .eq(NutritionDeficiencyRecord::getReportId, reportId);
+        SortUtil.applySort(wrapper);
         recordMapper.delete(wrapper);
     }
 }

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/NutritionProductService.java

@@ -12,6 +12,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -81,6 +82,8 @@ public class NutritionProductService {
         }
         wrapper.eq(NutritionProduct::getStatus, 1);
         wrapper.orderByDesc(NutritionProduct::getUpdateTime);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return nutritionProductMapper.selectList(wrapper);
     }
 

+ 4 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/PendingRefundService.java

@@ -14,6 +14,7 @@ import javax.annotation.Resource;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 待退款服务
@@ -143,6 +144,7 @@ public class PendingRefundService {
             if ("product".equals(refund.getOrderType()) && refund.getOrderNo() != null) {
                 LambdaQueryWrapper<ProductOrder> wrapper = new LambdaQueryWrapper<>();
                 wrapper.eq(ProductOrder::getOrderNo, refund.getOrderNo());
+                SortUtil.applySort(wrapper);
                 ProductOrder order = productOrderMapper.selectOne(wrapper);
                 if (order != null) {
                     order.setRefundStatus(1);
@@ -181,6 +183,8 @@ public class PendingRefundService {
             wrapper.eq(PendingRefund::getOrderType, orderType);
         }
         
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return pendingRefundMapper.selectPage(pageParam, wrapper);
     }
 

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/PointsExchangeService.java

@@ -20,6 +20,7 @@ import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class PointsExchangeService {
@@ -56,6 +57,8 @@ public class PointsExchangeService {
             wrapper.eq(PointsExchangeProduct::getCategory, category);
         }
         wrapper.orderByAsc(PointsExchangeProduct::getSortOrder);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return pointsExchangeProductMapper.selectPage(pageParam, wrapper);
     }
 
@@ -293,6 +296,8 @@ public class PointsExchangeService {
         LambdaQueryWrapper<PointsExchangeRecord> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(PointsExchangeRecord::getUserId, userId)
                .orderByDesc(PointsExchangeRecord::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return pointsExchangeRecordMapper.selectList(wrapper);
     }
 

+ 242 - 239
cfc-backend/src/main/java/com/etotem/cfc/service/PointsService.java

@@ -1,241 +1,244 @@
-package com.etotem.cfc.service;
+package com.etotem.cfc.service;
 
 import com.etotem.cfc.service.api.PointsServiceInterface;
-
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.etotem.cfc.entity.FamilyMember;
-import com.etotem.cfc.entity.PointsLog;
-import com.etotem.cfc.entity.User;
-import com.etotem.cfc.mapper.FamilyMemberMapper;
-import com.etotem.cfc.mapper.PointsLogMapper;
-import com.etotem.cfc.mapper.UserMapper;
-import javax.annotation.Resource;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
-@Service
-public class PointsService implements PointsServiceInterface {
-
-    @Resource
-    private FamilyMemberMapper familyMemberMapper;
-
-    @Resource
-    private PointsLogMapper pointsLogMapper;
-
-    @Resource
-    private UserMapper userMapper;
-
-    public Map<String, Object> getBalance(Long memberId) {
-        FamilyMember child = familyMemberMapper.selectById(memberId);
-        if (child == null) {
-            return null;
-        }
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("balance", child.getTotalPoints());
-        // 下个月1日0点
-        java.util.Calendar cal = java.util.Calendar.getInstance();
-        cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
-        cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
-        cal.set(java.util.Calendar.MINUTE, 0);
-        cal.set(java.util.Calendar.SECOND, 0);
-        cal.add(java.util.Calendar.MONTH, 1);
-        result.put("expireDate", cal.getTime());
-        return result;
-    }
-
-    public Page<PointsLog> getPointsLogs(Long memberId, Integer page, Integer size) {
-        Page<PointsLog> pageParam = new Page<>(page, size);
-        return pointsLogMapper.selectPage(pageParam, new LambdaQueryWrapper<PointsLog>()
-                .eq(PointsLog::getChildId, memberId)
-                .orderByDesc(PointsLog::getCreatedAt));
-    }
-
-    @Transactional
-    public Map<String, Object> adjustPoints(Long memberId, Integer amount, String reason, String password, Long userId) {
-        // 验证密码(简化版,实际应从数据库验证)
-        // 这里需要调用UserService验证密码
-        
-        FamilyMember child = familyMemberMapper.selectById(memberId);
-        if (child == null) {
-            return null;
-        }
-
-        int oldBalance = child.getTotalPoints();
-        int newBalance = oldBalance + amount;
-        
-        if (newBalance < 0) {
-            return null; // 积分不能为负
-        }
-
-        // 更新积分
-        child.setTotalPoints(newBalance);
-        child.setUpdatedAt(new Date());
-        familyMemberMapper.updateById(child);
-
-        // 记录流水
-        PointsLog log = new PointsLog();
-        log.setChildId(memberId);
-        log.setAmount(amount);
-        log.setType("adjust");
-        log.setDescription(reason);
-        log.setCreatedAt(new Date());
-        pointsLogMapper.insert(log);
-
-        Map<String, Object> result = new HashMap<>();
-        result.put("newBalance", newBalance);
-        return result;
-    }
-
-    /** @return 系统积分余额 */
-    @Transactional
-    public int awardSystemPoints(Long memberId, int amount, String reason) {
-        if (amount <= 0) {
-            throw new IllegalArgumentException("系统积分数量必须为正数");
-        }
-
-        FamilyMember child = familyMemberMapper.selectById(memberId);
-        if (child == null) {
-            throw new RuntimeException("孩子不存在");
-        }
-
-        int newSystemPoints = (child.getSystemPoints() == null ? 0 : child.getSystemPoints()) + amount;
-        child.setSystemPoints(newSystemPoints);
-
-        int newTotal = (child.getTotalPoints() == null ? 0 : child.getTotalPoints()) + amount;
-        child.setTotalPoints(newTotal);
-
-        child.setUpdatedAt(new Date());
-        familyMemberMapper.updateById(child);
-
-        PointsLog log = new PointsLog();
-        log.setChildId(memberId);
-        log.setAmount(amount);
-        log.setType("earn");
-        log.setCategory("system");
-        log.setDescription(reason);
-        log.setCreatedAt(new Date());
-        pointsLogMapper.insert(log);
-
-        return newSystemPoints;
-    }
-
-    /**
-     * 心愿兑换扣除积分(家长审批通过后调用)
-     * @param memberId 孩子ID
-     * @param amount 扣除数量
-     * @return true=扣除成功, false=余额不足
-     */
-    @Transactional
-    public boolean deductForWish(Long memberId, Integer amount) {
-        if (amount == null || amount <= 0) {
-            return false;
-        }
-        return deductSystemPoints(memberId, amount, "心愿兑换扣除") >= 0;
-    }
-
-    /** @return 扣除后余额,余额不足返回-1 */
-    @Transactional
-    public int deductSystemPoints(Long memberId, int amount, String reason) {
-        if (amount <= 0) {
-            throw new IllegalArgumentException("扣除数量必须为正数");
-        }
-
-        FamilyMember child = familyMemberMapper.selectById(memberId);
-        if (child == null) {
-            throw new RuntimeException("孩子不存在");
-        }
-
-        int currentSystem = child.getSystemPoints() == null ? 0 : child.getSystemPoints();
-        if (currentSystem < amount) {
-            return -1;
-        }
-
-        int newSystemPoints = currentSystem - amount;
-        child.setSystemPoints(newSystemPoints);
-
-        int newTotal = (child.getTotalPoints() == null ? 0 : child.getTotalPoints()) - amount;
-        child.setTotalPoints(newTotal);
-
-        child.setUpdatedAt(new Date());
-        familyMemberMapper.updateById(child);
-
-        PointsLog log = new PointsLog();
-        log.setChildId(memberId);
-        log.setAmount(-amount);
-        log.setType("spend");
-        log.setCategory("system");
-        log.setDescription(reason);
-        log.setCreatedAt(new Date());
-        pointsLogMapper.insert(log);
-
-        return newSystemPoints;
-    }
-
-    public int getSystemPointsBalance(Long memberId) {
-        FamilyMember child = familyMemberMapper.selectById(memberId);
-        if (child == null) {
-            return 0;
-        }
-        return child.getSystemPoints() == null ? 0 : child.getSystemPoints();
-    }
-
-    public Page<PointsLog> getPointsLogsByCategory(Long memberId, String category, Integer page, Integer size) {
-        Page<PointsLog> pageParam = new Page<>(page, size);
-        LambdaQueryWrapper<PointsLog> wrapper = new LambdaQueryWrapper<PointsLog>()
-                .eq(PointsLog::getChildId, memberId);
-        if (category != null && !category.isEmpty()) {
-            wrapper.eq(PointsLog::getCategory, category);
-        }
-        wrapper.orderByDesc(PointsLog::getCreatedAt);
-        return pointsLogMapper.selectPage(pageParam, wrapper);
-    }
-
-    /**
-     * 检查并发放心愿兑换奖励
-     * @param memberId 孩子ID
-     * @param amount 奖励积分
-     * @return 发放后系统积分余额,余额不足返回-1
-     */
-    @Transactional
-    public int checkAndGrantReward(Long memberId, int amount) {
-        int currentBalance = getSystemPointsBalance(memberId);
-        if (currentBalance < amount) {
-            return -1;
-        }
-        return awardSystemPoints(memberId, amount, "心愿兑换奖励");
-    }
-
-    @Transactional
-    public boolean deductUserPoints(Long userId, int amount, String reason) {
-        User user = userMapper.selectById(userId);
-        if (user == null) {
-            return false;
-        }
-        int current = user.getTotalPoints() == null ? 0 : user.getTotalPoints();
-        if (current < amount) {
-            return false;
-        }
-        user.setTotalPoints(current - amount);
-        user.setUpdatedAt(new Date());
-        userMapper.updateById(user);
-        return true;
-    }
-
-    @Transactional
-    public void refundUserPoints(Long userId, int amount, String reason) {
-        User user = userMapper.selectById(userId);
-        if (user == null) {
-            return;
-        }
-        int current = user.getTotalPoints() == null ? 0 : user.getTotalPoints();
-        user.setTotalPoints(current + amount);
-        user.setUpdatedAt(new Date());
-        userMapper.updateById(user);
-    }
-}
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.etotem.cfc.entity.FamilyMember;
+import com.etotem.cfc.entity.PointsLog;
+import com.etotem.cfc.entity.User;
+import com.etotem.cfc.mapper.FamilyMemberMapper;
+import com.etotem.cfc.mapper.PointsLogMapper;
+import com.etotem.cfc.mapper.UserMapper;
+import javax.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
+
+@Service
+public class PointsService implements PointsServiceInterface {
+
+    @Resource
+    private FamilyMemberMapper familyMemberMapper;
+
+    @Resource
+    private PointsLogMapper pointsLogMapper;
+
+    @Resource
+    private UserMapper userMapper;
+
+    public Map<String, Object> getBalance(Long memberId) {
+        FamilyMember child = familyMemberMapper.selectById(memberId);
+        if (child == null) {
+            return null;
+        }
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("balance", child.getTotalPoints());
+        // 下个月1日0点
+        java.util.Calendar cal = java.util.Calendar.getInstance();
+        cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
+        cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
+        cal.set(java.util.Calendar.MINUTE, 0);
+        cal.set(java.util.Calendar.SECOND, 0);
+        cal.add(java.util.Calendar.MONTH, 1);
+        result.put("expireDate", cal.getTime());
+        return result;
+    }
+
+    public Page<PointsLog> getPointsLogs(Long memberId, Integer page, Integer size) {
+        Page<PointsLog> pageParam = new Page<>(page, size);
+        return pointsLogMapper.selectPage(pageParam, new LambdaQueryWrapper<PointsLog>()
+                .eq(PointsLog::getChildId, memberId)
+                .orderByDesc(PointsLog::getCreatedAt));
+    }
+
+    @Transactional
+    public Map<String, Object> adjustPoints(Long memberId, Integer amount, String reason, String password, Long userId) {
+        // 验证密码(简化版,实际应从数据库验证)
+        // 这里需要调用UserService验证密码
+        
+        FamilyMember child = familyMemberMapper.selectById(memberId);
+        if (child == null) {
+            return null;
+        }
+
+        int oldBalance = child.getTotalPoints();
+        int newBalance = oldBalance + amount;
+        
+        if (newBalance < 0) {
+            return null; // 积分不能为负
+        }
+
+        // 更新积分
+        child.setTotalPoints(newBalance);
+        child.setUpdatedAt(new Date());
+        familyMemberMapper.updateById(child);
+
+        // 记录流水
+        PointsLog log = new PointsLog();
+        log.setChildId(memberId);
+        log.setAmount(amount);
+        log.setType("adjust");
+        log.setDescription(reason);
+        log.setCreatedAt(new Date());
+        pointsLogMapper.insert(log);
+
+        Map<String, Object> result = new HashMap<>();
+        result.put("newBalance", newBalance);
+        return result;
+    }
+
+    /** @return 系统积分余额 */
+    @Transactional
+    public int awardSystemPoints(Long memberId, int amount, String reason) {
+        if (amount <= 0) {
+            throw new IllegalArgumentException("系统积分数量必须为正数");
+        }
+
+        FamilyMember child = familyMemberMapper.selectById(memberId);
+        if (child == null) {
+            throw new RuntimeException("孩子不存在");
+        }
+
+        int newSystemPoints = (child.getSystemPoints() == null ? 0 : child.getSystemPoints()) + amount;
+        child.setSystemPoints(newSystemPoints);
+
+        int newTotal = (child.getTotalPoints() == null ? 0 : child.getTotalPoints()) + amount;
+        child.setTotalPoints(newTotal);
+
+        child.setUpdatedAt(new Date());
+        familyMemberMapper.updateById(child);
+
+        PointsLog log = new PointsLog();
+        log.setChildId(memberId);
+        log.setAmount(amount);
+        log.setType("earn");
+        log.setCategory("system");
+        log.setDescription(reason);
+        log.setCreatedAt(new Date());
+        pointsLogMapper.insert(log);
+
+        return newSystemPoints;
+    }
+
+    /**
+     * 心愿兑换扣除积分(家长审批通过后调用)
+     * @param memberId 孩子ID
+     * @param amount 扣除数量
+     * @return true=扣除成功, false=余额不足
+     */
+    @Transactional
+    public boolean deductForWish(Long memberId, Integer amount) {
+        if (amount == null || amount <= 0) {
+            return false;
+        }
+        return deductSystemPoints(memberId, amount, "心愿兑换扣除") >= 0;
+    }
+
+    /** @return 扣除后余额,余额不足返回-1 */
+    @Transactional
+    public int deductSystemPoints(Long memberId, int amount, String reason) {
+        if (amount <= 0) {
+            throw new IllegalArgumentException("扣除数量必须为正数");
+        }
+
+        FamilyMember child = familyMemberMapper.selectById(memberId);
+        if (child == null) {
+            throw new RuntimeException("孩子不存在");
+        }
+
+        int currentSystem = child.getSystemPoints() == null ? 0 : child.getSystemPoints();
+        if (currentSystem < amount) {
+            return -1;
+        }
+
+        int newSystemPoints = currentSystem - amount;
+        child.setSystemPoints(newSystemPoints);
+
+        int newTotal = (child.getTotalPoints() == null ? 0 : child.getTotalPoints()) - amount;
+        child.setTotalPoints(newTotal);
+
+        child.setUpdatedAt(new Date());
+        familyMemberMapper.updateById(child);
+
+        PointsLog log = new PointsLog();
+        log.setChildId(memberId);
+        log.setAmount(-amount);
+        log.setType("spend");
+        log.setCategory("system");
+        log.setDescription(reason);
+        log.setCreatedAt(new Date());
+        pointsLogMapper.insert(log);
+
+        return newSystemPoints;
+    }
+
+    public int getSystemPointsBalance(Long memberId) {
+        FamilyMember child = familyMemberMapper.selectById(memberId);
+        if (child == null) {
+            return 0;
+        }
+        return child.getSystemPoints() == null ? 0 : child.getSystemPoints();
+    }
+
+    public Page<PointsLog> getPointsLogsByCategory(Long memberId, String category, Integer page, Integer size) {
+        Page<PointsLog> pageParam = new Page<>(page, size);
+        LambdaQueryWrapper<PointsLog> wrapper = new LambdaQueryWrapper<PointsLog>()
+                .eq(PointsLog::getChildId, memberId);
+        if (category != null && !category.isEmpty()) {
+            wrapper.eq(PointsLog::getCategory, category);
+        }
+        wrapper.orderByDesc(PointsLog::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
+        return pointsLogMapper.selectPage(pageParam, wrapper);
+    }
+
+    /**
+     * 检查并发放心愿兑换奖励
+     * @param memberId 孩子ID
+     * @param amount 奖励积分
+     * @return 发放后系统积分余额,余额不足返回-1
+     */
+    @Transactional
+    public int checkAndGrantReward(Long memberId, int amount) {
+        int currentBalance = getSystemPointsBalance(memberId);
+        if (currentBalance < amount) {
+            return -1;
+        }
+        return awardSystemPoints(memberId, amount, "心愿兑换奖励");
+    }
+
+    @Transactional
+    public boolean deductUserPoints(Long userId, int amount, String reason) {
+        User user = userMapper.selectById(userId);
+        if (user == null) {
+            return false;
+        }
+        int current = user.getTotalPoints() == null ? 0 : user.getTotalPoints();
+        if (current < amount) {
+            return false;
+        }
+        user.setTotalPoints(current - amount);
+        user.setUpdatedAt(new Date());
+        userMapper.updateById(user);
+        return true;
+    }
+
+    @Transactional
+    public void refundUserPoints(Long userId, int amount, String reason) {
+        User user = userMapper.selectById(userId);
+        if (user == null) {
+            return;
+        }
+        int current = user.getTotalPoints() == null ? 0 : user.getTotalPoints();
+        user.setTotalPoints(current + amount);
+        user.setUpdatedAt(new Date());
+        userMapper.updateById(user);
+    }
+}

+ 6 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/PpointConfigService.java

@@ -19,6 +19,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * P点配置管理 — 综合品类级比例 + 商品级固定值
@@ -57,6 +58,7 @@ public class PpointConfigService {
                 .and(w -> w.isNull(CategoryPpoint::getEndDate).or().ge(CategoryPpoint::getEndDate, now))
                 .orderByDesc(CategoryPpoint::getStartDate)
                 .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         CategoryPpoint record = categoryPpointMapper.selectOne(wrapper);
         if (record != null && record.getRatio() != null && record.getRatio() > 0) {
             return record.getRatio();
@@ -79,6 +81,7 @@ public class PpointConfigService {
                 .and(w -> w.isNull(ProductPpoint::getEndDate).or().ge(ProductPpoint::getEndDate, now))
                 .orderByDesc(ProductPpoint::getStartDate)
                 .last("LIMIT 1");
+        SortUtil.applySort(pw);
         ProductPpoint productPpoint = productPpointMapper.selectOne(pw);
         if (productPpoint != null && productPpoint.getPpoint() != null && productPpoint.getPpoint() > 0) {
             return productPpoint.getPpoint();
@@ -106,6 +109,7 @@ public class PpointConfigService {
     public void saveCategoryRatio(Long categoryId, Integer ratio, Date startDate, Date endDate, Long adminUserId) {
         LambdaQueryWrapper<CategoryPpoint> wrapper = new LambdaQueryWrapper<CategoryPpoint>()
                 .eq(CategoryPpoint::getCategoryId, categoryId);
+        SortUtil.applySort(wrapper);
         CategoryPpoint existing = categoryPpointMapper.selectOne(wrapper);
         if (existing != null) {
             existing.setRatio(ratio);
@@ -143,6 +147,8 @@ public class PpointConfigService {
     public Map<String, Object> adminCategoryList(Page<CategoryPpoint> pageParam, String keyword) {
         LambdaQueryWrapper<CategoryPpoint> wrapper = new LambdaQueryWrapper<CategoryPpoint>()
                 .orderByDesc(CategoryPpoint::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<CategoryPpoint> page = categoryPpointMapper.selectPage(pageParam, wrapper);
         List<CategoryPpoint> records = page.getRecords();
 

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/PpointService.java

@@ -16,6 +16,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class PpointService {
@@ -50,6 +51,7 @@ public class PpointService {
                 .and(w -> w.isNull(ProductPpoint::getEndDate).or().ge(ProductPpoint::getEndDate, now))
                 .orderByDesc(ProductPpoint::getStartDate)
                 .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         ProductPpoint record = productPpointMapper.selectOne(wrapper);
 
         if (record != null && record.getPpoint() != null && record.getPpoint() > 0) {
@@ -73,6 +75,7 @@ public class PpointService {
         // Check if an existing record exists for this product
         LambdaQueryWrapper<ProductPpoint> wrapper = new LambdaQueryWrapper<ProductPpoint>()
                 .eq(ProductPpoint::getProductId, productId);
+        SortUtil.applySort(wrapper);
         ProductPpoint existing = productPpointMapper.selectOne(wrapper);
 
         if (existing != null) {
@@ -122,6 +125,8 @@ public class PpointService {
             wrapper.eq(ProductPpoint::getProductId, productId);
         }
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ProductPpoint> page = productPpointMapper.selectPage(pageParam, wrapper);
         List<ProductPpoint> records = page.getRecords();
 

+ 10 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java

@@ -51,6 +51,7 @@ import com.etotem.cfc.service.UserService;
 import com.alibaba.fastjson.JSON;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ProductOrderService {
@@ -905,6 +906,7 @@ public class ProductOrderService {
             LambdaQueryWrapper<AfterSalesRequest> wrapper = new LambdaQueryWrapper<AfterSalesRequest>()
                 .eq(AfterSalesRequest::getOrderNo, orderNo)
                 .eq(AfterSalesRequest::getStatus, "pending");
+            SortUtil.applySort(wrapper);
             AfterSalesRequest request = afterSalesRequestMapper.selectOne(wrapper);
             if (request != null) {
                 request.setStatus(status);
@@ -936,6 +938,8 @@ public class ProductOrderService {
             String kw = keyword.trim();
             wrapper.and(w -> w.like(ProductOrder::getProductName, kw).or().like(ProductOrder::getOrderNo, kw));
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ProductOrder> list = orderMapper.selectList(wrapper);
         return Result.success(list.stream().map(ProductOrderDTO::from).collect(Collectors.toList()));
     }
@@ -989,6 +993,8 @@ public class ProductOrderService {
         if (status != null && !status.isEmpty()) {
             wrapper.eq(ProductOrder::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ProductOrder> list = orderMapper.selectList(wrapper);
         return Result.success(list.stream().map(ProductOrderDTO::from).collect(Collectors.toList()));
     }
@@ -999,6 +1005,8 @@ public class ProductOrderService {
         if (status != null && !status.isEmpty()) {
             wrapper.eq(ProductOrder::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ProductOrder> list = orderMapper.selectList(wrapper);
         return Result.success(list.stream().map(ProductOrderDTO::from).collect(Collectors.toList()));
     }
@@ -1029,6 +1037,8 @@ public class ProductOrderService {
                 wrapper.lt(ProductOrder::getCreatedAt, cal.getTime());
             } catch (Exception ignored) {}
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         Page<ProductOrder> result = orderMapper.selectPage(pageParam, wrapper);
         List<ProductOrderDTO> records = result.getRecords().stream()
             .map(ProductOrderDTO::from)

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ProductRecommendationService.java

@@ -9,6 +9,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.*;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 商品推荐服务
@@ -65,6 +66,8 @@ public class ProductRecommendationService {
         if (dimensionCode != null && !dimensionCode.isEmpty()) {
             mappingQw.eq(ProductDimensionMapping::getDimensionCode, dimensionCode);
         }
+        SortUtil.applySort(mappingQw);
+        SortUtil.applySort(mappingQw);
         List<ProductDimensionMapping> mappings = dimensionMappingMapper.selectList(mappingQw);
 
         if (mappings != null && !mappings.isEmpty()) {
@@ -117,6 +120,8 @@ public class ProductRecommendationService {
             if (!purchasedIds.isEmpty()) {
                 domainQw.notIn(Product::getId, purchasedIds);
             }
+            SortUtil.applySort(domainQw);
+            SortUtil.applySort(domainQw);
             List<Product> domainMatched = productMapper.selectList(domainQw);
             candidates.addAll(domainMatched);
         }
@@ -243,6 +248,8 @@ public class ProductRecommendationService {
         qw.eq(memberId != null, FiveDimensionScore::getMemberId, memberId);
         qw.orderByDesc(FiveDimensionScore::getAssessedAt);
 
+        SortUtil.applySort(qw);
+        SortUtil.applySort(qw);
         List<FiveDimensionScore> records = fiveDimensionScoreMapper.selectList(qw);
 
         // 取每个维度的最新得分

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ProductService.java

@@ -24,6 +24,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class ProductService {
@@ -98,6 +99,8 @@ wrapper.in(Product::getId, productIds)
         if (query.getKeyword() != null && !query.getKeyword().isEmpty()) {
             wrapper.like(Product::getName, query.getKeyword());
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         IPage<Product> result = productMapper.selectPage(page, wrapper);
         boolean isGuest = (userId == null);
         String memberLevel = null;
@@ -246,6 +249,8 @@ wrapper.in(Product::getId, productIds)
         if (status != null && !status.isEmpty()) {
             wrapper.eq(Product::getStatus, status);
         }
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<Product> list = productMapper.selectList(wrapper);
         List<ProductDTO> dtos = list.stream().map(ProductDTO::from).collect(Collectors.toList());
         return Result.success(dtos);
@@ -255,6 +260,8 @@ wrapper.in(Product::getId, productIds)
      * 管理员分页查询商品列表
      */
     public Page<Product> adminProductList(Page<Product> pageParam, LambdaQueryWrapper<Product> wrapper) {
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return productMapper.selectPage(pageParam, wrapper);
     }
 

+ 3 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/PromotionMaterialService.java

@@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Slf4j
 @Service
@@ -34,6 +35,8 @@ public class PromotionMaterialService {
         }
         wrapper.orderByAsc(PromotionMaterial::getSortOrder);
         wrapper.orderByDesc(PromotionMaterial::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return promotionMaterialMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
     }
 

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/RecommendationService.java

@@ -25,6 +25,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.util.*;
+import com.etotem.cfc.util.SortUtil;
 
 /**
  * 跨表推荐搜索服务
@@ -244,6 +245,8 @@ public class RecommendationService {
                 .orderByDesc(ProductDimensionMapping::getMatchScore)
                 .last("LIMIT " + maxLimit);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<ProductDimensionMapping> mappings = productDimensionMappingMapper.selectList(wrapper);
 
         for (ProductDimensionMapping m : mappings) {
@@ -282,6 +285,8 @@ public class RecommendationService {
                 .eq(RepurchaseReminderRecord::getPurchased, 0)
                 .orderByDesc(RepurchaseReminderRecord::getSentAt);
 
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<RepurchaseReminderRecord> records = repurchaseReminderRecordMapper.selectList(wrapper);
 
         for (RepurchaseReminderRecord record : records) {

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/RelationshipQualityService.java

@@ -23,6 +23,7 @@ import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class RelationshipQualityService {
@@ -46,6 +47,8 @@ public class RelationshipQualityService {
     public List<RelationshipScoreVO> getScores(Long familyId) {
         LambdaQueryWrapper<FamilyMember> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyMember::getFamilyId, familyId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyMember> members = familyMemberMapper.selectList(wrapper);
 
         List<RelationshipScoreVO> result = new ArrayList<>();
@@ -109,6 +112,8 @@ public class RelationshipQualityService {
     public List<HealthAlertVO> getHealthAlerts(Long familyId) {
         LambdaQueryWrapper<FamilyMember> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyMember::getFamilyId, familyId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyMember> members = familyMemberMapper.selectList(wrapper);
 
         List<HealthAlertVO> alerts = new ArrayList<>();
@@ -150,6 +155,8 @@ public class RelationshipQualityService {
 
         LambdaQueryWrapper<FamilyMember> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(FamilyMember::getFamilyId, familyId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<FamilyMember> members = familyMemberMapper.selectList(wrapper);
 
         List<MilestoneVO> milestones = new ArrayList<>();
@@ -161,6 +168,7 @@ public class RelationshipQualityService {
             // 查询成员的生日信息
             LambdaQueryWrapper<FamilyMemberAttributes> attrWrapper = new LambdaQueryWrapper<>();
             attrWrapper.eq(FamilyMemberAttributes::getMemberId, member.getId());
+            SortUtil.applySort(attrWrapper);
             FamilyMemberAttributes attrs = familyMemberAttributesMapper.selectOne(attrWrapper);
 
             if (attrs != null && attrs.getBirthDatetime() != null) {

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/RelationshipQuestionnaireService.java

@@ -24,6 +24,7 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class RelationshipQuestionnaireService {
@@ -164,6 +165,7 @@ public class RelationshipQuestionnaireService {
                 .orderByDesc(RelationshipQuestionnaireSnapshot::getCreatedAt)
                 .last("LIMIT 1");
 
+        SortUtil.applySort(wrapper);
         RelationshipQuestionnaireSnapshot snapshot = snapshotMapper.selectOne(wrapper);
         if (snapshot == null) {
             return null;
@@ -191,6 +193,8 @@ public class RelationshipQuestionnaireService {
         // 先找到该成员的所有快照
         LambdaQueryWrapper<RelationshipQuestionnaireSnapshot> snapWrapper = new LambdaQueryWrapper<>();
         snapWrapper.eq(RelationshipQuestionnaireSnapshot::getFamilyMemberId, memberId);
+        SortUtil.applySort(snapWrapper);
+        SortUtil.applySort(snapWrapper);
         List<RelationshipQuestionnaireSnapshot> snapshots = snapshotMapper.selectList(snapWrapper);
 
         if (snapshots.isEmpty()) {
@@ -207,6 +211,8 @@ public class RelationshipQuestionnaireService {
         respWrapper.in(RelationshipQuestionnaireResponse::getSnapshotId, snapshotIds)
                 .orderByDesc(RelationshipQuestionnaireResponse::getCalculatedAt);
 
+        SortUtil.applySort(respWrapper);
+        SortUtil.applySort(respWrapper);
         return responseMapper.selectList(respWrapper);
     }
 
@@ -322,6 +328,7 @@ public class RelationshipQuestionnaireService {
             // 找到答卷人对应的 family_member 记录
             LambdaQueryWrapper<FamilyMember> respWrapper = new LambdaQueryWrapper<>();
             respWrapper.eq(FamilyMember::getUserId, respondentUserId);
+            SortUtil.applySort(respWrapper);
             FamilyMember respondent = familyMemberMapper.selectOne(respWrapper);
             if (respondent == null) {
                 log.warn("答卷人用户{}无family_member记录,跳过pairwise评分同步", respondentUserId);
@@ -331,6 +338,7 @@ public class RelationshipQuestionnaireService {
             LambdaQueryWrapper<FamilyRelationship> relWrapper = new LambdaQueryWrapper<>();
             relWrapper.eq(FamilyRelationship::getFromMemberId, respondent.getId())
                     .eq(FamilyRelationship::getToMemberId, targetMemberId);
+            SortUtil.applySort(relWrapper);
             FamilyRelationship rel = familyRelationshipMapper.selectOne(relWrapper);
             Date now = new Date();
             if (rel != null) {

+ 5 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/ReportSummaryService.java

@@ -30,6 +30,7 @@ import javax.annotation.Resource;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 @Slf4j
@@ -255,6 +256,8 @@ public class ReportSummaryService {
         wrapper.orderByDesc(ReportSummary::getReportDate);
         reportSummaryMapper.selectPage(page, wrapper);
 
+        SortUtil.applySort(wrapper);
+
         Page<ReportSummaryVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
         List<ReportSummaryVO> voList = new ArrayList<>();
         for (ReportSummary s : page.getRecords()) {
@@ -333,6 +336,8 @@ public class ReportSummaryService {
         wrapper.orderByDesc(ReportSummary::getReportDate);
         reportSummaryMapper.selectPage(page, wrapper);
 
+        SortUtil.applySort(wrapper);
+
         Page<ReportSummaryVO> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
         List<ReportSummaryVO> voList = new ArrayList<>();
         for (ReportSummary rs : page.getRecords()) {

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/SupplyHierarchyService.java

@@ -16,6 +16,7 @@ import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class SupplyHierarchyService extends ServiceImpl<SupplyHierarchyMapper, SupplyHierarchy> {
@@ -35,6 +36,7 @@ public class SupplyHierarchyService extends ServiceImpl<SupplyHierarchyMapper, S
         LambdaQueryWrapper<SupplyHierarchy> existingWrapper = new LambdaQueryWrapper<>();
         existingWrapper.eq(SupplyHierarchy::getSystemId, systemId)
                 .eq(SupplyHierarchy::getChildId, childId);
+        SortUtil.applySort(existingWrapper);
         SupplyHierarchy existing = this.getOne(existingWrapper);
 
         int level = 1;
@@ -100,6 +102,7 @@ public class SupplyHierarchyService extends ServiceImpl<SupplyHierarchyMapper, S
         LambdaQueryWrapper<SupplyHierarchy> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(SupplyHierarchy::getSystemId, systemId)
                 .eq(SupplyHierarchy::getChildId, childId);
+        SortUtil.applySort(wrapper);
         SupplyHierarchy existing = this.getOne(wrapper);
         if (existing != null) {
             existing.setStatus("inactive");
@@ -114,6 +117,7 @@ public class SupplyHierarchyService extends ServiceImpl<SupplyHierarchyMapper, S
         wrapper.eq(SupplyHierarchy::getSystemId, systemId)
                 .eq(SupplyHierarchy::getParentId, parentId)
                 .eq(SupplyHierarchy::getStatus, "active");
+        SortUtil.applySort(wrapper);
         List<SupplyHierarchy> hierarchies = this.list(wrapper);
         if (hierarchies.isEmpty()) {
             return new ArrayList<>();
@@ -134,6 +138,7 @@ public class SupplyHierarchyService extends ServiceImpl<SupplyHierarchyMapper, S
             wrapper.eq(SupplyHierarchy::getSystemId, systemId)
                     .in(SupplyHierarchy::getParentId, currentLevelIds)
                     .eq(SupplyHierarchy::getStatus, "active");
+            SortUtil.applySort(wrapper);
             List<SupplyHierarchy> hierarchies = this.list(wrapper);
             if (hierarchies.isEmpty()) {
                 break;
@@ -196,6 +201,8 @@ public class SupplyHierarchyService extends ServiceImpl<SupplyHierarchyMapper, S
             wrapper.eq(SupplyHierarchyChangeRequest::getStatus, status);
         }
         wrapper.orderByDesc(SupplyHierarchyChangeRequest::getCreatedAt);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return changeRequestMapper.selectList(wrapper);
     }
 

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/SupplySettlementService.java

@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.stream.Collectors;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class SupplySettlementService extends ServiceImpl<SupplySettlementMapper, SupplySettlement> {
@@ -61,6 +62,7 @@ public class SupplySettlementService extends ServiceImpl<SupplySettlementMapper,
             wrapper.eq(SupplySettlement::getStatus, status);
         }
 
+        SortUtil.applySort(wrapper);
         Page<SupplySettlement> result = this.page(pageParam, wrapper);
         Map<String, Object> data = new HashMap<>();
         data.put("records", result.getRecords());
@@ -87,6 +89,8 @@ public class SupplySettlementService extends ServiceImpl<SupplySettlementMapper,
     public Result<List<SupplySettlementDetail>> detailItems(Long settlementId) {
         LambdaQueryWrapper<SupplySettlementDetail> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(SupplySettlementDetail::getSettlementId, settlementId);
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         List<SupplySettlementDetail> items = supplySettlementDetailMapper.selectList(wrapper);
         return Result.success(items);
     }
@@ -133,6 +137,8 @@ public class SupplySettlementService extends ServiceImpl<SupplySettlementMapper,
                 .ge(ProductOrder::getCreatedAt, periodStart)
                 .le(ProductOrder::getCreatedAt, periodEnd);
 
+        SortUtil.applySort(orderWrapper);
+        SortUtil.applySort(orderWrapper);
         List<ProductOrder> orders = productOrderMapper.selectList(orderWrapper);
         if (orders.isEmpty()) {
             return Result.error("该周期内没有已完成的订单");
@@ -142,6 +148,8 @@ public class SupplySettlementService extends ServiceImpl<SupplySettlementMapper,
         List<Long> orderIds = orders.stream().map(ProductOrder::getId).collect(Collectors.toList());
         LambdaQueryWrapper<SupplySettlementDetail> existingWrapper = new LambdaQueryWrapper<>();
         existingWrapper.in(SupplySettlementDetail::getOrderId, orderIds);
+        SortUtil.applySort(existingWrapper);
+        SortUtil.applySort(existingWrapper);
         List<SupplySettlementDetail> existingDetails = supplySettlementDetailMapper.selectList(existingWrapper);
         Set<Long> existingOrderIds = existingDetails.stream()
                 .map(SupplySettlementDetail::getOrderId)

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/SupplySystemService.java

@@ -15,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional;
 import javax.annotation.Resource;
 import java.util.Date;
 import java.util.List;
+import com.etotem.cfc.util.SortUtil;
 
 @Service
 public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplySystem> {
@@ -35,6 +36,7 @@ public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplyS
             wrapper.eq(SupplySystem::getStatus, status);
         }
         wrapper.orderByDesc(SupplySystem::getId);
+        SortUtil.applySort(wrapper);
         return this.page(pageParam, wrapper);
     }
 
@@ -80,6 +82,7 @@ public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplyS
     public List<SupplySystem> listAll() {
         LambdaQueryWrapper<SupplySystem> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(SupplySystem::getStatus, "active");
+        SortUtil.applySort(wrapper);
         return this.list(wrapper);
     }
 
@@ -88,6 +91,7 @@ public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplyS
         wrapper.eq(SupplySystem::getAdminId, adminId)
                .eq(SupplySystem::getStatus, "active")
                .last("LIMIT 1");
+        SortUtil.applySort(wrapper);
         return this.getOne(wrapper);
     }
 
@@ -97,6 +101,8 @@ public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplyS
         LambdaQueryWrapper<SupplySystemMember> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(SupplySystemMember::getSystemId, systemId)
                .eq(SupplySystemMember::getStatus, "active");
+        SortUtil.applySort(wrapper);
+        SortUtil.applySort(wrapper);
         return supplySystemMemberMapper.selectList(wrapper);
     }
 
@@ -106,6 +112,7 @@ public class SupplySystemService extends ServiceImpl<SupplySystemMapper, SupplyS
         LambdaQueryWrapper<SupplySystemMember> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(SupplySystemMember::getSystemId, systemId)
                .eq(SupplySystemMember::getUserId, userId);
+        SortUtil.applySort(wrapper);
         SupplySystemMember existing = supplySystemMemberMapper.selectOne(wrapper);
         if (existing != null) return existing;
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä