Преглед изворни кода

feat: update backend entities, services, DTOs and configs

Update controllers, services, entities, DTOs, config, and schema files for guide package, commission, membership, energy system, data migration, and other backend modules.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
User пре 4 месеци
родитељ
комит
0be2df29ba
100 измењених фајлова са 435 додато и 386 уклоњено
  1. 12 0
      cfc-backend/pom.xml
  2. 5 1
      cfc-backend/src/main/java/com/etotem/cfc/config/JwtInterceptor.java
  3. 3 1
      cfc-backend/src/main/java/com/etotem/cfc/config/WebConfig.java
  4. 0 1
      cfc-backend/src/main/java/com/etotem/cfc/controller/CommissionController.java
  5. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/controller/MembershipController.java
  6. 3 4
      cfc-backend/src/main/java/com/etotem/cfc/controller/WithdrawalController.java
  7. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminCommissionController.java
  8. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/FamilyAttributeController.java
  9. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/MigrationController.java
  10. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/controller/admin/ServiceContentController.java
  11. 33 0
      cfc-backend/src/main/java/com/etotem/cfc/controller/auth/AuthController.java
  12. 5 5
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideManagementController.java
  13. 5 3
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideOrderController.java
  14. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuidePackageController.java
  15. 11 4
      cfc-backend/src/main/java/com/etotem/cfc/controller/parent/ParentDashboardController.java
  16. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/ActivityDTO.java
  17. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/AddGuidePackageDTO.java
  18. 2 4
      cfc-backend/src/main/java/com/etotem/cfc/dto/AdminCreateGuidePackageDTO.java
  19. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/AdminUpdateGuidePackageDTO.java
  20. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/BindGuideDTO.java
  21. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/CommissionSettleRequest.java
  22. 6 6
      cfc-backend/src/main/java/com/etotem/cfc/dto/CommissionSummaryDTO.java
  23. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/CreatePackageDTO.java
  24. 2 4
      cfc-backend/src/main/java/com/etotem/cfc/dto/CreatePackageTemplateDTO.java
  25. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/CreateServiceContentDTO.java
  26. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/dto/EmiReportDTO.java
  27. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/FamilyMembershipDTO.java
  28. 3 4
      cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageDTO.java
  29. 3 4
      cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageTemplateDTO.java
  30. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageUpdateDTO.java
  31. 2 0
      cfc-backend/src/main/java/com/etotem/cfc/dto/LoginResultDTO.java
  32. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/MembershipLevelDTO.java
  33. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/PackageDetailDTO.java
  34. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/PaymentOrderDTO.java
  35. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/ProductDTO.java
  36. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/ProductOrderDTO.java
  37. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/ReferralSummaryDTO.java
  38. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/ServiceContentDTO.java
  39. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/dto/TeacherDTO.java
  40. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/UpdateGuidePackagePriceDTO.java
  41. 3 3
      cfc-backend/src/main/java/com/etotem/cfc/dto/UpdatePackageTemplateDTO.java
  42. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/dto/UpdateServiceContentDTO.java
  43. 6 4
      cfc-backend/src/main/java/com/etotem/cfc/entity/Activity.java
  44. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/AssessmentPointsConfig.java
  45. 5 6
      cfc-backend/src/main/java/com/etotem/cfc/entity/BaziConfig.java
  46. 5 6
      cfc-backend/src/main/java/com/etotem/cfc/entity/BloodTypeConfig.java
  47. 3 4
      cfc-backend/src/main/java/com/etotem/cfc/entity/CommissionRecord.java
  48. 8 0
      cfc-backend/src/main/java/com/etotem/cfc/entity/DanAssessmentResult.java
  49. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/EnergyDimensionConfig.java
  50. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/EnergySourceConfig.java
  51. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/FamilyMemberAttributes.java
  52. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/FamilyMembership.java
  53. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/FinanceCheckin.java
  54. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/Guide.java
  55. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/GuideApplication.java
  56. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/GuideFamily.java
  57. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/GuidePackage.java
  58. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/GuidePackageTemplate.java
  59. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/InsurancePolicy.java
  60. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/MembershipLevel.java
  61. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/PackageOrder.java
  62. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/PaymentOrder.java
  63. 4 5
      cfc-backend/src/main/java/com/etotem/cfc/entity/Product.java
  64. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/ProductOrder.java
  65. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/ServiceContent.java
  66. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/entity/TaskTemplatePackage.java
  67. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/entity/Teacher.java
  68. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/UpgradeService.java
  69. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/entity/WithdrawalRequest.java
  70. 5 6
      cfc-backend/src/main/java/com/etotem/cfc/entity/ZodiacConfig.java
  71. 3 2
      cfc-backend/src/main/java/com/etotem/cfc/service/ActivityService.java
  72. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentOrderService.java
  73. 2 2
      cfc-backend/src/main/java/com/etotem/cfc/service/AssessmentService.java
  74. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/service/BindInviteService.java
  75. 60 78
      cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java
  76. 3 4
      cfc-backend/src/main/java/com/etotem/cfc/service/DataMigrationService.java
  77. 0 1
      cfc-backend/src/main/java/com/etotem/cfc/service/DatabaseSyncService.java
  78. 6 0
      cfc-backend/src/main/java/com/etotem/cfc/service/EmiReportService.java
  79. 13 15
      cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java
  80. 18 22
      cfc-backend/src/main/java/com/etotem/cfc/service/FamilyMemberAttributeService.java
  81. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/service/GuideFamilyService.java
  82. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/service/GuidePackageService.java
  83. 12 14
      cfc-backend/src/main/java/com/etotem/cfc/service/MembershipService.java
  84. 4 5
      cfc-backend/src/main/java/com/etotem/cfc/service/PackagePaymentService.java
  85. 8 9
      cfc-backend/src/main/java/com/etotem/cfc/service/PackagePurchaseService.java
  86. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java
  87. 7 0
      cfc-backend/src/main/java/com/etotem/cfc/service/ProductService.java
  88. 13 1
      cfc-backend/src/main/java/com/etotem/cfc/service/TaskStatsService.java
  89. 3 7
      cfc-backend/src/main/java/com/etotem/cfc/service/TaskTemplatePackageService.java
  90. 1 1
      cfc-backend/src/main/java/com/etotem/cfc/service/TeacherService.java
  91. 22 0
      cfc-backend/src/main/java/com/etotem/cfc/service/UserService.java
  92. 8 9
      cfc-backend/src/main/java/com/etotem/cfc/service/WithdrawalService.java
  93. 0 1
      cfc-backend/src/main/java/com/etotem/cfc/service/api/AssessmentOrderServiceInterface.java
  94. 1 2
      cfc-backend/src/main/java/com/etotem/cfc/service/api/BindInviteServiceInterface.java
  95. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/service/api/GuidePackageServiceInterface.java
  96. 0 1
      cfc-backend/src/main/java/com/etotem/cfc/service/api/GuidePackageTemplateServiceInterface.java
  97. 2 3
      cfc-backend/src/main/java/com/etotem/cfc/service/api/MembershipServiceInterface.java
  98. 5 0
      cfc-backend/src/main/resources/application.yml
  99. 2 2
      cfc-backend/src/main/resources/schema_assessment.sql
  100. 15 15
      cfc-backend/src/main/resources/schema_guide.sql

+ 12 - 0
cfc-backend/pom.xml

@@ -100,6 +100,18 @@
             <version>2.0.40</version>
         </dependency>
 
+        <!-- ZXing QR Code -->
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>core</artifactId>
+            <version>3.5.3</version>
+        </dependency>
+        <dependency>
+            <groupId>com.google.zxing</groupId>
+            <artifactId>javase</artifactId>
+            <version>3.5.3</version>
+        </dependency>
+
         <!-- SpringDoc OpenAPI (Swagger) -->
         <dependency>
             <groupId>org.springdoc</groupId>

+ 5 - 1
cfc-backend/src/main/java/com/etotem/cfc/config/JwtInterceptor.java

@@ -19,6 +19,7 @@ public class JwtInterceptor implements HandlerInterceptor {
 
     private static final String[] PUBLIC_PATHS = {
         "/api/auth/",
+        "/api/auth/verify",
         "/api/internal/",
         "/api/product/list",
         "/api/product/detail",
@@ -31,7 +32,10 @@ public class JwtInterceptor implements HandlerInterceptor {
         "/api/articles/detail",
         "/api/articles/categories",
         "/api/articles/featured",
-        "/api/articles/record-read"
+        "/api/articles/record-read",
+        "/api/activity/list",
+        "/api/activity/detail",
+        "/api/content-sections/visible"
     };
 
     @Override

+ 3 - 1
cfc-backend/src/main/java/com/etotem/cfc/config/WebConfig.java

@@ -49,7 +49,9 @@ public class WebConfig implements WebMvcConfigurer {
                 "/api/articles/detail",
                 "/api/articles/categories",
                 "/api/articles/featured",
-                "/api/articles/record-read"
+                "/api/articles/record-read",
+                "/api/activity/list",
+                "/api/activity/detail"
         );
 
         registry.addInterceptor(operationLogInterceptor)

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

@@ -8,7 +8,6 @@ import com.etotem.cfc.service.CommissionService;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.HashMap;
 import java.util.Map;
 

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/MembershipController.java

@@ -236,8 +236,8 @@ public class MembershipController {
             return Result.error("用户未登录");
         }
 
-        java.math.BigDecimal originalPrice = new java.math.BigDecimal(params.get("amount").toString());
-        java.math.BigDecimal discountedPrice = membershipService.applyMemberDiscount(userId, originalPrice);
+        Integer originalPrice = Integer.valueOf(params.get("amount").toString());
+        Integer discountedPrice = membershipService.applyMemberDiscount(userId, originalPrice);
 
         Map<String, Object> result = new HashMap<>();
         result.put("originalPrice", originalPrice);

+ 3 - 4
cfc-backend/src/main/java/com/etotem/cfc/controller/WithdrawalController.java

@@ -7,7 +7,6 @@ import com.etotem.cfc.service.WithdrawalService;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Map;
 
 @RestController
@@ -20,9 +19,9 @@ public class WithdrawalController {
     @PostMapping("/apply")
     public Result<String> apply(@RequestAttribute("userId") Long userId,
                                 @RequestBody Map<String, Object> params) {
-        BigDecimal amount = params.get("amount") != null
-                ? new BigDecimal(params.get("amount").toString())
-                : BigDecimal.ZERO;
+        Integer amount = params.get("amount") != null
+                ? Integer.valueOf(params.get("amount").toString())
+                : 0;
         String accountInfo = (String) params.get("accountInfo");
         return withdrawalService.apply(userId, amount, accountInfo);
     }

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/AdminCommissionController.java

@@ -9,7 +9,6 @@ import com.etotem.cfc.service.WithdrawalService;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Map;
 
 @RestController
@@ -58,8 +57,8 @@ public class AdminCommissionController {
         Long productId = params.get("productId") != null
                 ? Long.valueOf(params.get("productId").toString())
                 : null;
-        BigDecimal profitRate = params.get("profitRate") != null
-                ? new BigDecimal(params.get("profitRate").toString())
+        Integer profitRate = params.get("profitRate") != null
+                ? Integer.valueOf(params.get("profitRate").toString())
                 : null;
         if (productId == null || profitRate == null) {
             return Result.error("productId和profitRate不能为空");

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/controller/admin/FamilyAttributeController.java

@@ -6,7 +6,6 @@ import com.etotem.cfc.service.FamilyMemberAttributeService;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Map;
 
 @RestController
@@ -44,8 +43,8 @@ public class FamilyAttributeController {
         familyMemberAttributeService.autoCalculate(attrs);
 
         // Calculate innate scores for mind and wisdom dimensions
-        BigDecimal mindScore = familyMemberAttributeService.calcInnateScore(memberId, memberType, "mind");
-        BigDecimal wisdomScore = familyMemberAttributeService.calcInnateScore(memberId, memberType, "wisdom");
+        Integer mindScore = familyMemberAttributeService.calcInnateScore(memberId, memberType, "mind");
+        Integer wisdomScore = familyMemberAttributeService.calcInnateScore(memberId, memberType, "wisdom");
 
         // Reload to get updated values
         attrs = familyMemberAttributeService.getByMember(memberId, memberType);

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

@@ -28,7 +28,7 @@ public class MigrationController {
         } catch (Exception ignored) {
         }
         try {
-            jdbcTemplate.execute("ALTER TABLE guide_packages ADD COLUMN IF NOT EXISTS commission_rate DECIMAL(5,2) COMMENT '佣金比例'");
+            jdbcTemplate.execute("ALTER TABLE guide_packages ADD COLUMN IF NOT EXISTS commission_rate INT COMMENT '佣金比例(bps,100=1%)'");
         } catch (Exception ignored) {
         }
         return Result.success("迁移完成");

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

@@ -88,7 +88,7 @@ public class ServiceContentController {
         serviceContent.setDuration(params.get("duration") != null ? Integer.valueOf(params.get("duration").toString()) : null);
         serviceContent.setAgeRange(params.get("ageRange") != null ? params.get("ageRange").toString() : null);
         if (params.get("price") != null) {
-            serviceContent.setPrice(new java.math.BigDecimal(params.get("price").toString()));
+            serviceContent.setPrice(Integer.valueOf(params.get("price").toString()));
         }
         serviceContent.setUpdatedAt(new Date());
         boolean success = serviceContentService.updateContent(serviceContent);

+ 33 - 0
cfc-backend/src/main/java/com/etotem/cfc/controller/auth/AuthController.java

@@ -1,19 +1,23 @@
 package com.etotem.cfc.controller.auth;
 
 import com.etotem.cfc.common.Result;
+import com.etotem.cfc.config.JwtConfig;
 import com.etotem.cfc.dto.*;
 import com.etotem.cfc.dto.RegisterWithIdCardDTO;
 import com.etotem.cfc.dto.RegisterWithInviteCodeDTO;
 import com.etotem.cfc.entity.User;
 import com.etotem.cfc.service.UserService;
 import com.etotem.cfc.service.VerificationCodeService;
+import io.jsonwebtoken.Claims;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
 import org.springframework.web.bind.annotation.*;
 
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 
 @Tag(name = "用户认证", description = "用户登录、验证码、密码设置等认证接口")
 @RestController
@@ -26,6 +30,9 @@ public class AuthController {
     @Resource
     private VerificationCodeService verificationCodeService;
 
+    @Resource
+    private JwtConfig jwtConfig;
+
     /**
      * 发送验证码
      */
@@ -182,6 +189,32 @@ public class AuthController {
         return Result.success(success);
     }
 
+    /**
+     * JWT Token 验证(供 danshop 等内部服务调用)
+     * 从 Authorization header 提取 Bearer token,验证并返回用户信息
+     */
+    @Operation(summary = "验证JWT Token有效性")
+    @PostMapping("/verify")
+    public Result<Map<String, Object>> verifyToken(HttpServletRequest request) {
+        String authHeader = request.getHeader("Authorization");
+        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
+            return Result.error(401, "无效的Token");
+        }
+        try {
+            String token = authHeader.substring(7);
+            Claims claims = jwtConfig.parseToken(token);
+            Long userId = Long.parseLong(claims.getSubject());
+            String role = (String) claims.get("role");
+
+            Map<String, Object> data = new HashMap<>();
+            data.put("userId", userId);
+            data.put("role", role);
+            return Result.success(data);
+        } catch (Exception e) {
+            return Result.error(401, "Token无效或已过期");
+        }
+    }
+
     @Operation(summary = "验证密码")
     @PostMapping("/verify-password")
     public Result<Boolean> verifyPassword(HttpServletRequest request,

+ 5 - 5
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideManagementController.java

@@ -273,10 +273,10 @@ public class GuideManagementController {
     public Result<Boolean> addGuidePackage(@RequestAttribute("userId") Long userId,
                                           @RequestBody Map<String, Object> params) {
         Long packageId = Long.valueOf(params.get("packageId").toString());
-        java.math.BigDecimal price = new java.math.BigDecimal(params.get("price").toString());
-        java.math.BigDecimal commissionRate = params.containsKey("commissionRate")
-            ? new java.math.BigDecimal(params.get("commissionRate").toString())
-            : new java.math.BigDecimal("0.1");
+        Integer price = Integer.valueOf(params.get("price").toString());
+        Integer commissionRate = params.containsKey("commissionRate")
+            ? Integer.valueOf(params.get("commissionRate").toString())
+            : 1000;  // 默认10%
 
         boolean success = guidePackageService.addGuidePackage(userId, packageId, price, commissionRate);
         return Result.success(success);
@@ -301,7 +301,7 @@ public class GuideManagementController {
     public Result<Boolean> updateGuidePackage(@RequestAttribute("userId") Long userId,
                                                @PathVariable Long packageId,
                                                @RequestBody Map<String, Object> params) {
-        java.math.BigDecimal price = new java.math.BigDecimal(params.get("price").toString());
+        Integer price = Integer.valueOf(params.get("price").toString());
         boolean success = guidePackageService.updateGuidePackagePrice(userId, packageId, price);
         return Result.success(success);
     }

+ 5 - 3
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuideOrderController.java

@@ -10,8 +10,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.HashMap;
+import java.util.Objects;
 import java.util.Map;
 
 @Tag(name = "成长规划师订单", description = "成长规划师订单与佣金接口")
@@ -60,12 +60,14 @@ public class GuideOrderController {
                 .eq(PackageOrder::getGuideId, guideId)
                 .eq(PackageOrder::getStatus, "paid"));
 
-        BigDecimal totalRevenue = packageOrderMapper.selectList(new LambdaQueryWrapper<PackageOrder>()
+        Integer totalRevenue = packageOrderMapper.selectList(new LambdaQueryWrapper<PackageOrder>()
                 .eq(PackageOrder::getGuideId, guideId)
                 .eq(PackageOrder::getStatus, "paid"))
                 .stream()
+                .filter(Objects::nonNull)
                 .map(PackageOrder::getPrice)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                .filter(Objects::nonNull)
+                .reduce(0, Integer::sum);
 
         Map<String, Object> stats = new HashMap<>();
         stats.put("totalOrders", totalOrders);

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/controller/guide/GuidePackageController.java

@@ -11,7 +11,6 @@ import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.List;
 import java.util.Map;
 
@@ -85,7 +84,7 @@ public class GuidePackageController {
             existing.setName(params.get("name").toString());
         }
         if (params.get("price") != null) {
-            existing.setPrice(new BigDecimal(params.get("price").toString()));
+            existing.setPrice(Integer.valueOf(params.get("price").toString()));
         }
         guidePackageService.updateById(existing);
         return Result.success(existing);

+ 11 - 4
cfc-backend/src/main/java/com/etotem/cfc/controller/parent/ParentDashboardController.java

@@ -67,8 +67,10 @@ public class ParentDashboardController {
                 stats.put("pendingReviewCount", taskStats.getOrDefault("pendingReviewCount", 0));
                 stats.put("habitCount", taskStats.getOrDefault("habitCount", 0));
 
-                totalCompletionRate += (Integer) taskStats.getOrDefault("completionRate", 0);
-                totalHabitCount += (Integer) taskStats.getOrDefault("habitCount", 0);
+                Number cr = (Number) taskStats.getOrDefault("completionRate", 0);
+                totalCompletionRate += cr.intValue();
+                Number hc = (Number) taskStats.getOrDefault("habitCount", 0);
+                totalHabitCount += hc.intValue();
 
                 childStatsList.add(stats);
             }
@@ -79,11 +81,16 @@ public class ParentDashboardController {
         int parentPoints = currentUser != null && currentUser.getTotalPoints() != null
             ? currentUser.getTotalPoints() : 0;
         Map<String, Object> parentStats = taskStatsService.getUserStats(userId, null, null);
-        int parentCompletionRate = (Integer) parentStats.getOrDefault("completionRate", 0);
+        Number pcr = (Number) parentStats.getOrDefault("completionRate", 0);
+        int parentCompletionRate = pcr.intValue();
 
         Map<String, Object> result = new HashMap<>();
+        result.put("familyId", currentUser != null ? currentUser.getFamilyId() : null);
         result.put("children", childStatsList);
-        result.put("avgCompletionRate", childCount > 0 ? totalCompletionRate / childCount : 0);
+        // avgCompletionRate = (家长 + Σ孩子) / (1 + 孩子数)
+        int totalRate = parentCompletionRate + totalCompletionRate;
+        int avgRate = childCount > 0 ? totalRate / (childCount + 1) : parentCompletionRate;
+        result.put("avgCompletionRate", avgRate);
         result.put("totalHabitCount", totalHabitCount);
         result.put("parentPoints", parentPoints);
         result.put("parentCompletionRate", parentCompletionRate);

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/ActivityDTO.java

@@ -3,7 +3,7 @@ package com.etotem.cfc.dto;
 import com.etotem.cfc.entity.Activity;
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class ActivityDTO {
@@ -19,7 +19,7 @@ public class ActivityDTO {
     private String location;
     private Integer maxParticipants;
     private Integer currentParticipants;
-    private BigDecimal price;
+    private Integer price;
     private String vendorName;
     private String priceLabel;
 
@@ -48,7 +48,7 @@ public class ActivityDTO {
             dto.setPriceLabel("登录查看价格");
         } else {
             dto.setPrice(activity.getPrice());
-            if (activity.getPrice() != null && activity.getPrice().compareTo(BigDecimal.ZERO) == 0) {
+            if (activity.getPrice() != null && activity.getPrice() == 0) {
                 dto.setPriceLabel("免费");
             } else {
                 dto.setPriceLabel(null);

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/AddGuidePackageDTO.java

@@ -3,7 +3,7 @@ package com.etotem.cfc.dto;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
-import java.math.BigDecimal;
+
 
 @Data
 public class AddGuidePackageDTO {
@@ -11,7 +11,7 @@ public class AddGuidePackageDTO {
     private Long packageId;
 
     @NotNull(message = "价格不能为空")
-    private BigDecimal price;
+    private Integer price;
 
-    private BigDecimal commissionRate;
+    private Integer commissionRate;
 }

+ 2 - 4
cfc-backend/src/main/java/com/etotem/cfc/dto/AdminCreateGuidePackageDTO.java

@@ -2,8 +2,6 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
-
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 
@@ -18,7 +16,7 @@ public class AdminCreateGuidePackageDTO {
     private String description;
 
     @NotNull(message = "价格不能为空")
-    private BigDecimal price;
+    private Integer price;
 
     private Integer validityDays;
 
@@ -26,7 +24,7 @@ public class AdminCreateGuidePackageDTO {
 
     private Long packageId;
 
-    private BigDecimal commissionRate;
+    private Integer commissionRate;
 
     private Integer sortOrder;
 }

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/AdminUpdateGuidePackageDTO.java

@@ -2,7 +2,7 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class AdminUpdateGuidePackageDTO {
@@ -13,7 +13,7 @@ public class AdminUpdateGuidePackageDTO {
 
     private String description;
 
-    private BigDecimal price;
+    private Integer price;
 
     private Integer validityDays;
 
@@ -21,7 +21,7 @@ public class AdminUpdateGuidePackageDTO {
 
     private Long packageId;
 
-    private BigDecimal commissionRate;
+    private Integer commissionRate;
 
     private String status;
 

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/BindGuideDTO.java

@@ -2,13 +2,13 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class BindGuideDTO {
     private String bindToken; // 绑定令牌
     private String serviceType; // monthly/yearly/consulting
-    private BigDecimal servicePrice;
+    private Integer servicePrice;
     private Long guideId; // 成长规划师ID
     private Long familyId; // 家庭ID
 }

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/CommissionSettleRequest.java

@@ -7,6 +7,6 @@ public class CommissionSettleRequest {
     private Long orderId;
     private String orderType;
     private Long buyerId;
-    private java.math.BigDecimal orderAmount;
+    private Integer orderAmount;
     private Long productId;
 }

+ 6 - 6
cfc-backend/src/main/java/com/etotem/cfc/dto/CommissionSummaryDTO.java

@@ -1,13 +1,13 @@
 package com.etotem.cfc.dto;
 
 import lombok.Data;
-import java.math.BigDecimal;
+
 
 @Data
 public class CommissionSummaryDTO {
-    private BigDecimal totalCommission;
-    private BigDecimal settledAmount;
-    private BigDecimal pendingAmount;
-    private BigDecimal withdrawnAmount;
-    private BigDecimal availableAmount;
+    private Integer totalCommission;
+    private Integer settledAmount;
+    private Integer pendingAmount;
+    private Integer withdrawnAmount;
+    private Integer availableAmount;
 }

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/CreatePackageDTO.java

@@ -2,7 +2,7 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class CreatePackageDTO {
@@ -11,7 +11,7 @@ public class CreatePackageDTO {
     private Integer cycleDays;
     private String category;
     private String tags;
-    private BigDecimal price;
+    private Integer price;
     private Integer isPublic;
     private String coverImage;
 }

+ 2 - 4
cfc-backend/src/main/java/com/etotem/cfc/dto/CreatePackageTemplateDTO.java

@@ -2,8 +2,6 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
-
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 
@@ -17,9 +15,9 @@ public class CreatePackageTemplateDTO {
     private Integer validityMonths;
 
     @NotNull(message = "参考价格不能为空")
-    private BigDecimal referencePrice;
+    private Integer referencePrice;
 
-    private BigDecimal minPrice;
+    private Integer minPrice;
 
     private String description;
 }

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/CreateServiceContentDTO.java

@@ -5,7 +5,7 @@ import lombok.Data;
 import javax.validation.constraints.NotBlank;
 import javax.validation.constraints.NotNull;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class CreateServiceContentDTO {
@@ -22,5 +22,5 @@ public class CreateServiceContentDTO {
 
     private String ageRange;
 
-    private BigDecimal price;
+    private Integer price;
 }

+ 7 - 0
cfc-backend/src/main/java/com/etotem/cfc/dto/EmiReportDTO.java

@@ -20,6 +20,13 @@ public class EmiReportDTO implements Serializable {
 
     private Integer selfAwarenessScore;
 
+    private Integer opennessScore;
+    private Integer conscientiousnessScore;
+    private Integer extraversionScore;
+    private Integer agreeablenessScore;
+    private Integer neuroticismScore;
+    private Integer bigFiveOverallScore;
+
     private Integer overallScore;
 
     private String analysisReport;

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/FamilyMembershipDTO.java

@@ -1,7 +1,6 @@
 package com.etotem.cfc.dto;
 
 import lombok.Data;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -15,7 +14,7 @@ public class FamilyMembershipDTO {
     private String paymentMethod;
     private String paymentStatus;
     private String orderNo;
-    private BigDecimal amount;
+    private Integer amount;
     private Integer autoRenew;
     private Boolean isActive;  // 是否在会员期内
     private Long daysRemaining;  // 剩余天数

+ 3 - 4
cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageDTO.java

@@ -2,7 +2,6 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
 import java.util.List;
 
 @Data
@@ -12,8 +11,8 @@ public class GuidePackageDTO {
     private Long templateId;
     private String templateName;
     private String name;
-    private BigDecimal price;
-    private BigDecimal commissionRate;
+    private Integer price;
+    private Integer commissionRate;
     private Integer validityMonths;
     private String description;
     private String status;
@@ -28,6 +27,6 @@ public class GuidePackageDTO {
         private String serviceTitle;
         private Integer quantity;
         private String unit;
-        private BigDecimal unitPrice;
+        private Integer unitPrice;
     }
 }

+ 3 - 4
cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageTemplateDTO.java

@@ -2,7 +2,6 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
 import java.util.List;
 
 @Data
@@ -10,8 +9,8 @@ public class GuidePackageTemplateDTO {
     private Long id;
     private String name;
     private Integer validityMonths;
-    private BigDecimal referencePrice;
-    private BigDecimal minPrice;
+    private Integer referencePrice;
+    private Integer minPrice;
     private String description;
     private String status;
     private List<PackageServiceItemDTO> services;
@@ -22,6 +21,6 @@ public class GuidePackageTemplateDTO {
         private String serviceName;
         private Integer quantity;
         private String unit;
-        private BigDecimal unitPrice;
+        private Integer unitPrice;
     }
 }

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/GuidePackageUpdateDTO.java

@@ -3,7 +3,6 @@ package com.etotem.cfc.dto;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
-import java.math.BigDecimal;
 
 @Data
 public class GuidePackageUpdateDTO {
@@ -12,5 +11,5 @@ public class GuidePackageUpdateDTO {
 
     private String name;
 
-    private BigDecimal price;
+    private Integer price;
 }

+ 2 - 0
cfc-backend/src/main/java/com/etotem/cfc/dto/LoginResultDTO.java

@@ -17,4 +17,6 @@ public class LoginResultDTO {
     private String teacherStatus; // 成长规划师审核状态: pending/approved/rejected
     private String teacherRejectReason; // 成长规划师审核拒绝原因
     private Boolean hasTeacherRole; // 用户是否拥有teacher角色
+    private String danshopAccessToken; // danshop 商城访问token
+    private String danshopRefreshToken; // danshop 商城刷新token
 }

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/MembershipLevelDTO.java

@@ -1,7 +1,6 @@
 package com.etotem.cfc.dto;
 
 import lombok.Data;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -10,8 +9,8 @@ public class MembershipLevelDTO {
     private String levelCode;
     private String levelName;
     private String levelDesc;
-    private BigDecimal priceMonthly;
-    private BigDecimal priceYearly;
+    private Integer priceMonthly;
+    private Integer priceYearly;
     private String features;
     private Integer maxChildren;
     private Integer maxTasksPerDay;

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/PackageDetailDTO.java

@@ -2,7 +2,7 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class PackageDetailDTO {
@@ -12,8 +12,8 @@ public class PackageDetailDTO {
     private Integer cycleDays;
     private String category;
     private String tags;
-    private BigDecimal price;
-    private BigDecimal platformFee;
+    private Integer price;
+    private Integer platformFee;
     private Integer isPublic;
     private String shareCode;
     private String coverImage;

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/PaymentOrderDTO.java

@@ -1,7 +1,6 @@
 package com.etotem.cfc.dto;
 
 import lombok.Data;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -10,7 +9,7 @@ public class PaymentOrderDTO {
     private Long familyId;
     private String levelCode;
     private String paymentType;
-    private BigDecimal amount;
+    private Integer amount;
     private String status;
     private String payMethod;
     private String transactionId;

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/ProductDTO.java

@@ -3,7 +3,6 @@ package com.etotem.cfc.dto;
 import com.etotem.cfc.entity.Product;
 import lombok.Data;
 
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -14,8 +13,8 @@ public class ProductDTO {
     private String intro;
     private String coverImage;
     private String images;
-    private BigDecimal price;
-    private BigDecimal memberPrice;
+    private Integer price;
+    private Integer memberPrice;
     private Integer stock;
     private Integer salesCount;
     private String productType;
@@ -57,6 +56,7 @@ public class ProductDTO {
         // 游客模式:价格置null,显示提示标签
         if (isGuest) {
             d.price = null;
+            d.memberPrice = null;
             d.priceLabel = "登录查看价格";
         }
         return d;

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/ProductOrderDTO.java

@@ -3,7 +3,6 @@ package com.etotem.cfc.dto;
 import com.etotem.cfc.entity.ProductOrder;
 import lombok.Data;
 
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -17,8 +16,8 @@ public class ProductOrderDTO {
     private String buyerName;
     private Long familyId;
     private Integer quantity;
-    private BigDecimal unitPrice;
-    private BigDecimal totalAmount;
+    private Integer unitPrice;
+    private Integer totalAmount;
     private String status;
     private String paymentMethod;
     private String remark;

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/ReferralSummaryDTO.java

@@ -1,11 +1,11 @@
 package com.etotem.cfc.dto;
 
 import lombok.Data;
-import java.math.BigDecimal;
+
 
 @Data
 public class ReferralSummaryDTO {
     private String referralCode;
     private Integer invitedCount;
-    private BigDecimal totalEarnings;
+    private Integer totalEarnings;
 }

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/ServiceContentDTO.java

@@ -2,7 +2,7 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class ServiceContentDTO {
@@ -13,6 +13,6 @@ public class ServiceContentDTO {
     private String content;
     private Integer duration;
     private String ageRange;
-    private BigDecimal price;
+    private Integer price;
     private String status;
 }

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/dto/TeacherDTO.java

@@ -12,7 +12,7 @@ public class TeacherDTO {
     private String specialty;
     private String bio;
     private Integer experienceYears;
-    private java.math.BigDecimal rating;
+    private Integer rating;
     private Integer totalAppointments;
     private String status;
     private String verificationStatus;

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/UpdateGuidePackagePriceDTO.java

@@ -3,10 +3,10 @@ package com.etotem.cfc.dto;
 import lombok.Data;
 
 import javax.validation.constraints.NotNull;
-import java.math.BigDecimal;
+
 
 @Data
 public class UpdateGuidePackagePriceDTO {
     @NotNull(message = "价格不能为空")
-    private BigDecimal price;
+    private Integer price;
 }

+ 3 - 3
cfc-backend/src/main/java/com/etotem/cfc/dto/UpdatePackageTemplateDTO.java

@@ -2,7 +2,7 @@ package com.etotem.cfc.dto;
 
 import lombok.Data;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class UpdatePackageTemplateDTO {
@@ -11,9 +11,9 @@ public class UpdatePackageTemplateDTO {
 
     private Integer validityMonths;
 
-    private BigDecimal referencePrice;
+    private Integer referencePrice;
 
-    private BigDecimal minPrice;
+    private Integer minPrice;
 
     private String description;
 

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/dto/UpdateServiceContentDTO.java

@@ -4,7 +4,7 @@ import lombok.Data;
 
 import javax.validation.constraints.NotNull;
 
-import java.math.BigDecimal;
+
 
 @Data
 public class UpdateServiceContentDTO {
@@ -20,5 +20,5 @@ public class UpdateServiceContentDTO {
 
     private String ageRange;
 
-    private BigDecimal price;
+    private Integer price;
 }

+ 6 - 4
cfc-backend/src/main/java/com/etotem/cfc/entity/Activity.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -41,12 +40,15 @@ public class Activity implements Serializable {
 
     private Integer currentParticipants;
 
-    private BigDecimal price;
+    private Integer price;
 
-    /** all(默认)/member */
+    /** public(公开)/restricted(私密)/all(默认)/member */
     private String visibility;
 
-    /** 可见角色列表(逗号分隔), null表示所有角色 */
+    /** 可见范围: family(家庭)/role(角色)/user(用户), null表示不限制 */
+    private String visibleScope;
+
+    /** 可见对象标识: 家庭ID/角色名/用户ID 的JSON数组, 如 "["family_1","family_2"]" */
     private String visibleTo;
 
     private Long vendorId;

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/AssessmentPointsConfig.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -18,7 +17,7 @@ public class AssessmentPointsConfig implements Serializable {
 
     private Integer pointsValue;
 
-    private BigDecimal pointsValueYuan;
+    private Integer pointsValueYuan;
 
     private Integer isActive;
 

+ 5 - 6
cfc-backend/src/main/java/com/etotem/cfc/entity/BaziConfig.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -24,15 +23,15 @@ public class BaziConfig implements Serializable {
 
     private String yinYang;
 
-    private BigDecimal mindBase;
+    private Integer mindBase;
 
-    private BigDecimal wisdomBase;
+    private Integer wisdomBase;
 
-    private BigDecimal bodyModifier;
+    private Integer bodyModifier;
 
-    private BigDecimal actionModifier;
+    private Integer actionModifier;
 
-    private BigDecimal wealthModifier;
+    private Integer wealthModifier;
 
     private Date createdAt;
 }

+ 5 - 6
cfc-backend/src/main/java/com/etotem/cfc/entity/BloodTypeConfig.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -20,15 +19,15 @@ public class BloodTypeConfig implements Serializable {
 
     private String description;
 
-    private BigDecimal mindBase;
+    private Integer mindBase;
 
-    private BigDecimal wisdomBase;
+    private Integer wisdomBase;
 
-    private BigDecimal bodyModifier;
+    private Integer bodyModifier;
 
-    private BigDecimal actionModifier;
+    private Integer actionModifier;
 
-    private BigDecimal wealthModifier;
+    private Integer wealthModifier;
 
     private Date createdAt;
 }

+ 3 - 4
cfc-backend/src/main/java/com/etotem/cfc/entity/CommissionRecord.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -26,11 +25,11 @@ public class CommissionRecord implements Serializable {
 
     private String commissionType;   // member/profit
 
-    private BigDecimal orderAmount;
+    private Integer orderAmount;
 
-    private BigDecimal profitRate;
+    private Integer profitRate;
 
-    private BigDecimal commissionAmount;
+    private Integer commissionAmount;
 
     private String status;           // pending/settled/cancelled/withdrawn
 

+ 8 - 0
cfc-backend/src/main/java/com/etotem/cfc/entity/DanAssessmentResult.java

@@ -45,6 +45,14 @@ public class DanAssessmentResult implements Serializable {
 
     private Integer overallScore;  // 综合得分
 
+    // === 大五人格维度(Big Five / OCEAN) ===
+    private Integer opennessScore;  // 开放性(0-100)
+    private Integer conscientiousnessScore;  // 尽责性(0-100)
+    private Integer extraversionScore;  // 外向性(0-100)
+    private Integer agreeablenessScore;  // 宜人性(0-100)
+    private Integer neuroticismScore;  // 神经质(0-100)
+    private Integer bigFiveOverallScore;  // 大五人格综合分
+
     // === EMI 维度(情绪商数评估) ===
     private Integer emotionManagementScore;  // 情绪管理得分
     private Integer empathyScore;  // 同理心得分

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/EnergyDimensionConfig.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -22,7 +21,7 @@ public class EnergyDimensionConfig implements Serializable {
 
     private String category;
 
-    private BigDecimal weight;
+    private Integer weight;
 
     private Integer isActive;
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/EnergySourceConfig.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -29,7 +28,7 @@ public class EnergySourceConfig implements Serializable {
     private Long dimensionId;
 
     /** 占比如0.6000=60% */
-    private BigDecimal ratio;
+    private Integer ratio;
 
     private Date createdAt;
 }

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/FamilyMemberAttributes.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -38,10 +37,10 @@ public class FamilyMemberAttributes implements Serializable {
     private String bloodType;
 
     /** 心维度基础分(先天,0-100) */
-    private BigDecimal mindBaseScore;
+    private Integer mindBaseScore;
 
     /** 智维度基础分(先天,0-100) */
-    private BigDecimal wisdomBaseScore;
+    private Integer wisdomBaseScore;
 
     /** 行为修正因子JSON,记录各来源的修正值 */
     private String behaviorModifier;

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/FamilyMembership.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -32,7 +31,7 @@ public class FamilyMembership implements Serializable {
 
     private String transactionId;  // 交易流水号
 
-    private BigDecimal amount;  // 支付金额
+    private Integer amount;  // 支付金额(分)
 
     private Integer autoRenew;  // 自动续费
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/FinanceCheckin.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -24,7 +23,7 @@ public class FinanceCheckin implements Serializable {
 
     private Date checkinDate;
 
-    private BigDecimal amount;
+    private Integer amount;
 
     private String category;
 

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/Guide.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -61,7 +60,7 @@ public class Guide implements Serializable {
     /**
      * 评分
      */
-    private BigDecimal rating;
+    private Integer rating;
 
     /**
      * 总服务次数
@@ -84,7 +83,7 @@ public class Guide implements Serializable {
 
     private String avatar;
 
-    private BigDecimal commissionRate;
+    private Integer commissionRate;
 
     private Long streetId;
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/GuideApplication.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -28,7 +27,7 @@ public class GuideApplication implements Serializable {
 
     private String paymentProof;
 
-    private BigDecimal paymentAmount;
+    private Integer paymentAmount;
 
     private String status;
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/GuideFamily.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -22,7 +21,7 @@ public class GuideFamily implements Serializable {
 
     private String serviceType;  // 服务类型: monthly/yearly/consulting
 
-    private BigDecimal servicePrice;  // 服务价格
+    private Integer servicePrice;  // 服务价格(分)
 
     private String status;       // binding/paused/cancelled
 

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/GuidePackage.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -20,7 +19,7 @@ public class GuidePackage implements Serializable {
 
     private Long packageId;
 
-    private BigDecimal commissionRate;
+    private Integer commissionRate;
 
     private String name;
 
@@ -28,7 +27,7 @@ public class GuidePackage implements Serializable {
 
     private String description;
 
-    private BigDecimal price;
+    private Integer price;
 
     private Integer validityDays;
 

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/GuidePackageTemplate.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -20,9 +19,9 @@ public class GuidePackageTemplate implements Serializable {
 
     private Integer validityMonths;
 
-    private BigDecimal referencePrice;
+    private Integer referencePrice;
 
-    private BigDecimal minPrice;
+    private Integer minPrice;
 
     private String description;
 

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/InsurancePolicy.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -28,9 +27,9 @@ public class InsurancePolicy implements Serializable {
 
     private String insuredPerson;
 
-    private BigDecimal premium;
+    private Integer premium;
 
-    private BigDecimal sumInsured;
+    private Integer sumInsured;
 
     private Date startDate;
 

+ 2 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/MembershipLevel.java

@@ -21,9 +21,9 @@ public class MembershipLevel implements Serializable {
 
     private String levelDesc;  // 等级描述
 
-    private java.math.BigDecimal priceMonthly;  // 月费
+    private Integer priceMonthly;  // 月费(分)
 
-    private java.math.BigDecimal priceYearly;  // 年费
+    private Integer priceYearly;  // 年费(分)
 
     private String features;  // 功能权限列表(JSON)
 

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/PackageOrder.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -26,9 +25,9 @@ public class PackageOrder implements Serializable {
 
     private String packageName;   // 套餐名称
 
-    private BigDecimal price;      // 支付金额
+    private Integer price;      // 支付金额(分)
 
-    private BigDecimal platformFee; // 平台服务费
+    private Integer platformFee; // 平台服务费(分)
 
     private Long guideId;         // 成长规划师ID
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/PaymentOrder.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -24,7 +23,7 @@ public class PaymentOrder implements Serializable {
 
     private String paymentType;
 
-    private BigDecimal amount;
+    private Integer amount;
 
     private String status;
 

+ 4 - 5
cfc-backend/src/main/java/com/etotem/cfc/entity/Product.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -21,7 +20,7 @@ public class Product implements Serializable {
     private String intro;
     private String coverImage;
     private String images;
-    private BigDecimal price;
+    private Integer price;       // 价格(分)
     private Integer stock;
     private Integer salesCount;
     private String productType;
@@ -29,15 +28,15 @@ public class Product implements Serializable {
     private String vendorName;
     private String status;
     private String rejectReason;
-    private BigDecimal memberPrice;
+    private Integer memberPrice; // 会员价(分)
     private String memberEligible;
     private String domain;
     private String externalSource;
     private String externalId;
     private String externalData;
 
-    // 分佣系统 - 平台利润率(%)
-    private BigDecimal profitRate;
+    // 分佣系统 - 平台利润率(千分比)
+    private Integer profitRate;
 
     private Date createdAt;
     private Date updatedAt;

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/ProductOrder.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -23,8 +22,8 @@ public class ProductOrder implements Serializable {
     private Long buyerId;
     private Long familyId;
     private Integer quantity;
-    private BigDecimal unitPrice;
-    private BigDecimal totalAmount;
+    private Integer unitPrice;    // 单价(分)
+    private Integer totalAmount;  // 总价(分)
     private String status;
     private String paymentMethod;
     private String remark;

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/ServiceContent.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -26,7 +25,7 @@ public class ServiceContent implements Serializable {
 
     private String ageRange;
 
-    private BigDecimal price;
+    private Integer price;
 
     private String status;
 

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/entity/TaskTemplatePackage.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -28,9 +27,9 @@ public class TaskTemplatePackage implements Serializable {
 
     private String tags;         // 标签 JSON: ["学习", "专注"]
 
-    private BigDecimal price;    // 售价
+    private Integer price;    // 售价(分)
 
-    private BigDecimal platformFee;  // 平台服务费 (不超过10%)
+    private Integer platformFee;  // 平台服务费(分)
 
     private Integer isPublic;    // 是否公开到市场: 0/1
 

+ 1 - 1
cfc-backend/src/main/java/com/etotem/cfc/entity/Teacher.java

@@ -27,7 +27,7 @@ public class Teacher implements Serializable {
 
     private Integer experienceYears;  // 从业年限
 
-    private java.math.BigDecimal rating;  // 评分
+    private Integer rating;  // 评分(百分位,5.00=500)
 
     private Integer totalAppointments;  // 总测评次数
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/UpgradeService.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -22,7 +21,7 @@ public class UpgradeService implements Serializable {
 
     private String toLevel;
 
-    private BigDecimal serviceFee;
+    private Integer serviceFee;
 
     private String status;
 

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/entity/WithdrawalRequest.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -18,7 +17,7 @@ public class WithdrawalRequest implements Serializable {
 
     private Long userId;
 
-    private BigDecimal amount;
+    private Integer amount;
 
     private String accountInfo;     // JSON: 支付宝账号信息
 

+ 5 - 6
cfc-backend/src/main/java/com/etotem/cfc/entity/ZodiacConfig.java

@@ -6,7 +6,6 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Data
@@ -30,15 +29,15 @@ public class ZodiacConfig implements Serializable {
 
     private Integer endDay;
 
-    private BigDecimal mindBase;
+    private Integer mindBase;
 
-    private BigDecimal wisdomBase;
+    private Integer wisdomBase;
 
-    private BigDecimal bodyModifier;
+    private Integer bodyModifier;
 
-    private BigDecimal actionModifier;
+    private Integer actionModifier;
 
-    private BigDecimal wealthModifier;
+    private Integer wealthModifier;
 
     private Date createdAt;
 }

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

@@ -24,9 +24,10 @@ public class ActivityService extends ServiceImpl<ActivityMapper, Activity> {
         if (dimensionCode != null && !dimensionCode.isEmpty()) {
             query.eq(Activity::getDimensionCode, dimensionCode);
         }
-        // 游客过滤:排除会员专属活动
+        // 游客过滤:只返回公开活动
         if (userId == null) {
-            query.and(w -> w.eq(Activity::getVisibility, "all")
+            query.and(w -> w.eq(Activity::getVisibility, "public")
+                    .or().eq(Activity::getVisibility, "all")
                     .or().isNull(Activity::getVisibility));
         }
         Page<Activity> pageResult = this.page(new Page<>(page, size), query);

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

@@ -64,7 +64,7 @@ public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, A
         boolean updated = this.updateById(order);
         if (updated) {
             commissionService.settle(order.getId(), "assessment", order.getUserId(),
-                    new java.math.BigDecimal(order.getActualPrice()), null);
+                    order.getActualPrice() != null ? order.getActualPrice().intValue() : null, null);
         }
         return updated;
     }

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

@@ -72,14 +72,14 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         if (config == null) {
             config = new AssessmentPointsConfig();
             config.setPointsValue(pointsValue);
-            config.setPointsValueYuan(new java.math.BigDecimal(pointsValueYuan));
+            config.setPointsValueYuan((int)(pointsValueYuan * 100));
             config.setIsActive(1);
             config.setCreatedAt(new Date());
             config.setUpdatedAt(new Date());
             return pointsConfigMapper.insert(config) > 0;
         }
         config.setPointsValue(pointsValue);
-        config.setPointsValueYuan(new java.math.BigDecimal(pointsValueYuan));
+        config.setPointsValueYuan((int)(pointsValueYuan * 100));
         config.setUpdatedAt(new Date());
         return pointsConfigMapper.updateById(config) > 0;
     }

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/BindInviteService.java

@@ -8,7 +8,6 @@ import com.etotem.cfc.entity.User;
 import com.etotem.cfc.mapper.UserMapper;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
@@ -40,7 +39,7 @@ public class BindInviteService {
         gf.setGuideId(guideId);
         gf.setFamilyId(0L); // 暂时为0,家长确认时再设置
         gf.setServiceType("consulting");
-        gf.setServicePrice(BigDecimal.ZERO);
+        gf.setServicePrice(0);
         gf.setStatus("pending"); // 待确认状态
         gf.setBoundAt(new Date());
         gf.setCreatedAt(new Date());
@@ -72,7 +71,7 @@ public class BindInviteService {
      * @param servicePrice 服务价格
      * @return 绑定结果
      */
-    public boolean confirmBind(String inviteToken, Long guideId, Long familyId, String serviceType, BigDecimal servicePrice) {
+    public boolean confirmBind(String inviteToken, Long guideId, Long familyId, String serviceType, Integer servicePrice) {
         // 确认绑定
         return guideFamilyService.confirmBind(guideId, familyId, serviceType, servicePrice);
     }

+ 60 - 78
cfc-backend/src/main/java/com/etotem/cfc/service/CommissionService.java

@@ -17,11 +17,11 @@ import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Random;
 import java.util.stream.Collectors;
 
@@ -30,10 +30,6 @@ public class CommissionService {
 
     private static final Logger log = LoggerFactory.getLogger(CommissionService.class);
 
-    // 产品利润佣金提成比例(已废弃,改用 sys_config commission_product_profit_share)
-    // 保留为静态备用值
-    private static final BigDecimal PROFIT_COMMISSION_RATE = new BigDecimal("0.30");
-
     @Resource
     private UserMapper userMapper;
 
@@ -52,21 +48,9 @@ public class CommissionService {
     // ==================== 工具方法 ====================
 
     /**
-     * 从系统配置获取bps费率并转为BigDecimal
-     * 如 2000bps = 0.20 (20%)
-     */
-    private BigDecimal getRateFromConfig(String key, int defaultBps) {
-        String val = sysConfigService.getValue(key);
-        if (val == null) {
-            return BigDecimal.valueOf(defaultBps).divide(new BigDecimal("10000"));
-        }
-        return BigDecimal.valueOf(Long.parseLong(val)).divide(new BigDecimal("10000"));
-    }
-
-    /**
-     * 从系统配置获取bps整数值
+     * 从系统配置获取bps整数值(如 2000 = 20%)
      */
-    private int getIntConfig(String key, int defaultValue) {
+    private int getRateBps(String key, int defaultValue) {
         String val = sysConfigService.getValue(key);
         if (val == null) {
             return defaultValue;
@@ -145,10 +129,10 @@ public class CommissionService {
         LambdaQueryWrapper<CommissionRecord> wrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId)
                 .eq(CommissionRecord::getStatus, "settled");
-        BigDecimal total = commissionRecordMapper.selectList(wrapper).stream()
+        Integer total = commissionRecordMapper.selectList(wrapper).stream()
                 .map(CommissionRecord::getCommissionAmount)
-                .filter(a -> a != null)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                .filter(Objects::nonNull)
+                .reduce(0, Integer::sum);
         dto.setTotalEarnings(total);
         return dto;
     }
@@ -160,7 +144,7 @@ public class CommissionService {
      * 内部委托给settleTwoLevel实现L1+L2佣金
      */
     public void settle(Long orderId, String orderType, Long buyerId,
-                       BigDecimal orderAmount, Long productId) {
+                       Integer orderAmount, Long productId) {
         settleTwoLevel(orderId, orderType, buyerId, orderAmount, productId);
     }
 
@@ -168,13 +152,13 @@ public class CommissionService {
      * 两级佣金结算(L1+L2)
      * - L1: 买家的直接推荐人获得佣金
      * - L2: 如果L1推荐人也有推荐人,且订单类型为membership,L2获得佣金
-     * - 佣金费率从sys_config动态读取
+     * - 佣金费率从sys_config动态读取(bps)
      * - 默认状态为pending,settledAt为7天后
      */
     public void settleTwoLevel(Long orderId, String orderType, Long buyerId,
-                               BigDecimal orderAmount, Long productId) {
+                                Integer orderAmount, Long productId) {
         try {
-            if (buyerId == null || orderAmount == null || orderAmount.compareTo(BigDecimal.ZERO) <= 0) {
+            if (buyerId == null || orderAmount == null || orderAmount <= 0) {
                 return;
             }
 
@@ -190,12 +174,12 @@ public class CommissionService {
                 return;
             }
 
-            BigDecimal l1Amount = BigDecimal.ZERO;
+            int l1Amount = 0;
             String commissionType;
 
             if ("membership".equals(orderType)) {
-                BigDecimal rate = getRateFromConfig("commission_member_l1_rate", 2000);
-                l1Amount = orderAmount.multiply(rate);
+                int rateBps = getRateBps("commission_member_l1_rate", 2000);
+                l1Amount = orderAmount * rateBps / 10000;
                 commissionType = "member";
             } else {
                 // 非会员订单:只有FAMILY用户的推荐人能获得产品利润佣金
@@ -204,54 +188,52 @@ public class CommissionService {
                 if (productId != null) {
                     Product product = productMapper.selectById(productId);
                     if (product != null && product.getProfitRate() != null) {
-                        BigDecimal profitRate = product.getProfitRate();
+                        int profitRate = product.getProfitRate();
                         if (isFamily) {
                             // FAMILY推荐人获取利润佣金
-                            BigDecimal profitShare = getRateFromConfig("commission_product_profit_share", 1000);
-                            l1Amount = orderAmount.multiply(profitRate)
-                                    .divide(new BigDecimal("100"))
-                                    .multiply(profitShare);
+                            int profitShareBps = getRateBps("commission_product_profit_share", 1000);
+                            l1Amount = orderAmount * profitRate / 100 * profitShareBps / 10000;
                             commissionType = "profit";
                         } else {
                             // FREE推荐人只获得member类型佣金(不计利润分成)
-                            l1Amount = BigDecimal.ZERO;
+                            l1Amount = 0;
                             commissionType = "member";
                         }
                     } else {
                         // 没有利润率的产品,只给FAMILY推荐人基础服务佣金
                         if (isFamily) {
-                            BigDecimal serviceRate = getRateFromConfig("commission_service_rate", 1000);
-                            l1Amount = orderAmount.multiply(serviceRate);
+                            int serviceRateBps = getRateBps("commission_service_rate", 1000);
+                            l1Amount = orderAmount * serviceRateBps / 10000;
                             commissionType = "service";
                         } else {
-                            l1Amount = BigDecimal.ZERO;
+                            l1Amount = 0;
                             commissionType = "member";
                         }
                     }
                 } else {
                     // 没有productId的非会员订单(如评估、套餐)
                     if (isFamily) {
-                        BigDecimal serviceRate = getRateFromConfig("commission_service_rate", 1000);
-                        l1Amount = orderAmount.multiply(serviceRate);
+                        int serviceRateBps = getRateBps("commission_service_rate", 1000);
+                        l1Amount = orderAmount * serviceRateBps / 10000;
                         commissionType = "service";
                     } else {
-                        l1Amount = BigDecimal.ZERO;
+                        l1Amount = 0;
                         commissionType = "member";
                     }
                 }
             }
 
             // 创建L1佣金记录(金额>0才创建)
-            if (l1Amount.compareTo(BigDecimal.ZERO) > 0) {
+            if (l1Amount > 0) {
                 createCommissionRecord(orderId, orderType, l1ReferrerId, buyerId,
-                        commissionType, orderAmount, BigDecimal.ZERO, l1Amount,
+                        commissionType, orderAmount, 0, l1Amount,
                         1, "settled", new Date());
             }
 
             // 更新推荐人的累计佣金
             l1Referrer.setTotalCommissionEarned(
                     (l1Referrer.getTotalCommissionEarned() != null ? l1Referrer.getTotalCommissionEarned() : 0L)
-                            + l1Amount.longValue());
+                            + l1Amount);
             userMapper.updateById(l1Referrer);
 
             log.info("L1佣金结算成功: orderId={}, referrerId={}, amount={}, level=1",
@@ -262,17 +244,17 @@ public class CommissionService {
                 Long l2ReferrerId = l1Referrer.getReferrerId();
                 User l2Referrer = userMapper.selectById(l2ReferrerId);
                 if (l2Referrer != null) {
-                    BigDecimal l2Rate = getRateFromConfig("commission_member_l2_rate", 500);
-                    BigDecimal l2Amount = orderAmount.multiply(l2Rate);
+                    int l2RateBps = getRateBps("commission_member_l2_rate", 500);
+                    int l2Amount = orderAmount * l2RateBps / 10000;
 
-                    if (l2Amount.compareTo(BigDecimal.ZERO) > 0) {
+                    if (l2Amount > 0) {
                         createCommissionRecord(orderId, orderType, l2ReferrerId, buyerId,
-                                "member", orderAmount, BigDecimal.ZERO, l2Amount,
+                                "member", orderAmount, 0, l2Amount,
                                 2, "settled", new Date());
 
                         l2Referrer.setTotalCommissionEarned(
                                 (l2Referrer.getTotalCommissionEarned() != null ? l2Referrer.getTotalCommissionEarned() : 0L)
-                                        + l2Amount.longValue());
+                                        + l2Amount);
                         userMapper.updateById(l2Referrer);
 
                         // 更新L1推荐人的间接推荐人数
@@ -295,8 +277,8 @@ public class CommissionService {
      * 创建佣金记录
      */
     private void createCommissionRecord(Long orderId, String orderType, Long referrerId,
-                                        Long buyerId, String commissionType, BigDecimal orderAmount,
-                                        BigDecimal profitRate, BigDecimal commissionAmount,
+                                        Long buyerId, String commissionType, Integer orderAmount,
+                                        Integer profitRate, Integer commissionAmount,
                                         Integer level, String status, Date settledAt) {
         CommissionRecord record = new CommissionRecord();
         record.setOrderId(orderId);
@@ -323,27 +305,27 @@ public class CommissionService {
         LambdaQueryWrapper<CommissionRecord> allWrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId)
                 .ne(CommissionRecord::getStatus, "cancelled");
-        BigDecimal totalCommission = commissionRecordMapper.selectList(allWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        Integer totalCommission = commissionRecordMapper.selectList(allWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
         dto.setTotalCommission(totalCommission);
 
         // 已结算(settled)
         LambdaQueryWrapper<CommissionRecord> settledWrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId)
                 .eq(CommissionRecord::getStatus, "settled");
-        BigDecimal settledAmount = commissionRecordMapper.selectList(settledWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        Integer settledAmount = commissionRecordMapper.selectList(settledWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
         dto.setSettledAmount(settledAmount);
 
         // 待结算(pending)
         LambdaQueryWrapper<CommissionRecord> pendingWrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId)
                 .eq(CommissionRecord::getStatus, "pending");
-        BigDecimal pendingAmount = commissionRecordMapper.selectList(pendingWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        Integer pendingAmount = commissionRecordMapper.selectList(pendingWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
         dto.setPendingAmount(pendingAmount);
 
         dto.setAvailableAmount(getAvailableAmount(userId));
@@ -363,7 +345,7 @@ public class CommissionService {
     /**
      * 获取可提现金额(已结算 - 已提现,排除cancelled)
      */
-    public BigDecimal getAvailableAmount(Long userId) {
+    public Integer getAvailableAmount(Long userId) {
         // 已结算(settled + pending中已过settledAt的)
         LambdaQueryWrapper<CommissionRecord> availableWrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId)
@@ -373,13 +355,13 @@ public class CommissionService {
                         .or(i -> i.eq(CommissionRecord::getStatus, "pending")
                                 .isNotNull(CommissionRecord::getSettledAt)
                                 .le(CommissionRecord::getSettledAt, new Date())));
-        BigDecimal available = commissionRecordMapper.selectList(availableWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        int available = commissionRecordMapper.selectList(availableWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
 
-        BigDecimal withdrawn = getWithdrawnAmount(userId);
+        int withdrawn = getWithdrawnAmount(userId);
 
-        return available.subtract(withdrawn).max(BigDecimal.ZERO);
+        return Math.max(available - withdrawn, 0);
     }
 
     /**
@@ -408,9 +390,9 @@ public class CommissionService {
         LambdaQueryWrapper<CommissionRecord> teamWrapper = new LambdaQueryWrapper<CommissionRecord>()
                 .eq(CommissionRecord::getReferrerId, userId)
                 .ne(CommissionRecord::getStatus, "cancelled");
-        BigDecimal totalTeamCommission = commissionRecordMapper.selectList(teamWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        int totalTeamCommission = commissionRecordMapper.selectList(teamWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
         stats.put("totalCommission", totalTeamCommission);
 
         return stats;
@@ -430,9 +412,9 @@ public class CommissionService {
                 .ne(CommissionRecord::getStatus, "cancelled")
                 .ge(CommissionRecord::getCreatedAt, getStartOfDay(now))
                 .le(CommissionRecord::getCreatedAt, now);
-        BigDecimal todayCommission = commissionRecordMapper.selectList(todayWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        int todayCommission = commissionRecordMapper.selectList(todayWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
         stats.put("todayCommission", todayCommission);
 
         // 本月佣金
@@ -441,9 +423,9 @@ public class CommissionService {
                 .ne(CommissionRecord::getStatus, "cancelled")
                 .ge(CommissionRecord::getCreatedAt, getStartOfMonth(now))
                 .le(CommissionRecord::getCreatedAt, now);
-        BigDecimal monthCommission = commissionRecordMapper.selectList(monthWrapper).stream()
-                .map(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+        int monthCommission = commissionRecordMapper.selectList(monthWrapper).stream()
+                .mapToInt(r -> r.getCommissionAmount() != null ? r.getCommissionAmount() : 0)
+                .sum();
         stats.put("monthCommission", monthCommission);
 
         // 累计佣金
@@ -458,14 +440,14 @@ public class CommissionService {
         return stats;
     }
 
-    private BigDecimal getWithdrawnAmount(Long userId) {
+    private Integer getWithdrawnAmount(Long userId) {
         LambdaQueryWrapper<WithdrawalRequest> wrapper =
                 new LambdaQueryWrapper<WithdrawalRequest>()
                         .eq(WithdrawalRequest::getUserId, userId)
                         .eq(WithdrawalRequest::getStatus, "approved");
         return withdrawalRequestMapper.selectList(wrapper).stream()
-                .map(r -> r.getAmount() != null ? r.getAmount() : BigDecimal.ZERO)
-                .reduce(BigDecimal.ZERO, BigDecimal::add);
+                .mapToInt(r -> r.getAmount() != null ? r.getAmount() : 0)
+                .sum();
     }
 
     private Date getStartOfDay(Date date) {

+ 3 - 4
cfc-backend/src/main/java/com/etotem/cfc/service/DataMigrationService.java

@@ -11,7 +11,6 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.util.*;
 
@@ -464,9 +463,9 @@ public class DataMigrationService implements DataMigrationServiceInterface {
                     if (userId == null || familyId == null) continue;
 
                     String status = mapOrderStatus((String) row.get("order_status"));
-                    BigDecimal fee = row.get("fee_total") != null
-                        ? BigDecimal.valueOf(((Number) row.get("fee_total")).longValue()).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_HALF_UP)
-                        : BigDecimal.ZERO;
+                    Integer fee = row.get("fee_total") != null
+                        ? ((Number) row.get("fee_total")).intValue()
+                        : 0;
 
                     PackageOrder order = new PackageOrder();
                     order.setOrderNo((String) row.get("order_no"));

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

@@ -66,7 +66,6 @@ public class DatabaseSyncService {
         JAVA_TYPE_TO_SQL_TYPE.put(Short.class, "SMALLINT");
         JAVA_TYPE_TO_SQL_TYPE.put(Float.class, "FLOAT");
         JAVA_TYPE_TO_SQL_TYPE.put(Double.class, "DOUBLE");
-        JAVA_TYPE_TO_SQL_TYPE.put(java.math.BigDecimal.class, "DECIMAL(10,2)");
     }
 
     // @PostConstruct

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

@@ -33,6 +33,12 @@ public class EmiReportService {
         dto.setStressCopingScore(result.getStressCopingScore());
         dto.setSelfAwarenessScore(result.getSelfAwarenessScore());
         dto.setOverallScore(result.getOverallScore());
+        dto.setOpennessScore(result.getOpennessScore());
+        dto.setConscientiousnessScore(result.getConscientiousnessScore());
+        dto.setExtraversionScore(result.getExtraversionScore());
+        dto.setAgreeablenessScore(result.getAgreeablenessScore());
+        dto.setNeuroticismScore(result.getNeuroticismScore());
+        dto.setBigFiveOverallScore(result.getBigFiveOverallScore());
         dto.setAnalysisReport(result.getAnalysisReport());
         dto.setGrowthSuggestions(result.getGrowthSuggestions());
         dto.setAssessmentDate(result.getAssessmentDate());

+ 13 - 15
cfc-backend/src/main/java/com/etotem/cfc/service/EnergyService.java

@@ -11,8 +11,7 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
+
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -600,7 +599,7 @@ public class EnergyService {
                         .eq(EnergySourceConfig::getSourceType, sourceType)
                         .eq(EnergySourceConfig::getSourceId, sourceId)
         );
-        Map<Long, BigDecimal> dimRatios = resolveDimensionRatios(configs, sourceType, sourceId);
+        Map<Long, Integer> dimRatios = resolveDimensionRatios(configs, sourceType, sourceId);
 
         if (dimRatios.isEmpty()) return new HashMap<>();
 
@@ -742,7 +741,7 @@ public class EnergyService {
         );
         for (Map<String, Object> r : ratios) {
             String dimCode = (String) r.get("dimensionCode");
-            BigDecimal ratioVal = new BigDecimal(r.get("ratio").toString());
+            Integer ratioVal = Integer.valueOf(r.get("ratio").toString());
             EnergyDimension dim = getDimByCode(dimCode);
             if (dim == null) continue;
 
@@ -762,41 +761,40 @@ public class EnergyService {
     /**
      * 解析维度比例配置,按Fallback链降级
      */
-    private Map<Long, BigDecimal> resolveDimensionRatios(
+    private Map<Long, Integer> resolveDimensionRatios(
             List<EnergySourceConfig> configs, String sourceType, Long sourceId) {
 
         if (!configs.isEmpty()) {
-            Map<Long, BigDecimal> result = new LinkedHashMap<>();
+            Map<Long, Integer> result = new LinkedHashMap<>();
             for (EnergySourceConfig c : configs) result.put(c.getDimensionId(), c.getRatio());
             return result;
         }
 
         // Fallback: 默认 → 行(action) 100%
         EnergyDimension action = getDimByCode("action");
-        if (action != null) return Collections.singletonMap(action.getId(), BigDecimal.ONE);
+        if (action != null) return Collections.singletonMap(action.getId(), 10000);
         return Collections.emptyMap();
     }
 
     /**
      * 按比例分配整数,余数加到最大比例维度
      */
-    private Map<Long, Integer> calculateAllocations(Integer total, Map<Long, BigDecimal> ratios) {
-        BigDecimal totalRatio = ratios.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
-        if (totalRatio.compareTo(BigDecimal.ZERO) == 0) return Collections.emptyMap();
+    private Map<Long, Integer> calculateAllocations(Integer total, Map<Long, Integer> ratios) {
+        int totalRatio = ratios.values().stream().mapToInt(Integer::intValue).sum();
+        if (totalRatio == 0) return Collections.emptyMap();
 
         Map<Long, Integer> result = new LinkedHashMap<>();
         int allocated = 0;
 
         // 第一轮:按比例分配(向下取整)
         Long maxRatioDim = null;
-        BigDecimal maxRatio = BigDecimal.ZERO;
-        for (Map.Entry<Long, BigDecimal> entry : ratios.entrySet()) {
-            BigDecimal share = BigDecimal.valueOf(total).multiply(entry.getValue()).divide(totalRatio, 0, RoundingMode.DOWN);
-            int val = share.intValue();
+        int maxRatio = 0;
+        for (Map.Entry<Long, Integer> entry : ratios.entrySet()) {
+            int val = total * entry.getValue() / totalRatio;
             result.put(entry.getKey(), val);
             allocated += val;
 
-            if (entry.getValue().compareTo(maxRatio) > 0) {
+            if (entry.getValue() > maxRatio) {
                 maxRatio = entry.getValue();
                 maxRatioDim = entry.getKey();
             }

+ 18 - 22
cfc-backend/src/main/java/com/etotem/cfc/service/FamilyMemberAttributeService.java

@@ -10,8 +10,6 @@ import com.etotem.cfc.mapper.BloodTypeConfigMapper;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
-import java.math.RoundingMode;
 import java.util.*;
 import java.util.Calendar;
 
@@ -208,39 +206,39 @@ public class FamilyMemberAttributeService extends ServiceImpl<FamilyMemberAttrib
      * @param dimensionCode "mind" or "wisdom"
      * @return computed base score (0-100)
      */
-    public BigDecimal calcInnateScore(Long memberId, String memberType, String dimensionCode) {
+    public Integer calcInnateScore(Long memberId, String memberType, String dimensionCode) {
         FamilyMemberAttributes attrs = getByMember(memberId, memberType);
         if (attrs == null) {
-            return BigDecimal.ZERO;
+            return 0;
         }
 
         // If already computed, return cached value
         if ("mind".equals(dimensionCode) && attrs.getMindBaseScore() != null
-                && attrs.getMindBaseScore().compareTo(BigDecimal.ZERO) > 0) {
+                && attrs.getMindBaseScore() > 0) {
             return attrs.getMindBaseScore();
         }
         if ("wisdom".equals(dimensionCode) && attrs.getWisdomBaseScore() != null
-                && attrs.getWisdomBaseScore().compareTo(BigDecimal.ZERO) > 0) {
+                && attrs.getWisdomBaseScore() > 0) {
             return attrs.getWisdomBaseScore();
         }
 
         // --- Zodiac contribution (50%) ---
-        BigDecimal zodiacScore = BigDecimal.ZERO;
+        Integer zodiacScore = 0;
         if (attrs.getZodiac() != null) {
             LambdaQueryWrapper<ZodiacConfig> zodiacWrapper = new LambdaQueryWrapper<>();
             zodiacWrapper.eq(ZodiacConfig::getZodiacCode, attrs.getZodiac());
             ZodiacConfig zodiacConfig = zodiacConfigMapper.selectOne(zodiacWrapper);
             if (zodiacConfig != null) {
                 zodiacScore = "mind".equals(dimensionCode) ? zodiacConfig.getMindBase() : zodiacConfig.getWisdomBase();
-                if (zodiacScore == null) zodiacScore = BigDecimal.ZERO;
+                if (zodiacScore == null) zodiacScore = 0;
             }
         }
 
         // --- BaZi contribution (30%) - average of all stems/branches in eightCharacters ---
-        BigDecimal baziScore = BigDecimal.ZERO;
+        Integer baziScore = 0;
         if (attrs.getEightCharacters() != null) {
             Map<String, Object> eightCharMap = fromJson(attrs.getEightCharacters());
-            List<BigDecimal> scores = new ArrayList<>();
+            List<Integer> scores = new ArrayList<>();
             for (Map.Entry<String, Object> entry : eightCharMap.entrySet()) {
                 String pillar = String.valueOf(entry.getValue());
                 if (pillar != null && pillar.length() >= 1) {
@@ -250,7 +248,7 @@ public class FamilyMemberAttributeService extends ServiceImpl<FamilyMemberAttrib
                     baziWrapper.eq(BaziConfig::getType, "stem");
                     BaziConfig baziConfig = baziConfigMapper.selectOne(baziWrapper);
                     if (baziConfig != null) {
-                        BigDecimal val = "mind".equals(dimensionCode) ? baziConfig.getMindBase() : baziConfig.getWisdomBase();
+                        Integer val = "mind".equals(dimensionCode) ? baziConfig.getMindBase() : baziConfig.getWisdomBase();
                         if (val != null) scores.add(val);
                     }
                 }
@@ -261,35 +259,33 @@ public class FamilyMemberAttributeService extends ServiceImpl<FamilyMemberAttrib
                     baziWrapper.eq(BaziConfig::getType, "branch");
                     BaziConfig baziConfig = baziConfigMapper.selectOne(baziWrapper);
                     if (baziConfig != null) {
-                        BigDecimal val = "mind".equals(dimensionCode) ? baziConfig.getMindBase() : baziConfig.getWisdomBase();
+                        Integer val = "mind".equals(dimensionCode) ? baziConfig.getMindBase() : baziConfig.getWisdomBase();
                         if (val != null) scores.add(val);
                     }
                 }
             }
             if (!scores.isEmpty()) {
-                BigDecimal sum = BigDecimal.ZERO;
-                for (BigDecimal s : scores) sum = sum.add(s);
-                baziScore = sum.divide(BigDecimal.valueOf(scores.size()), 4, RoundingMode.HALF_UP);
+                int sum = 0;
+                for (Integer s : scores) sum = sum + s;
+                baziScore = (sum + scores.size() / 2) / scores.size();
             }
         }
 
         // --- Blood type contribution (20%) ---
-        BigDecimal bloodScore = BigDecimal.ZERO;
+        Integer bloodScore = 0;
         if (attrs.getBloodType() != null) {
             LambdaQueryWrapper<BloodTypeConfig> bloodWrapper = new LambdaQueryWrapper<>();
             bloodWrapper.eq(BloodTypeConfig::getBloodType, attrs.getBloodType());
             BloodTypeConfig bloodConfig = bloodTypeConfigMapper.selectOne(bloodWrapper);
             if (bloodConfig != null) {
                 bloodScore = "mind".equals(dimensionCode) ? bloodConfig.getMindBase() : bloodConfig.getWisdomBase();
-                if (bloodScore == null) bloodScore = BigDecimal.ZERO;
+                if (bloodScore == null) bloodScore = 0;
             }
         }
 
-        // --- Weighted sum ---
-        BigDecimal result = zodiacScore.multiply(BigDecimal.valueOf(0.5))
-                .add(baziScore.multiply(BigDecimal.valueOf(0.3)))
-                .add(bloodScore.multiply(BigDecimal.valueOf(0.2)))
-                .setScale(2, RoundingMode.HALF_UP);
+        // --- Weighted sum: zodiac×50% + bazi×30% + blood×20% ---
+        // Weights in bps: 50% = 5000, 30% = 3000, 20% = 2000
+        Integer result = (zodiacScore * 5000 + baziScore * 3000 + bloodScore * 2000) / 10000;
 
         // Cache the result
         if ("mind".equals(dimensionCode)) {

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

@@ -59,7 +59,7 @@ public class GuideFamilyService {
     /**
      * 确认绑定
      */
-    public boolean confirmBind(Long guideId, Long familyId, String serviceType, java.math.BigDecimal servicePrice) {
+    public boolean confirmBind(Long guideId, Long familyId, String serviceType, Integer servicePrice) {
         // 检查家庭是否已绑定其他规划师
         GuideFamily existing = guideFamilyMapper.selectOne(
             new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<GuideFamily>()

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/GuidePackageService.java

@@ -11,7 +11,6 @@ import com.etotem.cfc.mapper.GuidePackageMapper;
 import com.etotem.cfc.mapper.TaskTemplatePackageMapper;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
 import java.util.List;
 
 /**
@@ -26,7 +25,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     /**
      * 添加指导师套餐
      */
-    public boolean addGuidePackage(Long guideId, Long packageId, BigDecimal price, BigDecimal commissionRate) {
+    public boolean addGuidePackage(Long guideId, Long packageId, Integer price, Integer commissionRate) {
         // 检查是否已经存在
         LambdaQueryWrapper<GuidePackage> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(GuidePackage::getGuideId, guideId)
@@ -78,7 +77,7 @@ public class GuidePackageService extends ServiceImpl<GuidePackageMapper, GuidePa
     /**
      * 更新指导师套餐价格
      */
-    public boolean updateGuidePackagePrice(Long guideId, Long packageId, BigDecimal price) {
+    public boolean updateGuidePackagePrice(Long guideId, Long packageId, Integer price) {
         GuidePackage guidePackage = getGuidePackage(guideId, packageId);
         if (guidePackage == null) {
             return false;

+ 12 - 14
cfc-backend/src/main/java/com/etotem/cfc/service/MembershipService.java

@@ -9,7 +9,6 @@ import com.etotem.cfc.mapper.*;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -169,16 +168,16 @@ public class MembershipService implements MembershipServiceInterface {
             throw new RuntimeException("会员等级不存在");
         }
 
-        // 从系统配置读取会员费用
-        BigDecimal amount;
+        // 从系统配置读取会员费用(分)
+        Integer amount;
         if ("FAMILY".equals(levelCode)) {
             String feeStr = sysConfigService.getValue("member_fee_family");
-            long fee = feeStr != null ? Long.parseLong(feeStr) : 36500L; // 默认36500分=365元
-            amount = BigDecimal.valueOf(fee);
+            int fee = feeStr != null ? Integer.parseInt(feeStr) : 36500; // 默认36500分=365元
+            amount = fee;
         } else if ("PROVIDER".equals(levelCode)) {
             String feeStr = sysConfigService.getValue("member_fee_standard");
-            long fee = feeStr != null ? Long.parseLong(feeStr) : 1314L;
-            amount = BigDecimal.valueOf(fee);
+            int fee = feeStr != null ? Integer.parseInt(feeStr) : 1314;
+            amount = fee;
         } else {
             amount = "yearly".equals(paymentType) ? level.getPriceYearly() : level.getPriceMonthly();
         }
@@ -358,11 +357,11 @@ public class MembershipService implements MembershipServiceInterface {
     }
 
     /**
-     * 应用会员折扣
+     * 应用会员折扣,返回折后价格(分)
      */
-    public BigDecimal applyMemberDiscount(Long userId, BigDecimal originalPrice) {
-        if (originalPrice == null || originalPrice.compareTo(BigDecimal.ZERO) <= 0) {
-            return BigDecimal.ZERO;
+    public Integer applyMemberDiscount(Long userId, Integer originalPrice) {
+        if (originalPrice == null || originalPrice <= 0) {
+            return 0;
         }
 
         String level = getMemberLevel(userId);
@@ -370,9 +369,8 @@ public class MembershipService implements MembershipServiceInterface {
             String discountStr = sysConfigService.getValue("member_discount_family");
             if (discountStr != null) {
                 // discount is in bps (9000 = 90% = 10% off)
-                BigDecimal discountBps = new BigDecimal(discountStr);
-                BigDecimal discountRate = discountBps.divide(new BigDecimal("10000"));
-                return originalPrice.multiply(discountRate);
+                int discountBps = Integer.parseInt(discountStr);
+                return originalPrice * discountBps / 10000;
             }
         }
         return originalPrice;

+ 4 - 5
cfc-backend/src/main/java/com/etotem/cfc/service/PackagePaymentService.java

@@ -16,7 +16,6 @@ import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 import org.springframework.web.client.RestTemplate;
 
-import java.math.BigDecimal;
 import java.util.Date;
 import java.util.Map;
 import java.util.UUID;
@@ -60,15 +59,15 @@ public class PackagePaymentService implements PackagePaymentServiceInterface {
         }
 
         // 如果套餐免费,直接创建并返回
-        if (pkg.getPrice() == null || pkg.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
+        if (pkg.getPrice() == null || pkg.getPrice() <= 0) {
             PackageOrder order = new PackageOrder();
             order.setOrderNo(generateOrderNo());
             order.setUserId(userId);
             order.setFamilyId(familyId);
             order.setPackageId(packageId);
             order.setPackageName(pkg.getName());
-            order.setPrice(BigDecimal.ZERO);
-            order.setPlatformFee(BigDecimal.ZERO);
+            order.setPrice(0);
+            order.setPlatformFee(0);
             order.setGuideId(pkg.getCreatorId());
             order.setStatus("paid");
             order.setPayMethod("free");
@@ -117,7 +116,7 @@ public class PackagePaymentService implements PackagePaymentServiceInterface {
         params.put("nonce_str", UUID.randomUUID().toString().replace("-", "").substring(0, 16));
         params.put("body", "浠艾福-" + order.getPackageName());
         params.put("out_trade_no", order.getOrderNo());
-        params.put("total_fee", order.getPrice().multiply(new BigDecimal("100")).intValue());
+        params.put("total_fee", order.getPrice() * 100);
         params.put("spbill_create_ip", "127.0.0.1");
         params.put("notify_url", notifyUrl);
         params.put("trade_type", "JSAPI");

+ 8 - 9
cfc-backend/src/main/java/com/etotem/cfc/service/PackagePurchaseService.java

@@ -17,7 +17,6 @@ import com.etotem.cfc.mapper.TaskTemplatePackageMapper;
 import com.etotem.cfc.mapper.UserMapper;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -66,7 +65,7 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
             GuidePackage guidePackage = guidePackageService.getGuidePackage(guideId, packageId);
             if (guidePackage != null) {
                 result.put("guidePrice", guidePackage.getPrice());
-                result.put("commissionRate", new BigDecimal("0.1"));
+                result.put("commissionRate", 1000); // 10% in bps
                 result.put("totalPrice", guidePackage.getPrice());
                 
                 // 获取指导师信息
@@ -78,7 +77,7 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
             } else {
                 // 指导师没有设置该套餐的价格,使用基础价格
                 result.put("guidePrice", taskPackage.getPrice());
-                result.put("commissionRate", new BigDecimal("0.1"));
+                result.put("commissionRate", 1000); // 10% in bps
                 result.put("totalPrice", taskPackage.getPrice());
             }
         } else if (inviteCode != null && !inviteCode.isEmpty()) {
@@ -88,7 +87,7 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
                 GuidePackage guidePackage = guidePackageService.getGuidePackage(invite.getGuideId(), packageId);
                 if (guidePackage != null) {
                     result.put("guidePrice", guidePackage.getPrice());
-                    result.put("commissionRate", new BigDecimal("0.1"));
+                    result.put("commissionRate", 1000); // 10% in bps
                     result.put("totalPrice", guidePackage.getPrice());
                     result.put("guideId", invite.getGuideId());
                     
@@ -101,20 +100,20 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
                 } else {
                     // 指导师没有设置该套餐的价格,使用基础价格
                     result.put("guidePrice", taskPackage.getPrice());
-                    result.put("commissionRate", new BigDecimal("0.1"));
+                    result.put("commissionRate", 1000); // 10% in bps
                     result.put("totalPrice", taskPackage.getPrice());
                     result.put("guideId", invite.getGuideId());
                 }
             } else {
                 // 邀请码无效,使用基础价格
                 result.put("guidePrice", taskPackage.getPrice());
-                result.put("commissionRate", new BigDecimal("0.1"));
+                result.put("commissionRate", 1000); // 10% in bps
                 result.put("totalPrice", taskPackage.getPrice());
             }
         } else {
             // 没有指导师,使用基础价格
             result.put("guidePrice", taskPackage.getPrice());
-            result.put("commissionRate", new BigDecimal("0.1"));
+            result.put("commissionRate", 1000);
             result.put("totalPrice", taskPackage.getPrice());
         }
 
@@ -176,8 +175,8 @@ public class PackagePurchaseService implements PackagePurchaseServiceInterface {
         order.setFamilyId(dto.getFamilyId());
         order.setPackageId(dto.getPackageId());
         order.setPackageName((String) priceInfo.get("packageName"));
-        order.setPrice((BigDecimal) priceInfo.get("totalPrice"));
-        order.setPlatformFee((BigDecimal) priceInfo.get("platformFee"));
+        order.setPrice((Integer) priceInfo.get("totalPrice"));
+        order.setPlatformFee((Integer) priceInfo.get("platformFee"));
         order.setGuideId(guideId);
         order.setStatus("pending");
         order.setPayMethod(dto.getPayMethod());

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/service/ProductOrderService.java

@@ -14,7 +14,6 @@ import com.etotem.cfc.service.CommissionService;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -62,7 +61,7 @@ public class ProductOrderService {
         order.setFamilyId(buyer != null ? buyer.getFamilyId() : null);
         order.setQuantity(dto.getQuantity());
         order.setUnitPrice(product.getPrice());
-        order.setTotalAmount(product.getPrice().multiply(BigDecimal.valueOf(dto.getQuantity())));
+        order.setTotalAmount(product.getPrice() * dto.getQuantity());
         order.setStatus("pending");
         order.setPaymentMethod(dto.getPaymentMethod() != null ? dto.getPaymentMethod() : "wechat");
         order.setRemark(dto.getRemark());

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

@@ -28,6 +28,9 @@ public class ProductService {
     @Resource
     private UserMapper userMapper;
 
+    @Resource
+    private DanshopSyncService danshopSyncService;
+
     public Result<Map<String, Object>> list(ProductListQueryDTO query, Long userId) {
         Page<Product> page = new Page<>(query.getPage(), query.getSize());
         LambdaQueryWrapper<Product> wrapper = new LambdaQueryWrapper<Product>()
@@ -84,6 +87,8 @@ public class ProductService {
         product.setCreatedAt(new Date());
         product.setUpdatedAt(new Date());
         productMapper.insert(product);
+        // 同步到 danshop
+        danshopSyncService.syncProduct(product);
         return Result.success(ProductDTO.from(product));
     }
 
@@ -98,6 +103,8 @@ public class ProductService {
         product.setStatus("pending");
         product.setUpdatedAt(new Date());
         productMapper.updateById(product);
+        // 同步到 danshop
+        danshopSyncService.syncProduct(product);
         return Result.success(ProductDTO.from(productMapper.selectById(product.getId())));
     }
 

+ 13 - 1
cfc-backend/src/main/java/com/etotem/cfc/service/TaskStatsService.java

@@ -119,7 +119,7 @@ public class TaskStatsService {
             .filter(t -> "pending".equals(t.getStatus()) && t.getDeadline() != null && t.getDeadline().before(now))
             .count();
 
-        double rate = total > 0 ? Math.round(completed * 1000.0 / total) / 10.0 : 0;
+        long rate = total > 0 ? Math.round(completed * 1000.0 / total) * 10 : 0;
 
         Map<String, Object> result = new LinkedHashMap<>();
         result.put("totalTasks", total);
@@ -128,6 +128,18 @@ public class TaskStatsService {
         result.put("overdueTasks", overdue);
         result.put("completionRate", rate);
 
+        // 待完成任务列表(含真实标题)
+        List<Map<String, Object>> pendingTaskList = tasks.stream()
+            .filter(t -> "pending".equals(t.getStatus()))
+            .map(t -> {
+                Map<String, Object> item = new HashMap<>();
+                item.put("id", t.getId());
+                item.put("title", t.getTitle() != null ? t.getTitle() : "");
+                return item;
+            })
+            .collect(Collectors.toList());
+        result.put("pendingTaskList", pendingTaskList);
+
         return result;
     }
 }

+ 3 - 7
cfc-backend/src/main/java/com/etotem/cfc/service/TaskTemplatePackageService.java

@@ -13,7 +13,6 @@ import org.springframework.stereotype.Service;
 import javax.annotation.Resource;
 import org.springframework.transaction.annotation.Transactional;
 
-import java.math.BigDecimal;
 import java.util.Date;
 import java.util.List;
 import java.util.UUID;
@@ -27,8 +26,6 @@ public class TaskTemplatePackageService {
     @Resource
     private TaskTemplateItemMapper itemMapper;
 
-    private static final BigDecimal MAX_PLATFORM_FEE_RATE = new BigDecimal("0.10");
-
     /**
      * 创建套餐
      */
@@ -43,9 +40,8 @@ public class TaskTemplatePackageService {
         pkg.setTags(dto.getTags());
         pkg.setPrice(dto.getPrice());
         
-        // 计算平台服务费 (不超过10%)
-        BigDecimal feeRate = new BigDecimal("0.10");
-        pkg.setPlatformFee(dto.getPrice().multiply(feeRate));
+        // 计算平台服务费 (不超过10%, 1000bps)
+        pkg.setPlatformFee(dto.getPrice() * 1000 / 10000);
         
         pkg.setIsPublic(dto.getIsPublic() != null ? dto.getIsPublic() : 0);
         pkg.setCoverImage(dto.getCoverImage());
@@ -72,7 +68,7 @@ public class TaskTemplatePackageService {
         if (dto.getTags() != null) pkg.setTags(dto.getTags());
         if (dto.getPrice() != null) {
             pkg.setPrice(dto.getPrice());
-            pkg.setPlatformFee(dto.getPrice().multiply(new BigDecimal("0.10")));
+            pkg.setPlatformFee(dto.getPrice() * 1000 / 10000);
         }
         if (dto.getIsPublic() != null) pkg.setIsPublic(dto.getIsPublic());
         if (dto.getCoverImage() != null) pkg.setCoverImage(dto.getCoverImage());

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

@@ -70,7 +70,7 @@ public class TeacherService {
         teacher.setSpecialty(dto.getSpecialty());
         teacher.setBio(dto.getBio());
         teacher.setExperienceYears(dto.getExperienceYears());
-        teacher.setRating(java.math.BigDecimal.valueOf(5.00));
+        teacher.setRating(500);
         teacher.setTotalAppointments(0);
         teacher.setStatus("active");
         teacher.setVerificationStatus("pending");

+ 22 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/UserService.java

@@ -43,6 +43,9 @@ private VerificationCodeService verificationCodeService;
 @Resource
 private WechatService wechatService;
 
+@Resource
+private DanshopSyncService danshopSyncService;
+
     public LoginResultDTO wechatLogin(WechatLoginDTO dto) {
         // 模拟微信登录,实际需要调用微信API获取openid
         String openid = "mock_openid_" + dto.getCode();
@@ -89,6 +92,7 @@ private WechatService wechatService;
         result.setFamilyId(user.getFamilyId());
         result.setNickname(user.getNickname());
         populateTeacherFields(result, user);
+        syncToDanshop(result, user);
 
         return result;
     }
@@ -253,6 +257,7 @@ private WechatService wechatService;
         // 新用户需要完善信息(仅当需要选择角色时)
         result.setNeedsRoleSelect(isNewUser);
         populateTeacherFields(result, user);
+        syncToDanshop(result, user);
 
         return result;
     }
@@ -292,6 +297,7 @@ private WechatService wechatService;
         result.setIsNewUser(false);
         result.setOpenid(openid);
         populateTeacherFields(result, user);
+        syncToDanshop(result, user);
 
         return result;
     }
@@ -1185,4 +1191,20 @@ private WechatService wechatService;
         boolean hasTeacher = hasRole(user, "teacher");
         result.setHasTeacherRole(hasTeacher);
     }
+
+    /**
+     * 同步用户到 danshop,设置 danshop token
+     */
+    private void syncToDanshop(LoginResultDTO result, User user) {
+        try {
+            Map<String, String> danshopToken = danshopSyncService.syncMember(user);
+            if (danshopToken != null) {
+                result.setDanshopAccessToken(danshopToken.get("accessToken"));
+                result.setDanshopRefreshToken(danshopToken.get("refreshToken"));
+            }
+        } catch (Exception e) {
+            // Don't fail login if danshop sync fails
+            System.err.println("Danshop sync failed for user " + user.getId() + ": " + e.getMessage());
+        }
+    }
 }

+ 8 - 9
cfc-backend/src/main/java/com/etotem/cfc/service/WithdrawalService.java

@@ -8,13 +8,12 @@ import com.etotem.cfc.mapper.WithdrawalRequestMapper;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
-import java.math.BigDecimal;
 import java.util.Date;
 
 @Service
 public class WithdrawalService {
 
-    private static final BigDecimal MIN_WITHDRAWAL = new BigDecimal("100.00");
+    private static final Integer MIN_WITHDRAWAL = 10000; // 100元 = 10000分
 
     @Resource
     private WithdrawalRequestMapper withdrawalRequestMapper;
@@ -22,19 +21,19 @@ public class WithdrawalService {
     @Resource
     private CommissionService commissionService;
 
-    public Result<String> apply(Long userId, BigDecimal amount, String accountInfo) {
-        if (amount == null || amount.compareTo(BigDecimal.ZERO) <= 0) {
+    public Result<String> apply(Long userId, Integer amount, String accountInfo) {
+        if (amount == null || amount <= 0) {
             return Result.error("提现金额必须大于0");
         }
-        if (amount.compareTo(MIN_WITHDRAWAL) < 0) {
-            return Result.error("最低提现金额为 ¥" + MIN_WITHDRAWAL);
+        if (amount < MIN_WITHDRAWAL) {
+            return Result.error("最低提现金额为 ¥" + String.format("%.2f", MIN_WITHDRAWAL / 100.0));
         }
         if (accountInfo == null || accountInfo.trim().isEmpty()) {
             return Result.error("请填写账户信息");
         }
-        BigDecimal available = commissionService.getAvailableAmount(userId);
-        if (available.compareTo(amount) < 0) {
-            return Result.error("可提现余额不足,当前可提现 ¥" + available);
+        Integer available = commissionService.getAvailableAmount(userId);
+        if (available < amount) {
+            return Result.error("可提现余额不足,当前可提现 ¥" + String.format("%.2f", available / 100.0));
         }
         WithdrawalRequest request = new WithdrawalRequest();
         request.setUserId(userId);

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

@@ -1,7 +1,6 @@
 package com.etotem.cfc.service.api;
 
 import com.etotem.cfc.entity.AssessmentOrder;
-import java.math.BigDecimal;
 import java.util.List;
 
 public interface AssessmentOrderServiceInterface {

+ 1 - 2
cfc-backend/src/main/java/com/etotem/cfc/service/api/BindInviteServiceInterface.java

@@ -1,10 +1,9 @@
 package com.etotem.cfc.service.api;
 
-import java.math.BigDecimal;
 import java.util.Map;
 
 public interface BindInviteServiceInterface {
     Map<String, Object> generateInvite(Long guideId);
-    boolean confirmBind(String inviteToken, Long guideId, Long familyId, String serviceType, BigDecimal servicePrice);
+    boolean confirmBind(String inviteToken, Long guideId, Long familyId, String serviceType, Integer servicePrice);
     Map<String, Object> validateToken(String inviteToken);
 }

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/api/GuidePackageServiceInterface.java

@@ -1,13 +1,12 @@
 package com.etotem.cfc.service.api;
 
 import com.etotem.cfc.entity.GuidePackage;
-import java.math.BigDecimal;
 import java.util.List;
 
 public interface GuidePackageServiceInterface {
-    boolean addGuidePackage(Long guideId, Long packageId, BigDecimal price, BigDecimal commissionRate);
+    boolean addGuidePackage(Long guideId, Long packageId, Integer price, Integer commissionRate);
     List<GuidePackage> getGuidePackages(Long guideId);
     GuidePackage getGuidePackage(Long guideId, Long packageId);
-    boolean updateGuidePackagePrice(Long guideId, Long packageId, BigDecimal price);
+    boolean updateGuidePackagePrice(Long guideId, Long packageId, Integer price);
     boolean deleteGuidePackage(Long guideId, Long packageId);
 }

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

@@ -1,7 +1,6 @@
 package com.etotem.cfc.service.api;
 
 import com.etotem.cfc.entity.GuidePackageTemplate;
-import java.math.BigDecimal;
 import java.util.List;
 
 public interface GuidePackageTemplateServiceInterface {

+ 2 - 3
cfc-backend/src/main/java/com/etotem/cfc/service/api/MembershipServiceInterface.java

@@ -4,7 +4,6 @@ import com.etotem.cfc.dto.FamilyMembershipDTO;
 import com.etotem.cfc.dto.MembershipLevelDTO;
 import com.etotem.cfc.dto.PaymentOrderDTO;
 
-import java.math.BigDecimal;
 import java.util.List;
 
 public interface MembershipServiceInterface {
@@ -28,6 +27,6 @@ public interface MembershipServiceInterface {
     /** 获取当前有效会员等级 */
     String getMemberLevel(Long userId);
 
-    /** 应用会员折扣 */
-    BigDecimal applyMemberDiscount(Long userId, BigDecimal originalPrice);
+    /** 应用会员折扣,返回折后价格(分) */
+    Integer applyMemberDiscount(Long userId, Integer originalPrice);
 }

+ 5 - 0
cfc-backend/src/main/resources/application.yml

@@ -75,3 +75,8 @@ dify:
 logging:
   level:
     com.etotem.cfc: debug
+
+# Danshop 商城系统配置
+danshop:
+  base-url: http://localhost:8888
+  api-url: http://localhost:8888/api/internal

+ 2 - 2
cfc-backend/src/main/resources/schema_assessment.sql

@@ -17,7 +17,7 @@ CREATE TABLE IF NOT EXISTS assessment_materials (
 CREATE TABLE IF NOT EXISTS assessment_points_config (
     id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
     points_value INT DEFAULT 100 COMMENT '完成测评获得积分',
-    points_value_yuan DECIMAL(10,2) DEFAULT 0.01 COMMENT '1积分等于多少元',
+    points_value_yuan INT DEFAULT 1 COMMENT '1积分等于多少分(原元→现分)',
     is_active TINYINT DEFAULT 1 COMMENT '是否启用',
     created_at DATETIME COMMENT '创建时间',
     updated_at DATETIME COMMENT '更新时间'
@@ -25,7 +25,7 @@ CREATE TABLE IF NOT EXISTS assessment_points_config (
 
 -- 初始化默认积分配置
 INSERT INTO assessment_points_config (points_value, points_value_yuan, is_active, created_at, updated_at)
-VALUES (100, 0.01, 1, NOW(), NOW());
+VALUES (100, 1, 1, NOW(), NOW());
 
 -- 3. 家庭测评配置表
 CREATE TABLE IF NOT EXISTS family_assessment_config (

+ 15 - 15
cfc-backend/src/main/resources/schema_guide.sql

@@ -13,7 +13,7 @@ CREATE TABLE IF NOT EXISTS `guide_applications` (
     `current_level` VARCHAR(20) DEFAULT NULL COMMENT '当前等级(升级时填写)',
     `package_id` BIGINT COMMENT '申请的套餐ID',
     `payment_proof` VARCHAR(500) COMMENT '付款凭证URL',
-    `payment_amount` DECIMAL(10,2) COMMENT '付款金额',
+    `payment_amount` INT COMMENT '付款金额(分)',
     `status` VARCHAR(20) NOT NULL DEFAULT 'pending' COMMENT '状态: pending-待审核, approved-已通过, rejected-已拒绝',
     `reject_reason` VARCHAR(500) COMMENT '拒绝原因',
     `reviewed_at` DATETIME COMMENT '审核时间',
@@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS `guides` (
     `phone` VARCHAR(20) COMMENT '联系电话',
     `intro` TEXT COMMENT '个人介绍',
     `avatar` VARCHAR(500) COMMENT '头像URL',
-    `commission_rate` DECIMAL(5,4) DEFAULT 0.1000 COMMENT '佣金比例',
+    `commission_rate` INT DEFAULT 1000 COMMENT '佣金比例(基点,1000=10%)',
     `approved_at` DATETIME COMMENT '审核通过时间',
     `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
     `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
@@ -53,7 +53,7 @@ CREATE TABLE IF NOT EXISTS `upgrade_services` (
     `to_level` VARCHAR(20) NOT NULL COMMENT '目标等级: junior, intermediate, senior',
     `name` VARCHAR(100) NOT NULL COMMENT '服务名称',
     `description` TEXT COMMENT '描述',
-    `price` DECIMAL(10,2) NOT NULL COMMENT '价格',
+    `price` INT NOT NULL COMMENT '价格(分)',
     `service_months` INT DEFAULT 12 COMMENT '服务期限(月)',
     `service_limit_add` INT DEFAULT 0 COMMENT '额外增加的服务名额',
     `is_active` TINYINT DEFAULT 1 COMMENT '是否上架: 0-否, 1-是',
@@ -70,8 +70,8 @@ CREATE TABLE IF NOT EXISTS `guide_package_templates` (
     `id` BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '主键ID',
     `name` VARCHAR(100) NOT NULL COMMENT '套餐名称',
     `level` VARCHAR(20) NOT NULL COMMENT '等级: junior, intermediate, senior',
-    `price` DECIMAL(10,2) NOT NULL COMMENT '价格',
-    `min_price` DECIMAL(10,2) COMMENT '最低价',
+    `price` INT NOT NULL COMMENT '价格(分)',
+    `min_price` INT COMMENT '最低价(分)',
     `description` TEXT COMMENT '套餐描述',
     `service_months` INT DEFAULT 12 COMMENT '服务期限(月)',
     `service_limit` INT DEFAULT 50 COMMENT '服务名额限制',
@@ -90,7 +90,7 @@ CREATE TABLE IF NOT EXISTS `guide_family_relations` (
     `guide_id` BIGINT NOT NULL COMMENT '规划师ID',
     `family_id` BIGINT NOT NULL COMMENT '家庭ID',
     `service_type` VARCHAR(50) DEFAULT 'basic' COMMENT '服务类型: basic-基础, premium-高级',
-    `service_price` DECIMAL(10,2) DEFAULT 0.00 COMMENT '服务价格',
+    `service_price` INT DEFAULT 0 COMMENT '服务价格(分)',
     `status` VARCHAR(20) DEFAULT 'active' COMMENT '状态: active-服务中, paused-已暂停',
     `bound_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '绑定时间',
     `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@@ -134,8 +134,8 @@ CREATE TABLE IF NOT EXISTS `guide_packages` (
   `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID',
   `guide_id` BIGINT NOT NULL COMMENT '成长规划师ID',
   `package_id` BIGINT NOT NULL COMMENT '套餐ID',
-  `price` DECIMAL(10,2) NOT NULL COMMENT '成长规划师定价',
-  `commission_rate` DECIMAL(5,2) NOT NULL DEFAULT 0.00 COMMENT '上级佣金比例(%)',
+  `price` INT NOT NULL COMMENT '成长规划师定价(分)',
+  `commission_rate` INT NOT NULL DEFAULT 0 COMMENT '上级佣金比例(基点)',
   `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态:1-上架,0-下架',
   `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
   `update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
@@ -153,7 +153,7 @@ CREATE TABLE IF NOT EXISTS `orders` (
   `guide_id` BIGINT COMMENT '成长规划师ID',
   `package_id` BIGINT NOT NULL COMMENT '套餐ID',
   `package_name` VARCHAR(100) NOT NULL COMMENT '套餐名称',
-  `amount` DECIMAL(10,2) NOT NULL COMMENT '订单金额',
+  `amount` INT NOT NULL COMMENT '订单金额(分)',
   `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0-待支付,1-已支付,2-已取消,3-已退款',
   `payment_method` VARCHAR(20) COMMENT '支付方式:wechat-微信支付,alipay-支付宝',
   `payment_time` DATETIME COMMENT '支付时间',
@@ -172,7 +172,7 @@ CREATE TABLE IF NOT EXISTS `payment_records` (
   `order_no` VARCHAR(32) NOT NULL COMMENT '订单号',
   `transaction_id` VARCHAR(64) COMMENT '第三方交易号',
   `payment_method` VARCHAR(20) NOT NULL COMMENT '支付方式:wechat-微信支付,alipay-支付宝',
-  `amount` DECIMAL(10,2) NOT NULL COMMENT '支付金额',
+  `amount` INT NOT NULL COMMENT '支付金额(分)',
   `status` TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0-待支付,1-支付成功,2-支付失败',
   `notify_time` DATETIME COMMENT '回调时间',
   `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@@ -215,11 +215,11 @@ CREATE TABLE IF NOT EXISTS `assessment_results` (
   `assessment_date` DATE NOT NULL COMMENT '测评日期',
   `duration_minutes` INT COMMENT '测评时长(分钟)',
   `dan_level` VARCHAR(20) COMMENT 'DAN等级',
-  `attention_score` DECIMAL(5,2) COMMENT '注意力得分',
-  `focus_score` DECIMAL(5,2) COMMENT '专注力得分',
-  `memory_score` DECIMAL(5,2) COMMENT '记忆力得分',
-  `logic_score` DECIMAL(5,2) COMMENT '逻辑思维得分',
-  `overall_score` DECIMAL(5,2) COMMENT '综合得分',
+  `attention_score` INT COMMENT '注意力得分',
+  `focus_score` INT COMMENT '专注力得分',
+  `memory_score` INT COMMENT '记忆力得分',
+  `logic_score` INT COMMENT '逻辑思维得分',
+  `overall_score` INT COMMENT '综合得分',
   `analysis_report` TEXT COMMENT '分析报告',
   `growth_suggestions` TEXT COMMENT '成长建议',
   `next_review_date` DATE COMMENT '下次复测日期',

Неке датотеке нису приказане због велике количине промена