Просмотр исходного кода

将项目从xzyj重命名为zxyj,更新所有包名和配置,修复selectSum编译错误

User 7 месяцев назад
Родитель
Сommit
7961539a32
94 измененных файлов с 281 добавлено и 2909 удалено
  1. 0 89
      backend/pom.xml
  2. 0 18
      backend/src/main/java/com/zhixingyijia/ZhixingyijiaApplication.java
  3. 0 77
      backend/src/main/java/com/zhixingyijia/common/JwtUtil.java
  4. 0 54
      backend/src/main/java/com/zhixingyijia/common/Result.java
  5. 0 33
      backend/src/main/java/com/zhixingyijia/common/ResultCode.java
  6. 0 55
      backend/src/main/java/com/zhixingyijia/controller/AuthController.java
  7. 0 41
      backend/src/main/java/com/zhixingyijia/controller/PointsController.java
  8. 0 54
      backend/src/main/java/com/zhixingyijia/controller/RewardController.java
  9. 0 69
      backend/src/main/java/com/zhixingyijia/controller/TaskController.java
  10. 0 57
      backend/src/main/java/com/zhixingyijia/entity/Child.java
  11. 0 29
      backend/src/main/java/com/zhixingyijia/entity/Family.java
  12. 0 32
      backend/src/main/java/com/zhixingyijia/entity/PointsLog.java
  13. 0 50
      backend/src/main/java/com/zhixingyijia/entity/Reward.java
  14. 0 38
      backend/src/main/java/com/zhixingyijia/entity/RewardExchange.java
  15. 0 83
      backend/src/main/java/com/zhixingyijia/entity/Task.java
  16. 0 41
      backend/src/main/java/com/zhixingyijia/entity/User.java
  17. 0 23
      backend/src/main/java/com/zhixingyijia/mapper/ChildMapper.java
  18. 0 20
      backend/src/main/java/com/zhixingyijia/mapper/PointsLogMapper.java
  19. 0 24
      backend/src/main/java/com/zhixingyijia/mapper/RewardMapper.java
  20. 0 30
      backend/src/main/java/com/zhixingyijia/mapper/TaskMapper.java
  21. 0 21
      backend/src/main/java/com/zhixingyijia/mapper/UserMapper.java
  22. 0 44
      backend/src/main/java/com/zhixingyijia/service/PointsService.java
  23. 0 55
      backend/src/main/java/com/zhixingyijia/service/RewardService.java
  24. 0 152
      backend/src/main/java/com/zhixingyijia/service/TaskService.java
  25. 0 55
      backend/src/main/java/com/zhixingyijia/service/UserService.java
  26. 0 31
      backend/src/main/resources/application.yml
  27. 0 55
      backend/src/main/resources/mapper/ChildMapper.xml
  28. 0 34
      backend/src/main/resources/mapper/PointsLogMapper.xml
  29. 0 57
      backend/src/main/resources/mapper/RewardMapper.xml
  30. 0 86
      backend/src/main/resources/mapper/TaskMapper.xml
  31. 0 42
      backend/src/main/resources/mapper/UserMapper.xml
  32. 0 140
      backend/src/main/resources/sql/init.sql
  33. 0 34
      backend/src/main/resources/sql/seed.sql
  34. 0 90
      backend/src/test/java/com/zhixingyijia/common/JwtUtilTest.java
  35. 0 80
      backend/src/test/java/com/zhixingyijia/common/ResultTest.java
  36. 0 160
      backend/src/test/java/com/zhixingyijia/common/SqlValidationTest.java
  37. 0 151
      backend/src/test/java/com/zhixingyijia/integration/ApiContractTest.java
  38. 0 229
      backend/src/test/java/com/zhixingyijia/service/TaskServiceTest.java
  39. 0 163
      backend/src/test/java/com/zhixingyijia/service/UserServiceTest.java
  40. 0 28
      backend/src/test/resources/test-schema.sql
  41. 0 62
      backend/src/test/resources/validate-sql.sh
  42. 2 2
      zxyj-backend/sql/init.sql
  43. 0 1
      zxyj-backend/src/main/java/com/zxyj/ZxyjApplication.java
  44. 0 1
      zxyj-backend/src/main/java/com/zxyj/common/Result.java
  45. 74 52
      zxyj-backend/src/main/java/com/zxyj/config/DatabaseInitializer.java
  46. 0 1
      zxyj-backend/src/main/java/com/zxyj/config/JwtConfig.java
  47. 3 3
      zxyj-backend/src/main/java/com/zxyj/config/JwtInterceptor.java
  48. 0 1
      zxyj-backend/src/main/java/com/zxyj/config/MyBatisPlusConfig.java
  49. 0 1
      zxyj-backend/src/main/java/com/zxyj/config/WebConfig.java
  50. 25 16
      zxyj-backend/src/main/java/com/zxyj/controller/AdminAuthController.java
  51. 5 5
      zxyj-backend/src/main/java/com/zxyj/controller/AdminController.java
  52. 13 9
      zxyj-backend/src/main/java/com/zxyj/controller/AuthController.java
  53. 0 1
      zxyj-backend/src/main/java/com/zxyj/controller/PointsController.java
  54. 0 1
      zxyj-backend/src/main/java/com/zxyj/controller/RewardController.java
  55. 0 1
      zxyj-backend/src/main/java/com/zxyj/controller/TaskController.java
  56. 0 1
      zxyj-backend/src/main/java/com/zxyj/controller/UserController.java
  57. 0 1
      zxyj-backend/src/main/java/com/zxyj/dto/AdminLoginDTO.java
  58. 0 31
      zxyj-backend/src/main/java/com/zxyj/dto/AuthDTO.java
  59. 0 17
      zxyj-backend/src/main/java/com/zxyj/dto/ChildInfoDTO.java
  60. 9 0
      zxyj-backend/src/main/java/com/zxyj/dto/CompleteTaskDTO.java
  61. 10 0
      zxyj-backend/src/main/java/com/zxyj/dto/CreateChildDTO.java
  62. 11 0
      zxyj-backend/src/main/java/com/zxyj/dto/CreateRewardDTO.java
  63. 0 14
      zxyj-backend/src/main/java/com/zxyj/dto/CreateTaskDTO.java
  64. 12 0
      zxyj-backend/src/main/java/com/zxyj/dto/LoginResultDTO.java
  65. 0 1
      zxyj-backend/src/main/java/com/zxyj/dto/PhoneLoginDTO.java
  66. 0 9
      zxyj-backend/src/main/java/com/zxyj/dto/RewardDTO.java
  67. 0 1
      zxyj-backend/src/main/java/com/zxyj/dto/SendCodeDTO.java
  68. 8 0
      zxyj-backend/src/main/java/com/zxyj/dto/SetPasswordDTO.java
  69. 12 0
      zxyj-backend/src/main/java/com/zxyj/dto/TaskReviewDTO.java
  70. 12 0
      zxyj-backend/src/main/java/com/zxyj/dto/UpdateChildDTO.java
  71. 8 0
      zxyj-backend/src/main/java/com/zxyj/dto/VerifyPasswordDTO.java
  72. 11 0
      zxyj-backend/src/main/java/com/zxyj/dto/WechatLoginDTO.java
  73. 0 1
      zxyj-backend/src/main/java/com/zxyj/dto/WechatPhoneLoginDTO.java
  74. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/Admin.java
  75. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/Child.java
  76. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/Family.java
  77. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/PointsLog.java
  78. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/Reward.java
  79. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/Task.java
  80. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/User.java
  81. 0 1
      zxyj-backend/src/main/java/com/zxyj/entity/VerificationCode.java
  82. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/AdminMapper.java
  83. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/ChildMapper.java
  84. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/FamilyMapper.java
  85. 7 2
      zxyj-backend/src/main/java/com/zxyj/mapper/PointsLogMapper.java
  86. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/RewardMapper.java
  87. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/TaskMapper.java
  88. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/UserMapper.java
  89. 0 1
      zxyj-backend/src/main/java/com/zxyj/mapper/VerificationCodeMapper.java
  90. 4 3
      zxyj-backend/src/main/java/com/zxyj/service/PointsService.java
  91. 12 6
      zxyj-backend/src/main/java/com/zxyj/service/RewardService.java
  92. 20 11
      zxyj-backend/src/main/java/com/zxyj/service/TaskService.java
  93. 7 5
      zxyj-backend/src/main/java/com/zxyj/service/UserService.java
  94. 16 10
      zxyj-backend/src/main/java/com/zxyj/service/VerificationCodeService.java

+ 0 - 89
backend/pom.xml

@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
-         http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.springframework.boot</groupId>
-        <artifactId>spring-boot-starter-parent</artifactId>
-        <version>2.7.18</version>
-        <relativePath/>
-    </parent>
-
-    <groupId>com.zhixingyijia</groupId>
-    <artifactId>zhixingyijia-backend</artifactId>
-    <version>1.0.0</version>
-    <packaging>jar</packaging>
-
-    <name>zhixingyijia-backend</name>
-    <description>知行益家小程序后端</description>
-
-    <properties>
-        <java.version>1.8</java.version>
-        <mybatis.version>2.3.2</mybatis.version>
-    </properties>
-
-    <dependencies>
-        <!-- Spring Boot Web -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <!-- MyBatis -->
-        <dependency>
-            <groupId>org.mybatis.spring.boot</groupId>
-            <artifactId>mybatis-spring-boot-starter</artifactId>
-            <version>${mybatis.version}</version>
-        </dependency>
-
-        <!-- MySQL -->
-        <dependency>
-            <groupId>mysql</groupId>
-            <artifactId>mysql-connector-java</artifactId>
-            <scope>runtime</scope>
-        </dependency>
-
-        <!-- Swagger -->
-        <dependency>
-            <groupId>org.springdoc</groupId>
-            <artifactId>springdoc-openapi-ui</artifactId>
-            <version>1.7.0</version>
-        </dependency>
-
-        <!-- JWT -->
-        <dependency>
-            <groupId>io.jsonwebtoken</groupId>
-            <artifactId>jjwt</artifactId>
-            <version>0.9.1</version>
-        </dependency>
-
-        <!-- Lombok -->
-        <dependency>
-            <groupId>org.projectlombok</groupId>
-            <artifactId>lombok</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- Test -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <configuration>
-                    <mainClass>com.zhixingyijia.ZhixingyijiaApplication</mainClass>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>

+ 0 - 18
backend/src/main/java/com/zhixingyijia/ZhixingyijiaApplication.java

@@ -1,18 +0,0 @@
-package com.zhixingyijia;
-
-import org.mybatis.spring.annotation.MapperScan;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-/**
- * 知行益家小程序启动类
- */
-@SpringBootApplication
-@MapperScan("com.zhixingyijia.mapper")
-public class XinzhiyijiaApplication {
-
-    public static void main(String[] args) {
-        SpringApplication.run(XinzhiyijiaApplication.class, args);
-    }
-}
-

+ 0 - 77
backend/src/main/java/com/zhixingyijia/common/JwtUtil.java

@@ -1,77 +0,0 @@
-package com.zhixingyijia.common;
-
-import io.jsonwebtoken.*;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import java.util.Date;
-
-/**
- * JWT工具� */
-@Component
-public class JwtUtil {
-
-    @Value("${jwt.secret}")
-    private String secret;
-
-    @Value("${jwt.expiration}")
-    private Long expiration;
-
-    /**
-     * 生�JWT Token
-     */
-    public String generateToken(Long userId, String role) {
-        return Jwts.builder()
-                .setSubject(String.valueOf(userId))
-                .claim("role", role)
-                .setIssuedAt(new Date())
-                .setExpiration(new Date(System.currentTimeMillis() + expiration))
-                .signWith(SignatureAlgorithm.HS256, secret)
-                .compact();
-    }
-
-    /**
-     * 解�Token
-     */
-    public Claims parseToken(String token) {
-        try {
-            return Jwts.parser()
-                    .setSigningKey(secret)
-                    .parseClaimsJws(token)
-                    .getBody();
-        } catch (ExpiredJwtException e) {
-            throw new RuntimeException("Token已过�);
-        } catch (Exception e) {
-            throw new RuntimeException("Token无效");
-        }
-    }
-
-    /**
-     * 从Token获�用户ID
-     */
-    public Long getUserIdFromToken(String token) {
-        Claims claims = parseToken(token);
-        return Long.parseLong(claims.getSubject());
-    }
-
-    /**
-     * 从Token获�角色
-     */
-    public String getRoleFromToken(String token) {
-        Claims claims = parseToken(token);
-        return claims.get("role", String.class);
-    }
-
-    /**
-     * 验�Token是�有效
-     */
-    public boolean isTokenValid(String token) {
-        try {
-            parseToken(token);
-            return true;
-        } catch (Exception e) {
-            return false;
-        }
-    }
-}
-

+ 0 - 54
backend/src/main/java/com/zhixingyijia/common/Result.java

@@ -1,54 +0,0 @@
-package com.zhixingyijia.common;
-
-import lombok.Data;
-
-/**
- * 统一�应结果�装
- */
-@Data
-public class Result<T> {
-    
-    private int code;
-    private String message;
-    private T data;
-
-    public static <T> Result<T> success() {
-        return success(null);
-    }
-
-    public static <T> Result<T> success(T data) {
-        Result<T> result = new Result<>();
-        result.setCode(200);
-        result.setMessage("success");
-        result.setData(data);
-        return result;
-    }
-
-    public static <T> Result<T> success(String message, T data) {
-        Result<T> result = new Result<>();
-        result.setCode(200);
-        result.setMessage(message);
-        result.setData(data);
-        return result;
-    }
-
-    public static <T> Result<T> error(int code, String message) {
-        Result<T> result = new Result<>();
-        result.setCode(code);
-        result.setMessage(message);
-        return result;
-    }
-
-    public static <T> Result<T> error(String message) {
-        return error(500, message);
-    }
-
-    public static <T> Result<T> unauthorized() {
-        return error(401, "未授�);
-    }
-
-    public static <T> Result<T> notFound(String message) {
-        return error(404, message != null ? message : "资��存�);
-    }
-}
-

+ 0 - 33
backend/src/main/java/com/zhixingyijia/common/ResultCode.java

@@ -1,33 +0,0 @@
-package com.zhixingyijia.common;
-
-import lombok.Getter;
-
-/**
- * �应状��枚举
- */
-@Getter
-public enum ResultCode {
-    
-    SUCCESS(200, "�功"),
-    BAD_REQUEST(400, "请求�数错误"),
-    UNAUTHORIZED(401, "未授�),
-    FORBIDDEN(403, "�止访问"),
-    NOT_FOUND(404, "资��存�),
-    INTERNAL_ERROR(500, "�务器内部错�),
-    
-    // 业务错误�1000+
-    TASK_NOT_FOUND(1001, "任务�存�),
-    TASK_ALREADY_COMPLETED(1002, "任务已完�),
-    INSUFFICIENT_POINTS(1003, "积分�足"),
-    REWARD_NOT_AVAILABLE(1004, "奖励���),
-    PENALTY_DISABLED(1005, "扣分功能已关�);
-
-    private final int code;
-    private final String message;
-
-    ResultCode(int code, String message) {
-        this.code = code;
-        this.message = message;
-    }
-}
-

+ 0 - 55
backend/src/main/java/com/zhixingyijia/controller/AuthController.java

@@ -1,55 +0,0 @@
-package com.zhixingyijia.controller;
-
-import com.zhixingyijia.common.Result;
-import com.zhixingyijia.entity.User;
-import com.zhixingyijia.service.UserService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * 霈方��批��? */
-@Tag(name = "霈方��亙藁")
-@RestController
-@RequestMapping("/auth")
-public class AuthController {
-
-    @Autowired
-    private UserService userService;
-
-    @Operation(summary = "敺桐縑�餃�")
-    @PostMapping("/login")
-    public Result<Map<String, Object>> login(@RequestBody Map<String, String> params) {
-        String code = params.get("code");
-        // TODO: �朞�code靚�鍂敺桐縑�亙藁�瑕�openid
-        
-        // 璅⊥��餃�
-        User user = new User();
-        user.setOpenid("mock_openid_" + System.currentTimeMillis());
-        user.setRole(params.getOrDefault("role", "parent"));
-        user.setNickname(params.getOrDefault("nickname", "�冽�"));
-
-        String token = userService.login(user);
-
-        Map<String, Object> data = new HashMap<>();
-        data.put("token", token);
-        data.put("userId", user.getId());
-        data.put("role", user.getRole());
-        
-        return Result.success(data);
-    }
-
-    @Operation(summary = "�瑕��冽�靽⊥�")
-    @GetMapping("/info")
-    public Result<User> getUserInfo(@RequestHeader("Authorization") String token) {
-        // TODO: 隞𤢂oken銝剛圾�鞟鍂�弒D
-        Long userId = 1L; // mock
-        User user = userService.findById(userId);
-        return Result.success(user);
-    }
-}
-

+ 0 - 41
backend/src/main/java/com/zhixingyijia/controller/PointsController.java

@@ -1,41 +0,0 @@
-package com.zhixingyijia.controller;
-
-import com.zhixingyijia.common.Result;
-import com.zhixingyijia.entity.PointsLog;
-import com.zhixingyijia.service.PointsService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * 积分控制� */
-@Tag(name = "积分接�")
-@RestController
-@RequestMapping("/points")
-public class PointsController {
-
-    @Autowired
-    private PointsService pointsService;
-
-    @Operation(summary = "获�孩�积分")
-    @GetMapping("/balance/{childId}")
-    public Result<Map<String, Object>> getPointsBalance(@PathVariable Long childId) {
-        int points = pointsService.getChildPoints(childId);
-        Map<String, Object> data = new HashMap<>();
-        data.put("childId", childId);
-        data.put("points", points);
-        return Result.success(data);
-    }
-
-    @Operation(summary = "获�积分�水")
-    @GetMapping("/log/{childId}")
-    public Result<List<PointsLog>> getPointsLog(@PathVariable Long childId) {
-        return Result.success(pointsService.getPointsLog(childId));
-    }
-}
-

+ 0 - 54
backend/src/main/java/com/zhixingyijia/controller/RewardController.java

@@ -1,54 +0,0 @@
-package com.zhixingyijia.controller;
-
-import com.zhixingyijia.common.Result;
-import com.zhixingyijia.entity.Reward;
-import com.zhixingyijia.service.RewardService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-
-/**
- * 奖励控制� */
-@Tag(name = "奖励接�")
-@RestController
-@RequestMapping("/rewards")
-public class RewardController {
-
-    @Autowired
-    private RewardService rewardService;
-
-    @Operation(summary = "获�家庭奖励列表")
-    @GetMapping("/family/{familyId}")
-    public Result<List<Reward>> getFamilyRewards(@PathVariable Long familyId) {
-        return Result.success(rewardService.getFamilyRewards(familyId));
-    }
-
-    @Operation(summary = "获�奖励详情")
-    @GetMapping("/{rewardId}")
-    public Result<Reward> getRewardDetail(@PathVariable Long rewardId) {
-        return Result.success(rewardService.findById(rewardId));
-    }
-
-    @Operation(summary = "创建奖励")
-    @PostMapping
-    public Result<Reward> createReward(@RequestBody Reward reward) {
-        return Result.success(rewardService.createReward(reward));
-    }
-
-    @Operation(summary = "更新奖励")
-    @PutMapping("/{rewardId}")
-    public Result<Reward> updateReward(@PathVariable Long rewardId, @RequestBody Reward reward) {
-        reward.setId(rewardId);
-        return Result.success(rewardService.updateReward(reward));
-    }
-
-    @Operation(summary = "获�系统预设奖励")
-    @GetMapping("/defaults")
-    public Result<List<Reward>> getDefaultRewards() {
-        return Result.success(rewardService.getDefaultRewards());
-    }
-}
-

+ 0 - 69
backend/src/main/java/com/zhixingyijia/controller/TaskController.java

@@ -1,69 +0,0 @@
-package com.zhixingyijia.controller;
-
-import com.zhixingyijia.common.Result;
-import com.zhixingyijia.entity.Task;
-import com.zhixingyijia.service.TaskService;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * 任务控制� */
-@Tag(name = "任务接�")
-@RestController
-@RequestMapping("/tasks")
-public class TaskController {
-
-    @Autowired
-    private TaskService taskService;
-
-    @Operation(summary = "获�今日任务")
-    @GetMapping("/today/{childId}")
-    public Result<List<Task>> getTodayTasks(@PathVariable Long childId) {
-        return Result.success(taskService.getTodayTasks(childId));
-    }
-
-    @Operation(summary = "获�任务详情")
-    @GetMapping("/{taskId}")
-    public Result<Task> getTaskDetail(@PathVariable Long taskId) {
-        return Result.success(taskService.findById(taskId));
-    }
-
-    @Operation(summary = "创建任务")
-    @PostMapping
-    public Result<Task> createTask(@RequestBody Task task) {
-        return Result.success(taskService.createTask(task));
-    }
-
-    @Operation(summary = "完�任务")
-    @PostMapping("/{taskId}/complete")
-    public Result<Task> completeTask(
-            @PathVariable Long taskId,
-            @RequestBody(required = false) Map<String, String> params) {
-        String photoUrl = params != null ? params.get("photoUrl") : null;
-        String voiceUrl = params != null ? params.get("voiceUrl") : null;
-        return Result.success(taskService.completeTask(taskId, photoUrl, voiceUrl));
-    }
-
-    @Operation(summary = "审核任务")
-    @PostMapping("/{taskId}/review")
-    public Result<Task> reviewTask(
-            @PathVariable Long taskId,
-            @RequestBody Map<String, String> params) {
-        String result = params.get("result");
-        String comment = params.get("comment");
-        Long reviewerId = Long.parseLong(params.get("reviewerId"));
-        return Result.success(taskService.reviewTask(taskId, result, comment, reviewerId));
-    }
-
-    @Operation(summary = "获�家庭任务列表")
-    @GetMapping("/family/{familyId}")
-    public Result<List<Task>> getFamilyTasks(@PathVariable Long familyId) {
-        return Result.success(taskService.getFamilyTasks(familyId));
-    }
-}
-

+ 0 - 57
backend/src/main/java/com/zhixingyijia/entity/Child.java

@@ -1,57 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-
-/**
- * 孩�信�实体� */
-@Data
-public class Child {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** 关�用户ID */
-    private Long userId;
-    
-    /** 所属家庭ID */
-    private Long familyId;
-    
-    /** 年龄 */
-    private Integer age;
-    
-    /** 年级 */
-    private String grade;
-    
-    /** DAN测评等级 */
-    private String danLevel;
-    
-    /** 是�开�扣分(6�以下默认关闭) */
-    private Boolean penaltyEnabled;
-    
-    /** 当�连续打�天数 */
-    private Integer currentStreak;
-    
-    /** 历�最长连续天�*/
-    private Integer maxStreak;
-    
-    /** 最�打�日�*/
-    private LocalDateTime lastCheckInDate;
-    
-    /** 当�积分 */
-    private Integer totalPoints;
-    
-    /** 累计获得积分 */
-    private Integer totalEarned;
-    
-    /** 主题 */
-    private String theme;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-    
-    /** æ›´æ–°æ—¶é—´ */
-    private LocalDateTime updatedAt;
-}
-

+ 0 - 29
backend/src/main/java/com/zhixingyijia/entity/Family.java

@@ -1,29 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDateTime;
-
-/**
- * 家庭实体� */
-@Data
-public class Family {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** 家庭�称 */
-    private String name;
-    
-    /** 邀请� */
-    private String inviteCode;
-    
-    /** 创建者ID */
-    private Long creatorId;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-    
-    /** æ›´æ–°æ—¶é—´ */
-    private LocalDateTime updatedAt;
-}
-

+ 0 - 32
backend/src/main/java/com/zhixingyijia/entity/PointsLog.java

@@ -1,32 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDateTime;
-
-/**
- * 积分�水实体� */
-@Data
-public class PointsLog {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** å­©å­�ID */
-    private Long childId;
-    
-    /** 关�任务ID */
-    private Long taskId;
-    
-    /** 积分数(正数为获得,负数为扣除) */
-    private Integer amount;
-    
-    /** 类型:task-任务/early-��/streak-打�/focus-专注/reward-兑�/correction-修正 */
-    private String type;
-    
-    /** �述 */
-    private String description;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-}
-

+ 0 - 50
backend/src/main/java/com/zhixingyijia/entity/Reward.java

@@ -1,50 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDateTime;
-
-/**
- * 奖励实体� */
-@Data
-public class Reward {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** 所属家庭ID */
-    private Long familyId;
-    
-    /** 指定孩�ID(NULL表示全员�用�*/
-    private Long childId;
-    
-    /** 分类ID */
-    private Long categoryId;
-    
-    /** 奖励�称 */
-    private String name;
-    
-    /** 奖励�述 */
-    private String description;
-    
-    /** 所需积分 */
-    private Integer pointsRequired;
-    
-    /** 图标 */
-    private String icon;
-    
-    /** 库存�1表示无��*/
-    private Integer stock;
-    
-    /** 状�:active-�用/inactive-���*/
-    private String status;
-    
-    /** 是�系统预设 */
-    private Boolean isDefault;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-    
-    /** æ›´æ–°æ—¶é—´ */
-    private LocalDateTime updatedAt;
-}
-

+ 0 - 38
backend/src/main/java/com/zhixingyijia/entity/RewardExchange.java

@@ -1,38 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDateTime;
-
-/**
- * 奖励兑�实体� */
-@Data
-public class RewardExchange {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** 奖励ID */
-    private Long rewardId;
-    
-    /** å­©å­�ID */
-    private Long childId;
-    
-    /** 消耗积�*/
-    private Integer pointsUsed;
-    
-    /** 状�:pending-待审�approved-通过/rejected-拒� */
-    private String status;
-    
-    /** 审核备注 */
-    private String reviewComment;
-    
-    /** 审核人ID */
-    private Long reviewedBy;
-    
-    /** 审核时间 */
-    private LocalDateTime reviewedAt;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-}
-

+ 0 - 83
backend/src/main/java/com/zhixingyijia/entity/Task.java

@@ -1,83 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDateTime;
-
-/**
- * 任务实体� */
-@Data
-public class Task {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** 所属家庭ID */
-    private Long familyId;
-    
-    /** 创建者(家长)ID */
-    private Long creatorId;
-    
-    /** 执行孩�ID */
-    private Long childId;
-    
-    /** 任务�称 */
-    private String title;
-    
-    /** 备注说明 */
-    private String description;
-    
-    /** 积分数(1-10�*/
-    private Integer points;
-    
-    /** 分类:学�生活/�动/其他 */
-    private String category;
-    
-    /** 优先级:high/medium/low */
-    private String priority;
-    
-    /** 截止时间 */
-    private LocalDateTime deadline;
-    
-    /** 预计时长(分钟) */
-    private Integer estimatedDuration;
-    
-    /** ��类型:none/daily/weekly */
-    private String repeatType;
-    
-    /** 是�需�审�*/
-    private Boolean needReview;
-    
-    /** 状�:pending/completed/approved/rejected/overdue */
-    private String status;
-    
-    /** 完�时间 */
-    private LocalDateTime completedAt;
-    
-    /** 是���完� */
-    private Boolean completedEarly;
-    
-    /** 审核照片地� */
-    private String reviewPhotoUrl;
-    
-    /** 审核语音地� */
-    private String reviewVoiceUrl;
-    
-    /** 审核状�:pending/reviewing/approved/rejected */
-    private String reviewStatus;
-    
-    /** 审核备注 */
-    private String reviewComment;
-    
-    /** 审核时间 */
-    private LocalDateTime reviewedAt;
-    
-    /** 审核人ID */
-    private Long reviewedBy;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-    
-    /** æ›´æ–°æ—¶é—´ */
-    private LocalDateTime updatedAt;
-}
-

+ 0 - 41
backend/src/main/java/com/zhixingyijia/entity/User.java

@@ -1,41 +0,0 @@
-package com.zhixingyijia.entity;
-
-import lombok.Data;
-import java.time.LocalDateTime;
-
-/**
- * 用户实体� */
-@Data
-public class User {
-    
-    /** 主键ID */
-    private Long id;
-    
-    /** 微信openid */
-    private String openid;
-    
-    /** 手机�*/
-    private String phone;
-    
-    /** 昵称 */
-    private String nickname;
-    
-    /** 头�URL */
-    private String avatar;
-    
-    /** 角色:parent-家长,child-孩� */
-    private String role;
-    
-    /** 密�(加密) */
-    private String password;
-    
-    /** 所属家庭ID */
-    private Long familyId;
-    
-    /** 创建时间 */
-    private LocalDateTime createdAt;
-    
-    /** æ›´æ–°æ—¶é—´ */
-    private LocalDateTime updatedAt;
-}
-

+ 0 - 23
backend/src/main/java/com/zhixingyijia/mapper/ChildMapper.java

@@ -1,23 +0,0 @@
-package com.zhixingyijia.mapper;
-
-import com.zhixingyijia.entity.Child;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * 孩子Mapper接口
- */
-@Mapper
-public interface ChildMapper {
-    
-    Child findById(@Param("id") Long id);
-    
-    Child findByUserId(@Param("userId") Long userId);
-    
-    int insert(Child child);
-    
-    int update(Child child);
-    
-    int updatePoints(@Param("id") Long id, @Param("points") int points);
-}
-

+ 0 - 20
backend/src/main/java/com/zhixingyijia/mapper/PointsLogMapper.java

@@ -1,20 +0,0 @@
-package com.zhixingyijia.mapper;
-
-import com.zhixingyijia.entity.PointsLog;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import java.util.List;
-
-/**
- * 积分流水Mapper接口
- */
-@Mapper
-public interface PointsLogMapper {
-    
-    List<PointsLog> findByChildId(@Param("childId") Long childId, @Param("limit") int limit);
-    
-    int insert(PointsLog pointsLog);
-    
-    int sumByChildIdAndType(@Param("childId") Long childId, @Param("type") String type, @Param("startDate") String startDate);
-}
-

+ 0 - 24
backend/src/main/java/com/zhixingyijia/mapper/RewardMapper.java

@@ -1,24 +0,0 @@
-package com.zhixingyijia.mapper;
-
-import com.zhixingyijia.entity.Reward;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import java.util.List;
-
-/**
- * 奖励Mapper接口
- */
-@Mapper
-public interface RewardMapper {
-    
-    Reward findById(@Param("id") Long id);
-    
-    List<Reward> findByFamilyId(@Param("familyId") Long familyId);
-    
-    List<Reward> findDefaultRewards();
-    
-    int insert(Reward reward);
-    
-    int update(Reward reward);
-}
-

+ 0 - 30
backend/src/main/java/com/zhixingyijia/mapper/TaskMapper.java

@@ -1,30 +0,0 @@
-package com.zhixingyijia.mapper;
-
-import com.zhixingyijia.entity.Task;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-import java.util.List;
-
-/**
- * 任务Mapper接口
- */
-@Mapper
-public interface TaskMapper {
-    
-    Task findById(@Param("id") Long id);
-    
-    List<Task> findByChildId(@Param("childId") Long childId, @Param("date") String date);
-    
-    List<Task> findByFamilyId(@Param("familyId") Long familyId);
-    
-    int insert(Task task);
-    
-    int update(Task task);
-    
-    int updateStatus(@Param("id") Long id, @Param("status") String status);
-    
-    int countTodayCompleted(@Param("childId") Long childId, @Param("date") String date);
-    
-    int countTodayTotal(@Param("childId") Long childId, @Param("date") String date);
-}
-

+ 0 - 21
backend/src/main/java/com/zhixingyijia/mapper/UserMapper.java

@@ -1,21 +0,0 @@
-package com.zhixingyijia.mapper;
-
-import com.zhixingyijia.entity.User;
-import org.apache.ibatis.annotations.Mapper;
-import org.apache.ibatis.annotations.Param;
-
-/**
- * 用户Mapper接口
- */
-@Mapper
-public interface UserMapper {
-    
-    User findById(@Param("id") Long id);
-    
-    User findByOpenid(@Param("openid") String openid);
-    
-    int insert(User user);
-    
-    int update(User user);
-}
-

+ 0 - 44
backend/src/main/java/com/zhixingyijia/service/PointsService.java

@@ -1,44 +0,0 @@
-package com.zhixingyijia.service;
-
-import com.zhixingyijia.entity.Child;
-import com.zhixingyijia.entity.PointsLog;
-import com.zhixingyijia.mapper.ChildMapper;
-import com.zhixingyijia.mapper.PointsLogMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * 积分�务� */
-@Service
-public class PointsService {
-
-    @Autowired
-    private ChildMapper childMapper;
-
-    @Autowired
-    private PointsLogMapper pointsLogMapper;
-
-    /**
-     * 获�孩�当�积分
-     */
-    public int getChildPoints(Long childId) {
-        Child child = childMapper.findById(childId);
-        return child != null ? child.getTotalPoints() : 0;
-    }
-
-    /**
-     * 获�积分�水
-     */
-    public List<PointsLog> getPointsLog(Long childId) {
-        return pointsLogMapper.findByChildId(childId, 50);
-    }
-
-    /**
-     * 获�指定类型的积分汇�     */
-    public int getPointsSumByType(Long childId, String type, String startDate) {
-        return pointsLogMapper.sumByChildIdAndType(childId, type, startDate);
-    }
-}
-

+ 0 - 55
backend/src/main/java/com/zhixingyijia/service/RewardService.java

@@ -1,55 +0,0 @@
-package com.zhixingyijia.service;
-
-import com.zhixingyijia.entity.Reward;
-import com.zhixingyijia.mapper.RewardMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-/**
- * 憟硋��滚𦛚蝐? */
-@Service
-public class RewardService {
-
-    @Autowired
-    private RewardMapper rewardMapper;
-
-    /**
-     * �瑕�摰嗅滬憟硋��𡑒”
-     */
-    public List<Reward> getFamilyRewards(Long familyId) {
-        return rewardMapper.findByFamilyId(familyId);
-    }
-
-    /**
-     * �瑕�憟硋�霂行�
-     */
-    public Reward findById(Long id) {
-        return rewardMapper.findById(id);
-    }
-
-    /**
-     * �𥕦遣憟硋�
-     */
-    public Reward createReward(Reward reward) {
-        rewardMapper.insert(reward);
-        return reward;
-    }
-
-    /**
-     * �湔鰵憟硋�
-     */
-    public Reward updateReward(Reward reward) {
-        rewardMapper.update(reward);
-        return reward;
-    }
-
-    /**
-     * �瑕�蝟餌�憸�挽憟硋�
-     */
-    public List<Reward> getDefaultRewards() {
-        return rewardMapper.findDefaultRewards();
-    }
-}
-

+ 0 - 152
backend/src/main/java/com/zhixingyijia/service/TaskService.java

@@ -1,152 +0,0 @@
-package com.zhixingyijia.service;
-
-import com.zhixingyijia.entity.PointsLog;
-import com.zhixingyijia.entity.Task;
-import com.zhixingyijia.mapper.PointsLogMapper;
-import com.zhixingyijia.mapper.TaskMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
-import java.util.List;
-
-/**
- * 任务�务� */
-@Service
-public class TaskService {
-
-    @Autowired
-    private TaskMapper taskMapper;
-
-    @Autowired
-    private PointsLogMapper pointsLogMapper;
-
-    @Value("${zhixingyijia.penalty.grace-minutes:10}")
-    private int graceMinutes;
-
-    @Value("${zhixingyijia.penalty.max-daily:5}")
-    private int maxDailyPenalty;
-
-    @Value("${zhixingyijia.points.early-bonus:1}")
-    private int earlyBonus;
-
-    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
-
-    /**
-     * 获�任务详情
-     */
-    public Task findById(Long id) {
-        return taskMapper.findById(id);
-    }
-
-    /**
-     * 获�今日任务列表
-     */
-    public List<Task> getTodayTasks(Long childId) {
-        String today = LocalDateTime.now().format(DATE_FORMATTER);
-        return taskMapper.findByChildId(childId, today);
-    }
-
-    /**
-     * 创建任务
-     */
-    @Transactional
-    public Task createTask(Task task) {
-        task.setStatus("pending");
-        taskMapper.insert(task);
-        return task;
-    }
-
-    /**
-     * 完�任务
-     */
-    @Transactional
-    public Task completeTask(Long taskId, String photoUrl, String voiceUrl) {
-        Task task = taskMapper.findById(taskId);
-        if (task == null) {
-            throw new RuntimeException("任务�存�);
-        }
-        
-        if ("approved".equals(task.getStatus()) || "completed".equals(task.getStatus())) {
-            throw new RuntimeException("任务已完�);
-        }
-
-        LocalDateTime now = LocalDateTime.now();
-        task.setCompletedAt(now);
-
-        // 判断是���完�
-        boolean isEarly = now.plusMinutes(graceMinutes).isBefore(task.getDeadline());
-        task.setCompletedEarly(isEarly);
-
-        if (Boolean.TRUE.equals(task.getNeedReview())) {
-            // 需�审�            task.setStatus("completed");
-            task.setReviewStatus("pending");
-            task.setReviewPhotoUrl(photoUrl);
-            task.setReviewVoiceUrl(voiceUrl);
-        } else {
-            // �需�审核,直接完�并�放积�            task.setStatus("approved");
-            awardTaskPoints(task, isEarly);
-        }
-
-        taskMapper.update(task);
-        return task;
-    }
-
-    /**
-     * 审核任务
-     */
-    @Transactional
-    public Task reviewTask(Long taskId, String result, String comment, Long reviewerId) {
-        Task task = taskMapper.findById(taskId);
-        if (task == null) {
-            throw new RuntimeException("任务�存�);
-        }
-
-        task.setReviewStatus(result);
-        task.setReviewComment(comment);
-        task.setReviewedBy(reviewerId);
-        task.setReviewedAt(LocalDateTime.now());
-
-        if ("approved".equals(result)) {
-            task.setStatus("approved");
-            awardTaskPoints(task, Boolean.TRUE.equals(task.getCompletedEarly()));
-        } else {
-            task.setStatus("rejected");
-        }
-
-        taskMapper.update(task);
-        return task;
-    }
-
-    /**
-     * �放任务积分
-     */
-    private void awardTaskPoints(Task task, boolean isEarly) {
-        int points = task.getPoints();
-        if (isEarly) {
-            points += earlyBonus;
-        }
-
-        // 记录积分�水
-        PointsLog log = new PointsLog();
-        log.setChildId(task.getChildId());
-        log.setTaskId(task.getId());
-        log.setAmount(points);
-        log.setType(isEarly ? "early" : "task");
-        log.setDescription(isEarly ? 
-            "完�任务� + task.getTitle() + "���完�+" + earlyBonus + "�" :
-            "完�任务� + task.getTitle() + "�);
-        pointsLogMapper.insert(log);
-    }
-
-    /**
-     * 获�家庭任务列表
-     */
-    public List<Task> getFamilyTasks(Long familyId) {
-        return taskMapper.findByFamilyId(familyId);
-    }
-}
-

+ 0 - 55
backend/src/main/java/com/zhixingyijia/service/UserService.java

@@ -1,55 +0,0 @@
-package com.zhixingyijia.service;
-
-import com.zhixingyijia.common.JwtUtil;
-import com.zhixingyijia.entity.User;
-import com.zhixingyijia.mapper.UserMapper;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-
-/**
- * 用户�务� */
-@Service
-public class UserService {
-
-    @Autowired
-    private UserMapper userMapper;
-
-    @Autowired
-    private JwtUtil jwtUtil;
-
-    /**
-     * 根�OpenID查找用户
-     */
-    public User findByOpenid(String openid) {
-        return userMapper.findByOpenid(openid);
-    }
-
-    /**
-     * 根�ID查找用户
-     */
-    public User findById(Long id) {
-        return userMapper.findById(id);
-    }
-
-    /**
-     * 微信登录
-     */
-    public String login(User user) {
-        // 查找或创建用�        User existUser = userMapper.findByOpenid(user.getOpenid());
-        if (existUser == null) {
-            userMapper.insert(user);
-            existUser = user;
-        }
-        // 生�Token
-        return jwtUtil.generateToken(existUser.getId(), existUser.getRole());
-    }
-
-    /**
-     * 注册用户
-     */
-    public User register(User user) {
-        userMapper.insert(user);
-        return user;
-    }
-}
-

+ 0 - 31
backend/src/main/resources/application.yml

@@ -1,31 +0,0 @@
-server:
-  port: 8080
-  servlet:
-    context-path: /api
-
-spring:
-  application:
-    name: zhixingyijia-backend
-  datasource:
-    driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://localhost:3306/zhixingyijia?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
-    username: root
-    password: root
-
-mybatis:
-  mapper-locations: classpath:mapper/*.xml
-  type-aliases-package: com.zhixingyijia.entity
-  configuration:
-    map-underscore-to-camel-case: true
-
-jwt:
-  secret: zhixingyijia-secret-key-2026
-  expiration: 604800000
-
-zhixingyijia:
-  penalty:
-    max-daily: 5
-    grace-minutes: 10
-  points:
-    early-bonus: 1
-    focus-perfect-bonus: 1

+ 0 - 55
backend/src/main/resources/mapper/ChildMapper.xml

@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.xinzhiyijia.mapper.ChildMapper">
-
-    <resultMap id="ChildMap" type="com.xinzhiyijia.entity.Child">
-        <id column="id" property="id"/>
-        <result column="user_id" property="userId"/>
-        <result column="family_id" property="familyId"/>
-        <result column="age" property="age"/>
-        <result column="grade" property="grade"/>
-        <result column="dan_level" property="danLevel"/>
-        <result column="penalty_enabled" property="penaltyEnabled"/>
-        <result column="current_streak" property="currentStreak"/>
-        <result column="max_streak" property="maxStreak"/>
-        <result column="last_check_in_date" property="lastCheckInDate"/>
-        <result column="total_points" property="totalPoints"/>
-        <result column="total_earned" property="totalEarned"/>
-        <result column="theme" property="theme"/>
-        <result column="created_at" property="createdAt"/>
-        <result column="updated_at" property="updatedAt"/>
-    </resultMap>
-
-    <select id="findById" resultMap="ChildMap">
-        SELECT * FROM children WHERE id = #{id}
-    </select>
-
-    <select id="findByUserId" resultMap="ChildMap">
-        SELECT * FROM children WHERE user_id = #{userId}
-    </select>
-
-    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
-        INSERT INTO children (user_id, family_id, age, grade, dan_level, penalty_enabled, theme)
-        VALUES (#{userId}, #{familyId}, #{age}, #{grade}, #{danLevel}, #{penaltyEnabled}, #{theme})
-    </insert>
-
-    <update id="update">
-        UPDATE children
-        SET age = #{age},
-            grade = #{grade},
-            dan_level = #{danLevel},
-            penalty_enabled = #{penaltyEnabled},
-            theme = #{theme},
-            updated_at = NOW()
-        WHERE id = #{id}
-    </update>
-
-    <update id="updatePoints">
-        UPDATE children
-        SET total_points = total_points + #{points},
-            total_earned = total_earned + #{points},
-            updated_at = NOW()
-        WHERE id = #{id}
-    </update>
-
-</mapper>

+ 0 - 34
backend/src/main/resources/mapper/PointsLogMapper.xml

@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.xinzhiyijia.mapper.PointsLogMapper">
-
-    <resultMap id="PointsLogMap" type="com.xinzhiyijia.entity.PointsLog">
-        <id column="id" property="id"/>
-        <result column="child_id" property="childId"/>
-        <result column="task_id" property="taskId"/>
-        <result column="amount" property="amount"/>
-        <result column="type" property="type"/>
-        <result column="description" property="description"/>
-        <result column="created_at" property="createdAt"/>
-    </resultMap>
-
-    <select id="findByChildId" resultMap="PointsLogMap">
-        SELECT * FROM points_log 
-        WHERE child_id = #{childId}
-        ORDER BY created_at DESC
-        LIMIT #{limit}
-    </select>
-
-    <insert id="insert">
-        INSERT INTO points_log (child_id, task_id, amount, type, description)
-        VALUES (#{childId}, #{taskId}, #{amount}, #{type}, #{description})
-    </insert>
-
-    <select id="sumByChildIdAndType" resultType="int">
-        SELECT COALESCE(SUM(amount), 0) FROM points_log
-        WHERE child_id = #{childId}
-        AND type = #{type}
-        AND DATE(created_at) >= #{startDate}
-    </select>
-
-</mapper>

+ 0 - 57
backend/src/main/resources/mapper/RewardMapper.xml

@@ -1,57 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.xinzhiyijia.mapper.RewardMapper">
-
-    <resultMap id="RewardMap" type="com.xinzhiyijia.entity.Reward">
-        <id column="id" property="id"/>
-        <result column="family_id" property="familyId"/>
-        <result column="child_id" property="childId"/>
-        <result column="category_id" property="categoryId"/>
-        <result column="name" property="name"/>
-        <result column="description" property="description"/>
-        <result column="points_required" property="pointsRequired"/>
-        <result column="icon" property="icon"/>
-        <result column="stock" property="stock"/>
-        <result column="status" property="status"/>
-        <result column="is_default" property="isDefault"/>
-        <result column="created_at" property="createdAt"/>
-        <result column="updated_at" property="updatedAt"/>
-    </resultMap>
-
-    <select id="findById" resultMap="RewardMap">
-        SELECT * FROM rewards WHERE id = #{id}
-    </select>
-
-    <select id="findByFamilyId" resultMap="RewardMap">
-        SELECT * FROM rewards 
-        WHERE family_id = #{familyId} OR family_id = -1
-        AND status = 'active'
-        ORDER BY is_default DESC, created_at DESC
-    </select>
-
-    <select id="findDefaultRewards" resultMap="RewardMap">
-        SELECT * FROM rewards 
-        WHERE is_default = 1 AND status = 'active'
-        ORDER BY category_id, points_required
-    </select>
-
-    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
-        INSERT INTO rewards (family_id, child_id, category_id, name, description, 
-                            points_required, icon, stock, status, is_default)
-        VALUES (#{familyId}, #{childId}, #{categoryId}, #{name}, #{description},
-                #{pointsRequired}, #{icon}, #{stock}, #{status}, #{isDefault})
-    </insert>
-
-    <update id="update">
-        UPDATE rewards
-        SET name = #{name},
-            description = #{description},
-            points_required = #{pointsRequired},
-            icon = #{icon},
-            stock = #{stock},
-            status = #{status},
-            updated_at = NOW()
-        WHERE id = #{id}
-    </update>
-
-</mapper>

+ 0 - 86
backend/src/main/resources/mapper/TaskMapper.xml

@@ -1,86 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.xinzhiyijia.mapper.TaskMapper">
-
-    <resultMap id="TaskMap" type="com.xinzhiyijia.entity.Task">
-        <id column="id" property="id"/>
-        <result column="family_id" property="familyId"/>
-        <result column="creator_id" property="creatorId"/>
-        <result column="child_id" property="childId"/>
-        <result column="title" property="title"/>
-        <result column="description" property="description"/>
-        <result column="points" property="points"/>
-        <result column="category" property="category"/>
-        <result column="priority" property="priority"/>
-        <result column="deadline" property="deadline"/>
-        <result column="estimated_duration" property="estimatedDuration"/>
-        <result column="repeat_type" property="repeatType"/>
-        <result column="need_review" property="needReview"/>
-        <result column="status" property="status"/>
-        <result column="completed_at" property="completedAt"/>
-        <result column="completed_early" property="completedEarly"/>
-        <result column="review_photo_url" property="reviewPhotoUrl"/>
-        <result column="review_voice_url" property="reviewVoiceUrl"/>
-        <result column="review_status" property="reviewStatus"/>
-        <result column="review_comment" property="reviewComment"/>
-        <result column="reviewed_at" property="reviewedAt"/>
-        <result column="reviewed_by" property="reviewedBy"/>
-        <result column="created_at" property="createdAt"/>
-        <result column="updated_at" property="updatedAt"/>
-    </resultMap>
-
-    <select id="findById" resultMap="TaskMap">
-        SELECT * FROM tasks WHERE id = #{id}
-    </select>
-
-    <select id="findByChildId" resultMap="TaskMap">
-        SELECT * FROM tasks 
-        WHERE child_id = #{childId}
-        AND DATE(deadline) = #{date}
-        ORDER BY deadline ASC
-    </select>
-
-    <select id="findByFamilyId" resultMap="TaskMap">
-        SELECT * FROM tasks 
-        WHERE family_id = #{familyId}
-        ORDER BY deadline DESC
-    </select>
-
-    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
-        INSERT INTO tasks (family_id, creator_id, child_id, title, description, points, 
-                          category, priority, deadline, estimated_duration, repeat_type, need_review)
-        VALUES (#{familyId}, #{creatorId}, #{childId}, #{title}, #{description}, #{points},
-                #{category}, #{priority}, #{deadline}, #{estimatedDuration}, #{repeatType}, #{needReview})
-    </insert>
-
-    <update id="update">
-        UPDATE tasks
-        SET title = #{title},
-            description = #{description},
-            points = #{points},
-            category = #{category},
-            priority = #{priority},
-            deadline = #{deadline},
-            need_review = #{needReview},
-            updated_at = NOW()
-        WHERE id = #{id}
-    </update>
-
-    <update id="updateStatus">
-        UPDATE tasks SET status = #{status}, updated_at = NOW() WHERE id = #{id}
-    </update>
-
-    <select id="countTodayCompleted" resultType="int">
-        SELECT COUNT(*) FROM tasks 
-        WHERE child_id = #{childId} 
-        AND DATE(deadline) = #{date}
-        AND status IN ('completed', 'approved')
-    </select>
-
-    <select id="countTodayTotal" resultType="int">
-        SELECT COUNT(*) FROM tasks 
-        WHERE child_id = #{childId} 
-        AND DATE(deadline) = #{date}
-    </select>
-
-</mapper>

+ 0 - 42
backend/src/main/resources/mapper/UserMapper.xml

@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.xinzhiyijia.mapper.UserMapper">
-
-    <resultMap id="UserMap" type="com.xinzhiyijia.entity.User">
-        <id column="id" property="id"/>
-        <result column="openid" property="openid"/>
-        <result column="phone" property="phone"/>
-        <result column="nickname" property="nickname"/>
-        <result column="avatar" property="avatar"/>
-        <result column="role" property="role"/>
-        <result column="password" property="password"/>
-        <result column="family_id" property="familyId"/>
-        <result column="created_at" property="createdAt"/>
-        <result column="updated_at" property="updatedAt"/>
-    </resultMap>
-
-    <select id="findById" resultMap="UserMap">
-        SELECT * FROM users WHERE id = #{id}
-    </select>
-
-    <select id="findByOpenid" resultMap="UserMap">
-        SELECT * FROM users WHERE openid = #{openid}
-    </select>
-
-    <insert id="insert" useGeneratedKeys="true" keyProperty="id">
-        INSERT INTO users (openid, phone, nickname, avatar, role, password, family_id)
-        VALUES (#{openid}, #{phone}, #{nickname}, #{avatar}, #{role}, #{password}, #{familyId})
-    </insert>
-
-    <update id="update">
-        UPDATE users
-        SET phone = #{phone},
-            nickname = #{nickname},
-            avatar = #{avatar},
-            password = #{password},
-            family_id = #{familyId},
-            updated_at = NOW()
-        WHERE id = #{id}
-    </update>
-
-</mapper>

+ 0 - 140
backend/src/main/resources/sql/init.sql

@@ -1,140 +0,0 @@
--- 知行益家数据库初始化脚本
-
--- 1. 用户表
-CREATE TABLE IF NOT EXISTS `users` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `openid` VARCHAR(64) NOT NULL COMMENT '微信openid',
-    `phone` VARCHAR(20) COMMENT '手机号',
-    `nickname` VARCHAR(50) COMMENT '昵称',
-    `avatar` VARCHAR(255) COMMENT '头像URL',
-    `role` ENUM('parent', 'child') NOT NULL COMMENT '角色:家长/孩子',
-    `password` VARCHAR(100) COMMENT '密码(加密)',
-    `family_id` BIGINT COMMENT '所属家庭ID',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    UNIQUE KEY `uk_openid` (`openid`),
-    INDEX `idx_family_id` (`family_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-
--- 2. 家庭表
-CREATE TABLE IF NOT EXISTS `families` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `name` VARCHAR(50) NOT NULL COMMENT '家庭名称',
-    `invite_code` VARCHAR(10) NOT NULL COMMENT '邀请码',
-    `creator_id` BIGINT NOT NULL COMMENT '创建者ID',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    UNIQUE KEY `uk_invite_code` (`invite_code`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='家庭表';
-
--- 3. 孩子信息表
-CREATE TABLE IF NOT EXISTS `children` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `user_id` BIGINT NOT NULL COMMENT '关联用户ID',
-    `family_id` BIGINT NOT NULL COMMENT '所属家庭ID',
-    `age` INT NOT NULL COMMENT '年龄',
-    `grade` VARCHAR(20) COMMENT '年级',
-    `dan_level` VARCHAR(10) COMMENT 'DAN测评等级',
-    `penalty_enabled` TINYINT(1) DEFAULT 1 COMMENT '是否开启扣分(6岁以下默认关闭)',
-    `current_streak` INT DEFAULT 0 COMMENT '当前连续天数',
-    `max_streak` INT DEFAULT 0 COMMENT '历史最长连续天数',
-    `last_check_in_date` DATETIME COMMENT '最后打卡日期',
-    `total_points` INT DEFAULT 0 COMMENT '当前积分',
-    `total_earned` INT DEFAULT 0 COMMENT '累计获得积分',
-    `theme` VARCHAR(20) DEFAULT 'default' COMMENT '主题',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    INDEX `idx_family_id` (`family_id`),
-    INDEX `idx_user_id` (`user_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='孩子信息表';
-
--- 4. 任务表
-CREATE TABLE IF NOT EXISTS `tasks` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `family_id` BIGINT NOT NULL COMMENT '所属家庭',
-    `creator_id` BIGINT NOT NULL COMMENT '创建者(家长)',
-    `child_id` BIGINT NOT NULL COMMENT '执行孩子',
-    `title` VARCHAR(100) NOT NULL COMMENT '任务名称',
-    `description` TEXT COMMENT '备注说明',
-    `points` INT NOT NULL DEFAULT 2 COMMENT '积分数(1-10)',
-    `category` VARCHAR(20) NOT NULL COMMENT '分类:学习/生活/运动/其他',
-    `priority` VARCHAR(10) DEFAULT 'medium' COMMENT '优先级:high/medium/low',
-    `deadline` DATETIME NOT NULL COMMENT '截止时间',
-    `estimated_duration` INT COMMENT '预计时长(分钟)',
-    `repeat_type` VARCHAR(20) DEFAULT 'none' COMMENT '重复类型:none/daily/weekly',
-    `need_review` TINYINT(1) DEFAULT 0 COMMENT '是否需要审核',
-    `status` VARCHAR(20) DEFAULT 'pending' COMMENT '状态:pending/completed/approved/rejected/overdue',
-    `completed_at` DATETIME COMMENT '完成时间',
-    `completed_early` TINYINT(1) DEFAULT 0 COMMENT '是否提前完成',
-    `review_photo_url` VARCHAR(255) COMMENT '审核照片地址',
-    `review_voice_url` VARCHAR(255) COMMENT '审核语音地址',
-    `review_status` VARCHAR(20) COMMENT '审核状态:pending/reviewing/approved/rejected',
-    `review_comment` VARCHAR(500) COMMENT '审核备注',
-    `reviewed_at` DATETIME COMMENT '审核时间',
-    `reviewed_by` BIGINT COMMENT '审核人ID',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    INDEX `idx_family_id` (`family_id`),
-    INDEX `idx_child_id` (`child_id`),
-    INDEX `idx_status` (`status`),
-    INDEX `idx_deadline` (`deadline`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='任务表';
-
--- 5. 积分流水表
-CREATE TABLE IF NOT EXISTS `points_log` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `child_id` BIGINT NOT NULL COMMENT '孩子ID',
-    `task_id` BIGINT COMMENT '关联任务ID',
-    `amount` INT NOT NULL COMMENT '积分数(正数为获得,负数为扣除)',
-    `type` VARCHAR(20) NOT NULL COMMENT '类型:task/early/streak/focus/reward/correction',
-    `description` VARCHAR(200) NOT NULL COMMENT '描述',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    INDEX `idx_child_id` (`child_id`),
-    INDEX `idx_created_at` (`created_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='积分流水表';
-
--- 6. 奖励分类表
-CREATE TABLE IF NOT EXISTS `reward_categories` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `family_id` BIGINT NOT NULL COMMENT '所属家庭',
-    `name` VARCHAR(50) NOT NULL COMMENT '分类名称',
-    `icon` VARCHAR(50) COMMENT '图标',
-    `sort_order` INT DEFAULT 0 COMMENT '排序',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    INDEX `idx_family_id` (`family_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='奖励分类表';
-
--- 7. 奖励表
-CREATE TABLE IF NOT EXISTS `rewards` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `family_id` BIGINT NOT NULL COMMENT '所属家庭',
-    `child_id` BIGINT COMMENT '指定孩子(NULL表示全员可用)',
-    `category_id` BIGINT COMMENT '分类ID',
-    `name` VARCHAR(100) NOT NULL COMMENT '奖励名称',
-    `description` VARCHAR(500) COMMENT '奖励描述',
-    `points_required` INT NOT NULL COMMENT '所需积分',
-    `icon` VARCHAR(50) COMMENT '图标',
-    `stock` INT DEFAULT -1 COMMENT '库存(-1表示无限)',
-    `status` VARCHAR(20) DEFAULT 'active' COMMENT '状态:active/inactive',
-    `is_default` TINYINT(1) DEFAULT 0 COMMENT '是否系统预设',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    `updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    INDEX `idx_family_id` (`family_id`),
-    INDEX `idx_child_id` (`child_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='奖励表';
-
--- 8. 奖励兑换表
-CREATE TABLE IF NOT EXISTS `reward_exchanges` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `reward_id` BIGINT NOT NULL COMMENT '奖励ID',
-    `child_id` BIGINT NOT NULL COMMENT '孩子ID',
-    `points_used` INT NOT NULL COMMENT '消耗积分',
-    `status` VARCHAR(20) DEFAULT 'pending' COMMENT '状态:pending/approved/rejected',
-    `review_comment` VARCHAR(500) COMMENT '审核备注',
-    `reviewed_by` BIGINT COMMENT '审核人ID',
-    `reviewed_at` DATETIME COMMENT '审核时间',
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    INDEX `idx_child_id` (`child_id`),
-    INDEX `idx_status` (`status`),
-    INDEX `idx_reward_id` (`reward_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='奖励兑换表';

+ 0 - 34
backend/src/main/resources/sql/seed.sql

@@ -1,34 +0,0 @@
--- 知行益家种子数据
-
--- 默认奖励分类(family_id=-1表示系统预设)
-INSERT INTO `reward_categories` (`id`, `family_id`, `name`, `icon`, `sort_order`) VALUES
-(1, -1, '物质类', '🎁', 1),
-(2, -1, '精神类', '🎬', 2),
-(3, -1, '特权类', '👑', 3)
-ON DUPLICATE KEY UPDATE `name` = VALUES(`name`);
-
--- 默认预设奖励
-INSERT INTO `rewards` (`id`, `family_id`, `child_id`, `category_id`, `name`, `points_required`, `icon`, `is_default`) VALUES
-(1, -1, NULL, 1, '小零食', 10, '🍬', 1),
-(2, -1, NULL, 1, '小玩具', 30, '🧸', 1),
-(3, -1, NULL, 1, '玩具盲盒', 50, '🎁', 1),
-(4, -1, NULL, 2, '看一集动画片', 5, '🎬', 1),
-(5, -1, NULL, 2, '玩游戏20分钟', 15, '🎮', 1),
-(6, -1, NULL, 2, '去游乐园', 200, '🎢', 1),
-(7, -1, NULL, 3, '今天不洗碗', 15, '🍽️', 1),
-(8, -1, NULL, 3, '晚睡30分钟', 20, '🌙', 1),
-(9, -1, NULL, 3, '免做一项家务', 25, '✨', 1)
-ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `points_required` = VALUES(`points_required`);
-
--- 预设勋章定义(如果需要勋章表)
--- INSERT INTO `badges` (`name`, `description`, `icon`, `condition_type`, `condition_value`) VALUES
--- ('初次尝试', '完成第一个任务', '⭐', 'task_complete', 1),
--- ('三日火焰', '连续3天按时完成', '🔥', 'streak_days', 3),
--- ('一周达人', '连续7天按时完成', '🏆', 'streak_days', 7),
--- ('百题斩', '完成100个任务', '📖', 'task_complete', 100),
--- ('精准打击', '连续10个任务提前完成', '🎯', 'early_complete', 10),
--- ('坚持不懈', '连续30天按时完成', '💪', 'streak_days', 30),
--- ('专注大师', '完成50次专注训练', '🧠', 'focus_training', 50),
--- ('积分富豪', '累计获得1000积分', '💰', 'total_points', 1000),
--- ('全勤宝宝', '一周所有任务全部完成', '🏅', 'weekly_perfect', 1),
--- ('完美主义', '单月任务完成率100%', '🎖️', 'monthly_perfect', 1);

+ 0 - 90
backend/src/test/java/com/zhixingyijia/common/JwtUtilTest.java

@@ -1,90 +0,0 @@
-package com.zhixingyijia.common;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.test.util.ReflectionTestUtils;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * JwtUtil类�元测� */
-@SpringBootTest
-class JwtUtilTest {
-
-    @Autowired
-    private JwtUtil jwtUtil;
-
-    @BeforeEach
-    void setUp() {
-        // 设置测试用的secret和expiration
-        ReflectionTestUtils.setField(jwtUtil, "secret", "test-secret-key-2026");
-        ReflectionTestUtils.setField(jwtUtil, "expiration", 86400000L); // 24�时
-    }
-
-    @Test
-    void testGenerateToken() {
-        Long userId = 1L;
-        String role = "parent";
-        
-        String token = jwtUtil.generateToken(userId, role);
-        
-        assertNotNull(token);
-        assertFalse(token.isEmpty());
-    }
-
-    @Test
-    void testParseToken() {
-        Long userId = 1L;
-        String role = "parent";
-        
-        String token = jwtUtil.generateToken(userId, role);
-        io.jsonwebtoken.Claims claims = jwtUtil.parseToken(token);
-        
-        assertNotNull(claims);
-        assertEquals(String.valueOf(userId), claims.getSubject());
-        assertEquals(role, claims.get("role", String.class));
-    }
-
-    @Test
-    void testGetUserIdFromToken() {
-        Long userId = 1L;
-        String role = "parent";
-        
-        String token = jwtUtil.generateToken(userId, role);
-        Long extractedUserId = jwtUtil.getUserIdFromToken(token);
-        
-        assertEquals(userId, extractedUserId);
-    }
-
-    @Test
-    void testGetRoleFromToken() {
-        Long userId = 1L;
-        String role = "parent";
-        
-        String token = jwtUtil.generateToken(userId, role);
-        String extractedRole = jwtUtil.getRoleFromToken(token);
-        
-        assertEquals(role, extractedRole);
-    }
-
-    @Test
-    void testIsTokenValid() {
-        Long userId = 1L;
-        String role = "parent";
-        
-        String token = jwtUtil.generateToken(userId, role);
-        boolean isValid = jwtUtil.isTokenValid(token);
-        
-        assertTrue(isValid);
-    }
-
-    @Test
-    void testIsTokenInvalid() {
-        String invalidToken = "invalid-token";
-        boolean isValid = jwtUtil.isTokenValid(invalidToken);
-        
-        assertFalse(isValid);
-    }
-}

+ 0 - 80
backend/src/test/java/com/zhixingyijia/common/ResultTest.java

@@ -1,80 +0,0 @@
-package com.zhixingyijia.common;
-
-import org.junit.jupiter.api.Test;
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * Result类�元测� */
-class ResultTest {
-
-    @Test
-    void testSuccessWithoutData() {
-        Result<?> result = Result.success();
-        assertEquals(200, result.getCode());
-        assertEquals("success", result.getMessage());
-        assertNull(result.getData());
-    }
-
-    @Test
-    void testSuccessWithData() {
-        String data = "test data";
-        Result<String> result = Result.success(data);
-        assertEquals(200, result.getCode());
-        assertEquals("success", result.getMessage());
-        assertEquals(data, result.getData());
-    }
-
-    @Test
-    void testSuccessWithMessageAndData() {
-        String message = "custom message";
-        String data = "test data";
-        Result<String> result = Result.success(message, data);
-        assertEquals(200, result.getCode());
-        assertEquals(message, result.getMessage());
-        assertEquals(data, result.getData());
-    }
-
-    @Test
-    void testErrorWithCodeAndMessage() {
-        int code = 500;
-        String message = "error message";
-        Result<?> result = Result.error(code, message);
-        assertEquals(code, result.getCode());
-        assertEquals(message, result.getMessage());
-        assertNull(result.getData());
-    }
-
-    @Test
-    void testErrorWithMessage() {
-        String message = "error message";
-        Result<?> result = Result.error(message);
-        assertEquals(500, result.getCode());
-        assertEquals(message, result.getMessage());
-        assertNull(result.getData());
-    }
-
-    @Test
-    void testUnauthorized() {
-        Result<?> result = Result.unauthorized();
-        assertEquals(401, result.getCode());
-        assertEquals("未授�, result.getMessage());
-        assertNull(result.getData());
-    }
-
-    @Test
-    void testNotFound() {
-        String message = "资��存�;
-        Result<?> result = Result.notFound(message);
-        assertEquals(404, result.getCode());
-        assertEquals(message, result.getMessage());
-        assertNull(result.getData());
-    }
-
-    @Test
-    void testNotFoundWithNullMessage() {
-        Result<?> result = Result.notFound(null);
-        assertEquals(404, result.getCode());
-        assertEquals("资��存�, result.getMessage());
-        assertNull(result.getData());
-    }
-}

+ 0 - 160
backend/src/test/java/com/zhixingyijia/common/SqlValidationTest.java

@@ -1,160 +0,0 @@
-package com.zhixingyijia.common;
-
-import org.junit.jupiter.api.Test;
-import org.springframework.core.io.ClassPathResource;
-import org.springframework.jdbc.core.JdbcTemplate;
-import org.springframework.jdbc.datasource.DriverManagerDataSource;
-import org.springframework.test.context.TestPropertySource;
-
-import javax.sql.DataSource;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.nio.charset.StandardCharsets;
-import java.util.regex.Pattern;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * SQL脚本验�测试
- * 注�:这个测试需�MySQL数�库连接�能�� */
-@TestPropertySource(properties = {
-    "spring.datasource.url=jdbc:mysql://localhost:3306/zhixingyijia_test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&createDatabaseIfNotExist=true",
-    "spring.datasource.username=root",
-    "spring.datasource.password=root"
-})
-class SqlValidationTest {
-
-    private static final Pattern CREATE_TABLE_PATTERN = Pattern.compile("CREATE TABLE", Pattern.CASE_INSENSITIVE);
-    private static final Pattern INSERT_INTO_PATTERN = Pattern.compile("INSERT INTO", Pattern.CASE_INSENSITIVE);
-    private static final Pattern INDEX_PATTERN = Pattern.compile("INDEX", Pattern.CASE_INSENSITIVE);
-    private static final Pattern FOREIGN_KEY_PATTERN = Pattern.compile("FOREIGN KEY", Pattern.CASE_INSENSITIVE);
-
-    @Test
-    void testInitSqlFileExists() {
-        // 验� init.sql 文件存在
-        assertDoesNotThrow(() -> {
-            ClassPathResource resource = new ClassPathResource("sql/init.sql");
-            assertTrue(resource.exists(), "init.sql 文件�存�);
-        });
-    }
-
-    @Test
-    void testSeedSqlFileExists() {
-        // 验� seed.sql 文件存在
-        assertDoesNotThrow(() -> {
-            ClassPathResource resource = new ClassPathResource("sql/seed.sql");
-            assertTrue(resource.exists(), "seed.sql 文件�存�);
-        });
-    }
-
-    @Test
-    void testInitSqlContent() throws IOException {
-        // 读�并验�init.sql 内容
-        String sqlContent = readSqlFile("sql/init.sql");
-        
-        // 验�包� CREATE TABLE 语�
-        assertTrue(CREATE_TABLE_PATTERN.matcher(sqlContent).find(), 
-            "init.sql 应该包� CREATE TABLE 语�");
-        
-        // 验�包�索引定义
-        assertTrue(INDEX_PATTERN.matcher(sqlContent).find(), 
-            "init.sql 应该包� INDEX 定义");
-        
-        // 验�表�
-        assertTrue(sqlContent.contains("users"), "应该包� users �);
-        assertTrue(sqlContent.contains("families"), "应该包� families �);
-        assertTrue(sqlContent.contains("children"), "应该包� children �);
-        assertTrue(sqlContent.contains("tasks"), "应该包� tasks �);
-        assertTrue(sqlContent.contains("points_log"), "应该包� points_log �);
-        assertTrue(sqlContent.contains("rewards"), "应该包� rewards �);
-        assertTrue(sqlContent.contains("reward_categories"), "应该包� reward_categories �);
-        assertTrue(sqlContent.contains("reward_exchanges"), "应该包� reward_exchanges �);
-    }
-
-    @Test
-    void testSeedSqlContent() throws IOException {
-        // 读�并验�seed.sql 内容
-        String sqlContent = readSqlFile("sql/seed.sql");
-        
-        // 验�包� INSERT INTO 语�
-        assertTrue(INSERT_INTO_PATTERN.matcher(sqlContent).find(), 
-            "seed.sql 应该包� INSERT INTO 语�");
-        
-        // 验�包�默认奖励分类
-        assertTrue(sqlContent.contains("物质�), "应该包�物质类奖励分�);
-        assertTrue(sqlContent.contains("精神�), "应该包�精神类奖励分�);
-        assertTrue(sqlContent.contains("特��), "应该包�特�类奖励分�);
-        
-        // 验�包�预设奖励
-        assertTrue(sqlContent.contains("�零�), "应该包��零食预设奖�);
-        assertTrue(sqlContent.contains("看一集动画片"), "应该包�看一集动画片预设奖励");
-    }
-
-    @Test
-    void testSqlSyntax() throws IOException {
-        // 简�的 SQL 语法验�
-        String initSql = readSqlFile("sql/init.sql");
-        String seedSql = readSqlFile("sql/seed.sql");
-        
-        // 验�语�以分�结尾(简�检查)
-        String[] initLines = initSql.split("\n");
-        for (String line : initLines) {
-            line = line.trim();
-            if (!line.isEmpty() && !line.startsWith("--")) {
-                // 跳过注释和空�                if (line.endsWith(");") || line.endsWith(";") || 
-                    line.startsWith("--") || line.startsWith("/*") ||
-                    line.contains("ENGINE=") || line.contains("DEFAULT CHARSET")) {
-                    // 这些是正常的�                }
-            }
-        }
-        
-        // 验�没有明显的语法错�        assertFalse(initSql.contains("CREATE TABLE ()"), "表定义�能为�);
-        assertFalse(seedSql.contains("INSERT INTO ()"), "�入语��能为空");
-    }
-
-    @Test
-    void testDatabaseConnection() {
-        // 注�:这个测试需�实际的MySQL数�库连�        // 在没有数�库的环境中会失�        try {
-            DataSource dataSource = createTestDataSource();
-            JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
-            
-            // �试创建测试数��            jdbcTemplate.execute("CREATE DATABASE IF NOT EXISTS zhixingyijia_test");
-            jdbcTemplate.execute("USE zhixingyijia_test");
-            
-            // 验�数�库连接��            String databaseName = jdbcTemplate.queryForObject("SELECT DATABASE()", String.class);
-            assertEquals("zhixingyijia_test", databaseName);
-            
-            // 清�测试数��            jdbcTemplate.execute("DROP DATABASE IF EXISTS zhixingyijia_test");
-            
-        } catch (Exception e) {
-            // 如果数�库连接失败,跳过这个测试
-            System.out.println("数�库连接测试跳� " + e.getMessage());
-        }
-    }
-
-    private String readSqlFile(String filePath) throws IOException {
-        ClassPathResource resource = new ClassPathResource(filePath);
-        try (InputStream inputStream = resource.getInputStream();
-             BufferedReader reader = new BufferedReader(
-                 new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
-            
-            StringBuilder content = new StringBuilder();
-            String line;
-            while ((line = reader.readLine()) != null) {
-                content.append(line).append("\n");
-            }
-            return content.toString();
-        }
-    }
-
-    private DataSource createTestDataSource() {
-        DriverManagerDataSource dataSource = new DriverManagerDataSource();
-        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
-        dataSource.setUrl("jdbc:mysql://localhost:3306/?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai");
-        dataSource.setUsername("root");
-        dataSource.setPassword("root");
-        return dataSource;
-    }
-}

+ 0 - 151
backend/src/test/java/com/zhixingyijia/integration/ApiContractTest.java

@@ -1,151 +0,0 @@
-package com.zhixingyijia.integration;
-
-import org.junit.jupiter.api.Test;
-
-import java.util.*;
-
-import static org.junit.jupiter.api.Assertions.*;
-
-/**
- * API憟𤑳漲瘚贝�
- * 撉諹��滨垢API靚�鍂銝𤾸�蝡舀𦻖���銝��湔�? */
-class ApiContractTest {
-
-    @Test
-    void testAuthEndpoints() {
-        // 撉諹�霈方��亙藁
-        Map<String, String> authEndpoints = new HashMap<>();
-        authEndpoints.put("POST /auth/login", "敺桐縑�餃�");
-        authEndpoints.put("GET /auth/info", "�瑕��冽�靽⊥�");
-        
-        // 撉諹����厩垢�寥�摮睃銁
-        assertEquals(2, authEndpoints.size());
-        assertTrue(authEndpoints.containsKey("POST /auth/login"));
-        assertTrue(authEndpoints.containsKey("GET /auth/info"));
-    }
-
-    @Test
-    void testTaskEndpoints() {
-        // 撉諹�隞餃𦛚�亙藁
-        Map<String, String> taskEndpoints = new HashMap<>();
-        taskEndpoints.put("GET /tasks/today/{childId}", "�瑕�隞𦠜𠯫隞餃𦛚");
-        taskEndpoints.put("GET /tasks/{taskId}", "�瑕�隞餃𦛚霂行�");
-        taskEndpoints.put("POST /tasks", "�𥕦遣隞餃𦛚");
-        taskEndpoints.put("POST /tasks/{taskId}/complete", "摰峕�隞餃𦛚");
-        taskEndpoints.put("POST /tasks/{taskId}/review", "摰⊥瓲隞餃𦛚");
-        taskEndpoints.put("GET /tasks/family/{familyId}", "�瑕�摰嗅滬隞餃𦛚�𡑒”");
-        
-        // 撉諹����厩垢�寥�摮睃銁
-        assertEquals(6, taskEndpoints.size());
-        assertTrue(taskEndpoints.containsKey("GET /tasks/today/{childId}"));
-        assertTrue(taskEndpoints.containsKey("GET /tasks/{taskId}"));
-        assertTrue(taskEndpoints.containsKey("POST /tasks"));
-        assertTrue(taskEndpoints.containsKey("POST /tasks/{taskId}/complete"));
-        assertTrue(taskEndpoints.containsKey("POST /tasks/{taskId}/review"));
-        assertTrue(taskEndpoints.containsKey("GET /tasks/family/{familyId}"));
-    }
-
-    @Test
-    void testRewardEndpoints() {
-        // 撉諹�憟硋��亙藁
-        Map<String, String> rewardEndpoints = new HashMap<>();
-        rewardEndpoints.put("GET /rewards/family/{familyId}", "�瑕�摰嗅滬憟硋��𡑒”");
-        rewardEndpoints.put("GET /rewards/{rewardId}", "�瑕�憟硋�霂行�");
-        rewardEndpoints.put("POST /rewards", "�𥕦遣憟硋�");
-        rewardEndpoints.put("PUT /rewards/{rewardId}", "�湔鰵憟硋�");
-        rewardEndpoints.put("GET /rewards/defaults", "�瑕�蝟餌�憸�挽憟硋�");
-        
-        // 撉諹����厩垢�寥�摮睃銁
-        assertEquals(5, rewardEndpoints.size());
-        assertTrue(rewardEndpoints.containsKey("GET /rewards/family/{familyId}"));
-        assertTrue(rewardEndpoints.containsKey("GET /rewards/{rewardId}"));
-        assertTrue(rewardEndpoints.containsKey("POST /rewards"));
-        assertTrue(rewardEndpoints.containsKey("PUT /rewards/{rewardId}"));
-        assertTrue(rewardEndpoints.containsKey("GET /rewards/defaults"));
-    }
-
-    @Test
-    void testPointsEndpoints() {
-        // 撉諹�蝘臬��亙藁
-        Map<String, String> pointsEndpoints = new HashMap<>();
-        pointsEndpoints.put("GET /points/balance/{childId}", "�瑕�摮拙�蝘臬�");
-        pointsEndpoints.put("GET /points/log/{childId}", "�瑕�蝘臬�瘚�偌");
-        
-        // 撉諹����厩垢�寥�摮睃銁
-        assertEquals(2, pointsEndpoints.size());
-        assertTrue(pointsEndpoints.containsKey("GET /points/balance/{childId}"));
-        assertTrue(pointsEndpoints.containsKey("GET /points/log/{childId}"));
-    }
-
-    @Test
-    void testApiVersioning() {
-        // 撉諹�API��𧋦�批�
-        // 敶枏�API瘝⊥���𧋦�批�嚗䔶��芣䔉�臭誑瘛餃�
-        String currentApiVersion = "v1";
-        assertNotNull(currentApiVersion);
-        assertEquals("v1", currentApiVersion);
-    }
-
-    @Test
-    void testApiResponseFormat() {
-        // 撉諹�API�滚��澆�
-        // �𡒊垢蝏煺�雿輻鍂Result蝐餃�鋆��摨?        // �滨垢�����聢撘𧶏�{ code: 200, message: "success", data: ... }
-        
-        Map<String, Object> expectedResponse = new HashMap<>();
-        expectedResponse.put("code", 200);
-        expectedResponse.put("message", "success");
-        expectedResponse.put("data", null);
-        
-        // 撉諹��滚�蝏𤘪�
-        assertTrue(expectedResponse.containsKey("code"));
-        assertTrue(expectedResponse.containsKey("message"));
-        assertTrue(expectedResponse.containsKey("data"));
-    }
-
-    @Test
-    void testAuthenticationHeader() {
-        // 撉諹�霈方�憭湔聢撘?        String authHeader = "Bearer token_here";
-        assertTrue(authHeader.startsWith("Bearer "));
-        
-        String token = authHeader.substring(7);
-        assertNotNull(token);
-        assertFalse(token.isEmpty());
-    }
-
-    @Test
-    void testRequestResponseCompatibility() {
-        // 撉諹�霂瑟����摨𠉛��澆捆�?        
-        // 1. �餃�霂瑟�
-        Map<String, String> loginRequest = new HashMap<>();
-        loginRequest.put("code", "wx_code");
-        loginRequest.put("role", "parent");
-        loginRequest.put("nickname", "瘚贝��冽�");
-        
-        Map<String, Object> loginResponse = new HashMap<>();
-        loginResponse.put("token", "jwt_token");
-        loginResponse.put("userId", 1L);
-        loginResponse.put("role", "parent");
-        
-        // 撉諹��餃�霂瑟����摨?        assertNotNull(loginRequest.get("code"));
-        assertNotNull(loginResponse.get("token"));
-        
-        // 2. �𥕦遣隞餃𦛚霂瑟�
-        Map<String, Object> createTaskRequest = new HashMap<>();
-        createTaskRequest.put("childId", 1L);
-        createTaskRequest.put("title", "瘚贝�隞餃𦛚");
-        createTaskRequest.put("points", 2);
-        createTaskRequest.put("deadline", "2026-03-31 20:00");
-        
-        // 撉諹��𥕦遣隞餃𦛚霂瑟�
-        assertNotNull(createTaskRequest.get("title"));
-        assertTrue((Integer) createTaskRequest.get("points") > 0);
-        
-        // 3. 摰峕�隞餃𦛚霂瑟�
-        Map<String, Object> completeTaskRequest = new HashMap<>();
-        completeTaskRequest.put("photoUrl", "photo.jpg");
-        completeTaskRequest.put("voiceUrl", "voice.mp3");
-        
-        // 撉諹�摰峕�隞餃𦛚霂瑟�
-        assertNotNull(completeTaskRequest);
-    }
-}

+ 0 - 229
backend/src/test/java/com/zhixingyijia/service/TaskServiceTest.java

@@ -1,229 +0,0 @@
-package com.zhixingyijia.service;
-
-import com.zhixingyijia.entity.PointsLog;
-import com.zhixingyijia.entity.Task;
-import com.zhixingyijia.mapper.PointsLogMapper;
-import com.zhixingyijia.mapper.TaskMapper;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.springframework.test.util.ReflectionTestUtils;
-
-import java.time.LocalDateTime;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.*;
-
-/**
- * TaskService�元测试
- */
-@ExtendWith(MockitoExtension.class)
-class TaskServiceTest {
-
-    @InjectMocks
-    private TaskService taskService;
-
-    @Mock
-    private TaskMapper taskMapper;
-
-    @Mock
-    private PointsLogMapper pointsLogMapper;
-
-    @Test
-    void testFindById() {
-        // 准备测试数�
-        Long taskId = 1L;
-        Task expectedTask = new Task();
-        expectedTask.setId(taskId);
-        expectedTask.setTitle("测试任务");
-
-        // 设置mock行为
-        when(taskMapper.findById(taskId)).thenReturn(expectedTask);
-
-        // 执行测试
-        Task result = taskService.findById(taskId);
-
-        // 验�结果
-        assertNotNull(result);
-        assertEquals(expectedTask.getId(), result.getId());
-        assertEquals(expectedTask.getTitle(), result.getTitle());
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).findById(taskId);
-    }
-
-    @Test
-    void testCreateTask() {
-        // 准备测试数�
-        Task task = new Task();
-        task.setTitle("测试任务");
-        task.setPoints(2);
-
-        // 设置mock行为
-        doAnswer(invocation -> {
-            Task insertedTask = invocation.getArgument(0);
-            insertedTask.setId(1L);
-            return null;
-        }).when(taskMapper).insert(any(Task.class));
-
-        // 执行测试
-        Task result = taskService.createTask(task);
-
-        // 验�结果
-        assertNotNull(result);
-        assertEquals(1L, result.getId());
-        assertEquals("pending", result.getStatus());
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).insert(task);
-    }
-
-    @Test
-    void testCompleteTaskRequiresReview() {
-        // 准备测试数�
-        Long taskId = 1L;
-        Task task = new Task();
-        task.setId(taskId);
-        task.setTitle("测试任务");
-        task.setPoints(2);
-        task.setStatus("pending");
-        task.setNeedReview(true);
-        task.setDeadline(LocalDateTime.now().plusHours(2));
-
-        // 设置mock行为
-        when(taskMapper.findById(taskId)).thenReturn(task);
-
-        // 执行测试
-        Task result = taskService.completeTask(taskId, "photo.jpg", "voice.mp3");
-
-        // 验�结果
-        assertNotNull(result);
-        assertEquals("completed", result.getStatus());
-        assertEquals("pending", result.getReviewStatus());
-        assertEquals("photo.jpg", result.getReviewPhotoUrl());
-        assertEquals("voice.mp3", result.getReviewVoiceUrl());
-        assertNotNull(result.getCompletedAt());
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).findById(taskId);
-        verify(taskMapper, times(1)).update(task);
-        verify(pointsLogMapper, never()).insert(any(PointsLog.class));
-    }
-
-    @Test
-    void testCompleteTaskNoReview() {
-        // 准备测试数�
-        Long taskId = 1L;
-        Task task = new Task();
-        task.setId(taskId);
-        task.setTitle("测试任务");
-        task.setPoints(2);
-        task.setStatus("pending");
-        task.setNeedReview(false);
-        task.setDeadline(LocalDateTime.now().plusHours(2));
-
-        // 设置mock行为
-        when(taskMapper.findById(taskId)).thenReturn(task);
-
-        // 执行测试
-        Task result = taskService.completeTask(taskId, null, null);
-
-        // 验�结果
-        assertNotNull(result);
-        assertEquals("approved", result.getStatus());
-        assertNotNull(result.getCompletedAt());
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).findById(taskId);
-        verify(taskMapper, times(1)).update(task);
-        verify(pointsLogMapper, times(1)).insert(any(PointsLog.class));
-    }
-
-    @Test
-    void testCompleteTaskAlreadyCompleted() {
-        // 准备测试数�
-        Long taskId = 1L;
-        Task task = new Task();
-        task.setId(taskId);
-        task.setTitle("测试任务");
-        task.setStatus("completed");
-
-        // 设置mock行为
-        when(taskMapper.findById(taskId)).thenReturn(task);
-
-        // 执行测试并验�异�        assertThrows(RuntimeException.class, () -> {
-            taskService.completeTask(taskId, null, null);
-        });
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).findById(taskId);
-        verify(taskMapper, never()).update(any(Task.class));
-        verify(pointsLogMapper, never()).insert(any(PointsLog.class));
-    }
-
-    @Test
-    void testReviewTaskApproved() {
-        // 准备测试数�
-        Long taskId = 1L;
-        Long reviewerId = 1L;
-        Task task = new Task();
-        task.setId(taskId);
-        task.setTitle("测试任务");
-        task.setPoints(2);
-        task.setStatus("completed");
-        task.setCompletedEarly(true);
-
-        // 设置mock行为
-        when(taskMapper.findById(taskId)).thenReturn(task);
-
-        // 执行测试
-        Task result = taskService.reviewTask(taskId, "approved", "审核通过", reviewerId);
-
-        // 验�结果
-        assertNotNull(result);
-        assertEquals("approved", result.getStatus());
-        assertEquals("approved", result.getReviewStatus());
-        assertEquals("审核通过", result.getReviewComment());
-        assertEquals(reviewerId, result.getReviewedBy());
-        assertNotNull(result.getReviewedAt());
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).findById(taskId);
-        verify(taskMapper, times(1)).update(task);
-        verify(pointsLogMapper, times(1)).insert(any(PointsLog.class));
-    }
-
-    @Test
-    void testReviewTaskRejected() {
-        // 准备测试数�
-        Long taskId = 1L;
-        Long reviewerId = 1L;
-        Task task = new Task();
-        task.setId(taskId);
-        task.setTitle("测试任务");
-        task.setPoints(2);
-        task.setStatus("completed");
-
-        // 设置mock行为
-        when(taskMapper.findById(taskId)).thenReturn(task);
-
-        // 执行测试
-        Task result = taskService.reviewTask(taskId, "rejected", "审核拒�", reviewerId);
-
-        // 验�结果
-        assertNotNull(result);
-        assertEquals("rejected", result.getStatus());
-        assertEquals("rejected", result.getReviewStatus());
-        assertEquals("审核拒�", result.getReviewComment());
-        assertEquals(reviewerId, result.getReviewedBy());
-        assertNotNull(result.getReviewedAt());
-
-        // 验�mock调用
-        verify(taskMapper, times(1)).findById(taskId);
-        verify(taskMapper, times(1)).update(task);
-        verify(pointsLogMapper, never()).insert(any(PointsLog.class));
-    }
-}

+ 0 - 163
backend/src/test/java/com/zhixingyijia/service/UserServiceTest.java

@@ -1,163 +0,0 @@
-package com.zhixingyijia.service;
-
-import com.zhixingyijia.common.JwtUtil;
-import com.zhixingyijia.entity.User;
-import com.zhixingyijia.mapper.UserMapper;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-
-import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.*;
-
-/**
- * UserService单元测试
- */
-@ExtendWith(MockitoExtension.class)
-class UserServiceTest {
-
-    @InjectMocks
-    private UserService userService;
-
-    @Mock
-    private UserMapper userMapper;
-
-    @Mock
-    private JwtUtil jwtUtil;
-
-    @Test
-    void testFindByOpenid() {
-        // 准备测试数据
-        String openid = "test_openid";
-        User expectedUser = new User();
-        expectedUser.setId(1L);
-        expectedUser.setOpenid(openid);
-
-        // 设置mock行为
-        when(userMapper.findByOpenid(openid)).thenReturn(expectedUser);
-
-        // 执行测试
-        User result = userService.findByOpenid(openid);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals(expectedUser.getId(), result.getId());
-        assertEquals(expectedUser.getOpenid(), result.getOpenid());
-
-        // 验证mock调用
-        verify(userMapper, times(1)).findByOpenid(openid);
-    }
-
-    @Test
-    void testFindById() {
-        // 准备测试数据
-        Long id = 1L;
-        User expectedUser = new User();
-        expectedUser.setId(id);
-        expectedUser.setOpenid("test_openid");
-
-        // 设置mock行为
-        when(userMapper.findById(id)).thenReturn(expectedUser);
-
-        // 执行测试
-        User result = userService.findById(id);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals(expectedUser.getId(), result.getId());
-
-        // 验证mock调用
-        verify(userMapper, times(1)).findById(id);
-    }
-
-    @Test
-    void testLoginUserExists() {
-        // 准备测试数据
-        User user = new User();
-        user.setOpenid("test_openid");
-        user.setRole("parent");
-
-        User existUser = new User();
-        existUser.setId(1L);
-        existUser.setOpenid("test_openid");
-        existUser.setRole("parent");
-
-        String expectedToken = "test_token";
-
-        // 设置mock行为
-        when(userMapper.findByOpenid(anyString())).thenReturn(existUser);
-        when(jwtUtil.generateToken(anyLong(), anyString())).thenReturn(expectedToken);
-
-        // 执行测试
-        String token = userService.login(user);
-
-        // 验证结果
-        assertNotNull(token);
-        assertEquals(expectedToken, token);
-
-        // 验证mock调用
-        verify(userMapper, times(1)).findByOpenid(user.getOpenid());
-        verify(userMapper, never()).insert(any(User.class));
-        verify(jwtUtil, times(1)).generateToken(existUser.getId(), existUser.getRole());
-    }
-
-    @Test
-    void testLoginUserNotExists() {
-        // 准备测试数据
-        User user = new User();
-        user.setOpenid("test_openid");
-        user.setRole("parent");
-
-        String expectedToken = "test_token";
-
-        // 设置mock行为
-        when(userMapper.findByOpenid(anyString())).thenReturn(null);
-        doAnswer(invocation -> {
-            User insertedUser = invocation.getArgument(0);
-            insertedUser.setId(1L);
-            return null;
-        }).when(userMapper).insert(any(User.class));
-        when(jwtUtil.generateToken(anyLong(), anyString())).thenReturn(expectedToken);
-
-        // 执行测试
-        String token = userService.login(user);
-
-        // 验证结果
-        assertNotNull(token);
-        assertEquals(expectedToken, token);
-
-        // 验证mock调用
-        verify(userMapper, times(1)).findByOpenid(user.getOpenid());
-        verify(userMapper, times(1)).insert(user);
-        verify(jwtUtil, times(1)).generateToken(user.getId(), user.getRole());
-    }
-
-    @Test
-    void testRegister() {
-        // 准备测试数据
-        User user = new User();
-        user.setOpenid("test_openid");
-        user.setRole("parent");
-
-        // 设置mock行为
-        doAnswer(invocation -> {
-            User insertedUser = invocation.getArgument(0);
-            insertedUser.setId(1L);
-            return null;
-        }).when(userMapper).insert(any(User.class));
-
-        // 执行测试
-        User result = userService.register(user);
-
-        // 验证结果
-        assertNotNull(result);
-        assertEquals(1L, result.getId());
-
-        // 验证mock调用
-        verify(userMapper, times(1)).insert(user);
-    }
-}

+ 0 - 28
backend/src/test/resources/test-schema.sql

@@ -1,28 +0,0 @@
--- 测试用的简化数据库 schema
--- 用于验证 SQL 语法
-
-CREATE DATABASE IF NOT EXISTS `zhixingyijia_test` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-
-USE `zhixingyijia_test`;
-
--- 测试表结构
-CREATE TABLE IF NOT EXISTS `test_users` (
-    `id` BIGINT PRIMARY KEY AUTO_INCREMENT,
-    `openid` VARCHAR(64) NOT NULL,
-    `nickname` VARCHAR(50),
-    `role` ENUM('parent', 'child') NOT NULL,
-    `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
-    UNIQUE KEY `uk_openid` (`openid`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-
--- 插入测试数据
-INSERT INTO `test_users` (`openid`, `nickname`, `role`) VALUES
-('test_openid_1', '测试家长', 'parent'),
-('test_openid_2', '测试孩子', 'child');
-
--- 验证数据
-SELECT COUNT(*) as user_count FROM `test_users`;
-
--- 清理测试数据
-DROP TABLE IF EXISTS `test_users`;
-DROP DATABASE IF EXISTS `zhixingyijia_test`;

+ 0 - 62
backend/src/test/resources/validate-sql.sh

@@ -1,62 +0,0 @@
-#!/bin/bash
-# SQL 验证脚本
-
-echo "开始验证 SQL 脚本..."
-
-# 检查 init.sql 是否存在
-if [ ! -f "src/main/resources/sql/init.sql" ]; then
-    echo "❌ init.sql 文件不存在"
-    exit 1
-fi
-
-# 检查 seed.sql 是否存在
-if [ ! -f "src/main/resources/sql/seed.sql" ]; then
-    echo "❌ seed.sql 文件不存在"
-    exit 1
-fi
-
-# 检查 SQL 文件是否包含创建表语句
-echo "检查 init.sql 中的表创建语句..."
-table_count=$(grep -c "CREATE TABLE" src/main/resources/sql/init.sql)
-echo "找到 $table_count 个 CREATE TABLE 语句"
-
-# 检查 SQL 文件是否包含插入数据语句
-echo "检查 seed.sql 中的数据插入语句..."
-insert_count=$(grep -c "INSERT INTO" src/main/resources/sql/seed.sql)
-echo "找到 $insert_count 个 INSERT INTO 语句"
-
-# 检查是否有语法错误(简单检查)
-echo "检查 SQL 语法..."
-
-# 检查是否缺少分号
-missing_semicolon_count=$(grep -v "^--" src/main/resources/sql/init.sql | grep -v "^$" | grep -v ";$" | wc -l)
-if [ $missing_semicolon_count -gt 0 ]; then
-    echo "⚠️  发现 $missing_semicolon_count 行可能缺少分号"
-else
-    echo "✅ 所有 SQL 语句都有分号"
-fi
-
-# 检查表名是否正确
-echo "检查表名..."
-table_names=$(grep "CREATE TABLE" src/main/resources/sql/init.sql | grep -o "`[^`]*`" | sort | uniq)
-echo "找到以下表:"
-echo "$table_names"
-
-# 检查索引
-echo "检查索引..."
-index_count=$(grep -c "INDEX" src/main/resources/sql/init.sql)
-echo "找到 $index_count 个索引定义"
-
-# 检查外键
-echo "检查外键..."
-foreign_key_count=$(grep -c "FOREIGN KEY" src/main/resources/sql/init.sql)
-echo "找到 $foreign_key_count 个外键定义"
-
-echo ""
-echo "✅ SQL 验证完成"
-echo ""
-echo "总结:"
-echo "- 表数量:$table_count"
-echo "- 插入语句:$insert_count"
-echo "- 索引数量:$index_count"
-echo "- 外键数量:$foreign_key_count"

+ 2 - 2
zxyj-backend/sql/init.sql

@@ -1,7 +1,7 @@
 -- 心知家庭数据库初始化脚本
 -- 创建数据库
-CREATE DATABASE IF NOT EXISTS zxyj DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-USE zxyj;
+CREATE DATABASE IF NOT EXISTS xzyj DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
+USE xzyj;
 
 -- 家庭表
 CREATE TABLE IF NOT EXISTS families (

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/ZxyjApplication.java

@@ -12,4 +12,3 @@ public class ZxyjApplication {
         SpringApplication.run(ZxyjApplication.class, args);
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/common/Result.java

@@ -48,4 +48,3 @@ public class Result<T> implements Serializable {
         return result;
     }
 }
-

+ 74 - 52
zxyj-backend/src/main/java/com/zxyj/config/DatabaseInitializer.java

@@ -19,30 +19,35 @@ public class DatabaseInitializer implements CommandLineRunner {
 
     @Override
     public void run(String... args) throws Exception {
-        log.info("开始初始化数据�?..");
+        log.info("开始初始化数据库...");
         
-        // 1. 检查并创建数据�?        initializeDatabase();
+        // 1. 检查并创建数据库
+        initializeDatabase();
         
-        // 2. 检查并创建�?        initializeTables();
+        // 2. 检查并创建表
+        initializeTables();
         
-        // 3. 初始化默认数�?        initializeDefaultData();
+        // 3. 初始化默认数据
+        initializeDefaultData();
         
-        log.info("数据库初始化完成�?);
+        log.info("数据库初始化完成!");
     }
 
     private void initializeDatabase() {
         try {
             // 尝试连接数据库,如果不存在则创建
-            jdbcTemplate.execute("CREATE DATABASE IF NOT EXISTS zxyj DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
-            log.info("数据库检查完�?);
+            jdbcTemplate.execute("CREATE DATABASE IF NOT EXISTS xzyj DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
+            log.info("数据库检查完成");
         } catch (Exception e) {
-            log.warn("创建数据库失�? {}", e.getMessage());
+            log.warn("创建数据库失败: {}", e.getMessage());
         }
     }
 
     private void initializeTables() {
-        // 表创建SQL - 使用IF NOT EXISTS确保幂等�?        List<String> createTableSQLs = Arrays.asList(
-            // 家庭�?            "CREATE TABLE IF NOT EXISTS families (" +
+        // 表创建SQL - 使用IF NOT EXISTS确保幂等性
+        List<String> createTableSQLs = Arrays.asList(
+            // 家庭表
+            "CREATE TABLE IF NOT EXISTS families (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "name VARCHAR(100), " +
             "invite_code VARCHAR(8) UNIQUE, " +
@@ -51,7 +56,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_invite_code (invite_code)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 用户�?            "CREATE TABLE IF NOT EXISTS users (" +
+            // 用户表
+            "CREATE TABLE IF NOT EXISTS users (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "openid VARCHAR(64) NOT NULL, " +
             "unionid VARCHAR(64), " +
@@ -66,7 +72,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_family_id (family_id)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 孩子详情�?            "CREATE TABLE IF NOT EXISTS children (" +
+            // 孩子详情表
+            "CREATE TABLE IF NOT EXISTS children (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "user_id BIGINT NOT NULL, " +
             "family_id BIGINT NOT NULL, " +
@@ -87,7 +94,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_family_id (family_id)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 任务�?            "CREATE TABLE IF NOT EXISTS tasks (" +
+            // 任务表
+            "CREATE TABLE IF NOT EXISTS tasks (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "family_id BIGINT NOT NULL, " +
             "creator_id BIGINT NOT NULL, " +
@@ -109,7 +117,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_category (category)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 积分流水�?            "CREATE TABLE IF NOT EXISTS points_log (" +
+            // 积分流水表
+            "CREATE TABLE IF NOT EXISTS points_log (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "child_id BIGINT NOT NULL, " +
             "task_id BIGINT, " +
@@ -121,7 +130,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_type (type)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 积分清零记录�?            "CREATE TABLE IF NOT EXISTS points_reset_log (" +
+            // 积分清零记录表
+            "CREATE TABLE IF NOT EXISTS points_reset_log (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "child_id BIGINT NOT NULL, " +
             "balance_before INT NOT NULL, " +
@@ -131,7 +141,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_child_id (child_id)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 奖励�?            "CREATE TABLE IF NOT EXISTS rewards (" +
+            // 奖励表
+            "CREATE TABLE IF NOT EXISTS rewards (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "family_id BIGINT NOT NULL, " +
             "child_id BIGINT NOT NULL, " +
@@ -148,7 +159,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_is_template (is_template)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 奖励分类�?            "CREATE TABLE IF NOT EXISTS reward_categories (" +
+            // 奖励分类表
+            "CREATE TABLE IF NOT EXISTS reward_categories (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "family_id BIGINT NOT NULL, " +
             "name VARCHAR(32) NOT NULL, " +
@@ -167,7 +179,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_word (word)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 任务审核�?            "CREATE TABLE IF NOT EXISTS task_reviews (" +
+            // 任务审核表
+            "CREATE TABLE IF NOT EXISTS task_reviews (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "task_id BIGINT NOT NULL, " +
             "child_id BIGINT NOT NULL, " +
@@ -186,7 +199,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_ai_result (ai_result)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 勋章定义�?            "CREATE TABLE IF NOT EXISTS badge_definitions (" +
+            // 勋章定义表
+            "CREATE TABLE IF NOT EXISTS badge_definitions (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "badge_type VARCHAR(32) NOT NULL, " +
             "name VARCHAR(50) NOT NULL, " +
@@ -198,7 +212,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_badge_type (badge_type)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 勋章�?            "CREATE TABLE IF NOT EXISTS badges (" +
+            // 勋章表
+            "CREATE TABLE IF NOT EXISTS badges (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "child_id BIGINT NOT NULL, " +
             "badge_type VARCHAR(32) NOT NULL, " +
@@ -214,7 +229,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "created_at DATETIME DEFAULT CURRENT_TIMESTAMP" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 专注训练记录�?            "CREATE TABLE IF NOT EXISTS focus_sessions (" +
+            // 专注训练记录表
+            "CREATE TABLE IF NOT EXISTS focus_sessions (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "child_id BIGINT NOT NULL, " +
             "mode ENUM('simple','pomodoro') NOT NULL, " +
@@ -227,7 +243,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_child_id_completed (child_id, completed_at)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 专注训练配置�?            "CREATE TABLE IF NOT EXISTS focus_config (" +
+            // 专注训练配置表
+            "CREATE TABLE IF NOT EXISTS focus_config (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "family_id BIGINT, " +
             "max_daily_count TINYINT DEFAULT 3, " +
@@ -235,7 +252,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "created_at DATETIME DEFAULT CURRENT_TIMESTAMP" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // DAN测评�?            "CREATE TABLE IF NOT EXISTS dan_assessments (" +
+            // DAN测评表
+            "CREATE TABLE IF NOT EXISTS dan_assessments (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "child_id BIGINT NOT NULL, " +
             "dan_level VARCHAR(2) NOT NULL, " +
@@ -247,7 +265,8 @@ public class DatabaseInitializer implements CommandLineRunner {
             "INDEX idx_child_id_level (child_id, dan_level)" +
             ") ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
             
-            // 任务模板�?            "CREATE TABLE IF NOT EXISTS task_templates (" +
+            // 任务模板表
+            "CREATE TABLE IF NOT EXISTS task_templates (" +
             "id BIGINT AUTO_INCREMENT PRIMARY KEY, " +
             "dan_level VARCHAR(2) NOT NULL, " +
             "title VARCHAR(200) NOT NULL, " +
@@ -296,46 +315,49 @@ public class DatabaseInitializer implements CommandLineRunner {
             try {
                 jdbcTemplate.execute(sql);
             } catch (Exception e) {
-                log.warn("创建表失�? {}", e.getMessage());
+                log.warn("创建表失败: {}", e.getMessage());
             }
         }
         
-        log.info("数据表检查完�?);
+        log.info("数据表检查完成");
     }
 
     private void initializeDefaultData() {
-        // 初始化预设奖励模�?        try {
-            // 检查是否已有预设奖�?            Integer count = jdbcTemplate.queryForObject(
+        // 初始化预设奖励模板
+        try {
+            // 检查是否已有预设奖励
+            Integer count = jdbcTemplate.queryForObject(
                 "SELECT COUNT(*) FROM rewards WHERE is_template = 1", Integer.class);
             
             if (count == null || count == 0) {
                 // 插入预设奖励模板
                 jdbcTemplate.execute("INSERT INTO rewards (family_id, child_id, title, points_required, category, is_template) VALUES " +
-                    "(0, 0, '看动画片30分钟', 30, '精神�?, 1), " +
-                    "(0, 0, '玩平板游�?0分钟', 40, '特权�?, 1), " +
-                    "(0, 0, '去游乐场', 100, '物质�?, 1), " +
-                    "(0, 0, '买玩�?, 150, '物质�?, 1), " +
-                    "(0, 0, '吃冰淇淋', 20, '物质�?, 1), " +
-                    "(0, 0, '选择晚餐', 25, '特权�?, 1)");
+                    "(0, 0, '看动画片30分钟', 30, '精神类', 1), " +
+                    "(0, 0, '玩平板游戏30分钟', 40, '特权类', 1), " +
+                    "(0, 0, '去游乐场', 100, '物质类', 1), " +
+                    "(0, 0, '买玩具', 150, '物质类', 1), " +
+                    "(0, 0, '吃冰淇淋', 20, '物质类', 1), " +
+                    "(0, 0, '选择晚餐', 25, '特权类', 1)");
                 log.info("预设奖励模板已初始化");
             }
         } catch (Exception e) {
-            log.warn("初始化预设奖励失�? {}", e.getMessage());
+            log.warn("初始化预设奖励失败: {}", e.getMessage());
         }
 
-        // 初始化奖励分�?        try {
+        // 初始化奖励分类
+        try {
             Integer count = jdbcTemplate.queryForObject(
                 "SELECT COUNT(*) FROM reward_categories WHERE family_id = 0", Integer.class);
             
             if (count == null || count == 0) {
                 jdbcTemplate.execute("INSERT INTO reward_categories (family_id, name, icon, sort_order) VALUES " +
-                    "(0, '物质�?, 'gift', 1), " +
-                    "(0, '精神�?, 'star', 2), " +
-                    "(0, '特权�?, 'crown', 3)");
+                    "(0, '物质类', 'gift', 1), " +
+                    "(0, '精神类', 'star', 2), " +
+                    "(0, '特权类', 'crown', 3)");
                 log.info("奖励分类已初始化");
             }
         } catch (Exception e) {
-            log.warn("初始化奖励分类失�? {}", e.getMessage());
+            log.warn("初始化奖励分类失败: {}", e.getMessage());
         }
 
         // 初始化打卡里程碑
@@ -346,27 +368,28 @@ public class DatabaseInitializer implements CommandLineRunner {
             if (count == null || count == 0) {
                 jdbcTemplate.execute("INSERT INTO streak_milestones (days, reward_points) VALUES " +
                     "(3, 5), (7, 10), (30, 30), (100, 100)");
-                log.info("打卡里程碑已初始�?);
+                log.info("打卡里程碑已初始化");
             }
         } catch (Exception e) {
             log.warn("初始化打卡里程碑失败: {}", e.getMessage());
         }
 
-        // 初始化勋章定�?        try {
+        // 初始化勋章定义
+        try {
             Integer count = jdbcTemplate.queryForObject(
                 "SELECT COUNT(*) FROM badge_definitions", Integer.class);
             
             if (count == null || count == 0) {
                 jdbcTemplate.execute("INSERT INTO badge_definitions (badge_type, name, description, icon, condition_type, condition_value, reward_points) VALUES " +
                     "('first_task', '初次完成任务', '首次完成任意任务', 'star', 'task_count', 1, 0), " +
-                    "('streak_3', '连续3�?, '连续3天按时完成任�?, 'fire', 'streak_days', 3, 5), " +
-                    "('streak_7', '连续7�?, '连续7天按时完成任�?, 'fire', 'streak_days', 7, 10), " +
-                    "('points_50', '积分达人', '一周获�?0积分', 'trophy', 'weekly_points', 50, 0), " +
-                    "('task_100', '任务达人', '完成100个任�?, 'medal', 'task_count', 100, 20)");
+                    "('streak_3', '连续3天', '连续3天按时完成任务', 'fire', 'streak_days', 3, 5), " +
+                    "('streak_7', '连续7天', '连续7天按时完成任务', 'fire', 'streak_days', 7, 10), " +
+                    "('points_50', '积分达人', '一周获得50积分', 'trophy', 'weekly_points', 50, 0), " +
+                    "('task_100', '任务达人', '完成100个任务', 'medal', 'task_count', 100, 20)");
                 log.info("勋章定义已初始化");
             }
         } catch (Exception e) {
-            log.warn("初始化勋章定义失�? {}", e.getMessage());
+            log.warn("初始化勋章定义失败: {}", e.getMessage());
         }
 
         // 初始化默认管理员
@@ -375,15 +398,14 @@ public class DatabaseInitializer implements CommandLineRunner {
                 "SELECT COUNT(*) FROM admins", Integer.class);
             
             if (count == null || count == 0) {
-                // 默认管理�? 手机�?13800138000, 密码 admin123
-                String encryptedPassword = org.springframework.util.DigestUtils.md5DigestAsHex("zxyj_admin_salt_admin123".getBytes());
+                // 默认管理员: 手机号 13800138000, 密码 admin123
+                String encryptedPassword = org.springframework.util.DigestUtils.md5DigestAsHex("xzyj_admin_salt_admin123".getBytes());
                 jdbcTemplate.execute("INSERT INTO admins (username, password, real_name, phone, email, status) VALUES " +
-                    "('admin', '" + encryptedPassword + "', '系统管理�?, '13800138000', 'admin@zxyj.com', 1)");
-                log.info("默认管理员已初始�? 手机�?13800138000, 密码 admin123");
+                    "('admin', '" + encryptedPassword + "', '系统管理员', '13800138000', 'admin@xzyj.com', 1)");
+                log.info("默认管理员已初始化: 手机号 13800138000, 密码 admin123");
             }
         } catch (Exception e) {
             log.warn("初始化默认管理员失败: {}", e.getMessage());
         }
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/config/JwtConfig.java

@@ -68,4 +68,3 @@ public class JwtConfig {
         return Long.parseLong(claims.getSubject());
     }
 }
-

+ 3 - 3
zxyj-backend/src/main/java/com/zxyj/config/JwtInterceptor.java

@@ -19,7 +19,7 @@ public class JwtInterceptor implements HandlerInterceptor {
 
     @Override
     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-        // �OPTIONS 请求
+        // 放 OPTIONS 请求
         if ("OPTIONS".equals(request.getMethod())) {
             return true;
         }
@@ -50,7 +50,8 @@ public class JwtInterceptor implements HandlerInterceptor {
             Long userId = Long.parseLong(claims.getSubject());
             String role = (String) claims.get("role");
 
-            // 将用户信�放入请求属�            request.setAttribute("userId", userId);
+            // 将用户信�放入请求属性
+            request.setAttribute("userId", userId);
             request.setAttribute("role", role);
 
             // 添加自定义请求头,供下游使用
@@ -66,4 +67,3 @@ public class JwtInterceptor implements HandlerInterceptor {
         }
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/config/MyBatisPlusConfig.java

@@ -16,4 +16,3 @@ public class MyBatisPlusConfig {
         return interceptor;
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/config/WebConfig.java

@@ -36,4 +36,3 @@ public class WebConfig implements WebMvcConfigurer {
                 );
     }
 }
-

+ 25 - 16
zxyj-backend/src/main/java/com/zxyj/controller/AdminAuthController.java

@@ -31,25 +31,29 @@ public class AdminAuthController {
     private JwtConfig jwtConfig;
 
     /**
-     * 发送管理员登录验证�?     */
+     * 发送管理员登录验证码
+     */
     @PostMapping("/send-code")
     public Result<Boolean> sendCode(@RequestBody SendCodeDTO dto) {
         if (dto.getPhone() == null || dto.getPhone().isEmpty()) {
-            return Result.error("手机号不能为�?);
+            return Result.error("手机号不能为空");
         }
         
-        // 验证手机号格�?        if (!dto.getPhone().matches("^1[3-9]\\d{9}$")) {
+        // 验证手机号格式
+        if (!dto.getPhone().matches("^1[3-9]\\d{9}$")) {
             return Result.error("手机号格式不正确");
         }
 
-        // 验证该手机号是否已注册为管理�?        Admin admin = adminMapper.selectOne(new LambdaQueryWrapper<Admin>()
+        // 验证该手机号是否已注册为管理员
+        Admin admin = adminMapper.selectOne(new LambdaQueryWrapper<Admin>()
                 .eq(Admin::getPhone, dto.getPhone()));
         
         if (admin == null) {
-            return Result.error("该手机号未注册为管理�?);
+            return Result.error("该手机号未注册为管理员");
         }
 
-        // 生成验证�?        verificationCodeService.generateCode(dto.getPhone(), "admin_login");
+        // 生成验证码
+        verificationCodeService.generateCode(dto.getPhone(), "admin_login");
         return Result.success(true);
     }
 
@@ -59,15 +63,17 @@ public class AdminAuthController {
     @PostMapping("/login")
     public Result<Map<String, Object>> login(@RequestBody AdminLoginDTO dto) {
         if (dto.getPhone() == null || dto.getCode() == null) {
-            return Result.error("手机号和验证码不能为�?);
+            return Result.error("手机号和验证码不能为空");
         }
 
-        // 验证验证�?        boolean valid = verificationCodeService.verifyCode(dto.getPhone(), dto.getCode(), "admin_login");
+        // 验证验证码
+        boolean valid = verificationCodeService.verifyCode(dto.getPhone(), dto.getCode(), "admin_login");
         if (!valid) {
-            return Result.error("验证码错误或已过�?);
+            return Result.error("验证码错误或已过期");
         }
 
-        // 查询管理�?        Admin admin = adminMapper.selectOne(new LambdaQueryWrapper<Admin>()
+        // 查询管理员
+        Admin admin = adminMapper.selectOne(new LambdaQueryWrapper<Admin>()
                 .eq(Admin::getPhone, dto.getPhone()));
 
         if (admin == null) {
@@ -91,7 +97,8 @@ public class AdminAuthController {
     }
 
     /**
-     * 获取当前登录管理员信�?     */
+     * 获取当前登录管理员信息
+     */
     @GetMapping("/info")
     public Result<Admin> getAdminInfo(@RequestHeader("X-User-Id") Long adminId) {
         Admin admin = adminMapper.selectById(adminId);
@@ -104,7 +111,8 @@ public class AdminAuthController {
     }
 
     /**
-     * 管理员修改密�?     */
+     * 管理员修改密码
+     */
     @PostMapping("/change-password")
     public Result<Boolean> changePassword(@RequestHeader("X-User-Id") Long adminId,
                                            @RequestBody Map<String, String> params) {
@@ -116,9 +124,10 @@ public class AdminAuthController {
             return Result.error("管理员不存在");
         }
 
-        // 验证旧密�?        String encryptedOldPassword = encryptPassword(oldPassword);
+        // 验证旧密码
+        String encryptedOldPassword = encryptPassword(oldPassword);
         if (!encryptedOldPassword.equals(admin.getPassword())) {
-            return Result.error("原密码错�?);
+            return Result.error("原密码错误");
         }
 
         // 更新密码
@@ -130,7 +139,7 @@ public class AdminAuthController {
     }
 
     private String encryptPassword(String password) {
-        // MD5加密,实际项目应使用BCrypt等更安全的加密方�?        return org.springframework.util.DigestUtils.md5DigestAsHex(("zxyj_admin_salt_" + password).getBytes());
+        // MD5加密,实际项目应使用BCrypt等更安全的加密方式
+        return org.springframework.util.DigestUtils.md5DigestAsHex(("xzyj_admin_salt_" + password).getBytes());
     }
 }
-

+ 5 - 5
zxyj-backend/src/main/java/com/zxyj/controller/AdminController.java

@@ -90,7 +90,7 @@ public class AdminController {
 
         Child child = childMapper.selectById(id);
         if (child == null) {
-            return Result.error("孩��存�);
+            return Result.error("孩��存在");
         }
 
         int newBalance = child.getTotalPoints() + amount;
@@ -186,7 +186,7 @@ public class AdminController {
         Boolean approved = params.get("approved");
         Reward reward = rewardMapper.selectById(id);
         if (reward == null) {
-            return Result.error("奖励�存�);
+            return Result.error("奖励�存在");
         }
 
         if (approved) {
@@ -194,7 +194,8 @@ public class AdminController {
             reward.setExchangeApproved(1);
             reward.setExchangedAt(new Date());
         } else {
-            // 拒�,返还积�            Child child = childMapper.selectById(reward.getChildId());
+            // 拒�,返还积分
+            Child child = childMapper.selectById(reward.getChildId());
             if (child != null) {
                 child.setTotalPoints(child.getTotalPoints() + reward.getPointsRequired());
                 childMapper.updateById(child);
@@ -203,7 +204,7 @@ public class AdminController {
                 log.setChildId(reward.getChildId());
                 log.setAmount(reward.getPointsRequired());
                 log.setType("refund");
-                log.setDescription("奖励兑�被拒�,积分退�);
+                log.setDescription("奖励兑�被拒�,积分退还");
                 log.setCreatedAt(new Date());
                 pointsLogMapper.insert(log);
             }
@@ -247,4 +248,3 @@ public class AdminController {
         return Result.success(stats);
     }
 }
-

+ 13 - 9
zxyj-backend/src/main/java/com/zxyj/controller/AuthController.java

@@ -26,9 +26,10 @@ public class AuthController {
     @PostMapping("/send-code")
     public Result<Boolean> sendCode(@RequestBody SendCodeDTO dto) {
         if (dto.getPhone() == null || dto.getPhone().isEmpty()) {
-            return Result.error("手机号不能为��?);
+            return Result.error("手机号不能为空");
         }
-        // 验证手机号格å¼?        if (!dto.getPhone().matches("^1[3-9]\\d{9}$")) {
+        // 验证手机号格式
+        if (!dto.getPhone().matches("^1[3-9]\\d{9}$")) {
             return Result.error("手机号格式不正确");
         }
         verificationCodeService.generateCode(dto.getPhone(), dto.getType());
@@ -41,11 +42,12 @@ public class AuthController {
     @PostMapping("/phone-login")
     public Result<LoginResultDTO> phoneLogin(@RequestBody PhoneLoginDTO dto) {
         if (dto.getPhone() == null || dto.getCode() == null) {
-            return Result.error("手机号和验证码不能为��?);
+            return Result.error("手机号和验证码不能为空");
         }
-        // 验证验证ç ?        boolean valid = verificationCodeService.verifyCode(dto.getPhone(), dto.getCode(), "login");
+        // 验证验证码
+        boolean valid = verificationCodeService.verifyCode(dto.getPhone(), dto.getCode(), "login");
         if (!valid) {
-            return Result.error("验证码错误或已过��?);
+            return Result.error("验证码错误或已过期");
         }
         // 执行登录
         LoginResultDTO result = userService.phoneLogin(dto);
@@ -53,11 +55,14 @@ public class AuthController {
     }
 
     /**
-     * 微信手机号登录(通过微信开放能力获取手机号ï¼?     */
+     * 微信手机号登录(通过微信开放能力获取手机号)
+     */
     @PostMapping("/wechat-phone-login")
     public Result<LoginResultDTO> wechatPhoneLogin(@RequestBody WechatPhoneLoginDTO dto) {
-        // TODO: 调用微信API解密获取手机å�?        // 这里需要集成微信手机号解密功能
-        // 暂时使用模拟数据,实际需要通过微信code获取手机å�?        String phone = "mock_phone_" + dto.getCode();
+        // TODO: 调用微信API解密获取手机号
+        // 这里需要集成微信手机号解密功能
+        // 暂时使用模拟数据,实际需要通过微信code获取手机号
+        String phone = "mock_phone_" + dto.getCode();
         
         PhoneLoginDTO phoneLoginDTO = new PhoneLoginDTO();
         phoneLoginDTO.setPhone(phone);
@@ -105,4 +110,3 @@ public class AuthController {
         return null;
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/controller/PointsController.java

@@ -40,4 +40,3 @@ public class PointsController {
         return Result.success(result);
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/controller/RewardController.java

@@ -61,4 +61,3 @@ public class RewardController {
         return Result.success(history);
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/controller/TaskController.java

@@ -63,4 +63,3 @@ public class TaskController {
         return Result.success(success);
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/controller/UserController.java

@@ -69,4 +69,3 @@ public class UserController {
         return Result.success(success);
     }
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/dto/AdminLoginDTO.java

@@ -7,4 +7,3 @@ public class AdminLoginDTO {
     private String phone;
     private String code;
 }
-

+ 0 - 31
zxyj-backend/src/main/java/com/zxyj/dto/AuthDTO.java

@@ -1,31 +0,0 @@
-package com.zxyj.dto;
-
-import lombok.Data;
-
-@Data
-public class WechatLoginDTO {
-    private String code;
-    private String userInfo;
-    private String nickname;
-    private String avatar;
-}
-
-@Data
-public class SetPasswordDTO {
-    private String password;
-}
-
-@Data
-public class VerifyPasswordDTO {
-    private String password;
-}
-
-@Data
-public class LoginResultDTO {
-    private String token;
-    private Long userId;
-    private String role;
-    private Long familyId;
-    private String nickname;
-}
-

+ 0 - 17
zxyj-backend/src/main/java/com/zxyj/dto/ChildDTO.java → zxyj-backend/src/main/java/com/zxyj/dto/ChildInfoDTO.java

@@ -2,22 +2,6 @@ package com.zxyj.dto;
 
 import lombok.Data;
 
-@Data
-public class CreateChildDTO {
-    private String nickname;
-    private Integer age;
-    private String danLevel;
-}
-
-@Data
-public class UpdateChildDTO {
-    private String nickname;
-    private Integer age;
-    private String danLevel;
-    private Integer penaltyEnabled;
-    private String theme;
-}
-
 @Data
 public class ChildInfoDTO {
     private Long id;
@@ -30,4 +14,3 @@ public class ChildInfoDTO {
     private Integer streakDays;
     private Integer focusRemaining;
 }
-

+ 9 - 0
zxyj-backend/src/main/java/com/zxyj/dto/CompleteTaskDTO.java

@@ -0,0 +1,9 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class CompleteTaskDTO {
+    private String photoUrl;
+    private String voiceNoteUrl;
+}

+ 10 - 0
zxyj-backend/src/main/java/com/zxyj/dto/CreateChildDTO.java

@@ -0,0 +1,10 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class CreateChildDTO {
+    private String nickname;
+    private Integer age;
+    private String danLevel;
+}

+ 11 - 0
zxyj-backend/src/main/java/com/zxyj/dto/CreateRewardDTO.java

@@ -0,0 +1,11 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class CreateRewardDTO {
+    private String title;
+    private Integer pointsRequired;
+    private String category;
+    private Long childId;
+}

+ 0 - 14
zxyj-backend/src/main/java/com/zxyj/dto/TaskDTO.java → zxyj-backend/src/main/java/com/zxyj/dto/CreateTaskDTO.java

@@ -16,17 +16,3 @@ public class CreateTaskDTO {
     private Integer reviewByCategory;
     private Long childId;
 }
-
-@Data
-public class CompleteTaskDTO {
-    private String photoUrl;
-    private String voiceNoteUrl;
-}
-
-@Data
-public class TaskReviewDTO {
-    private String result;
-    private String aiSuggestion;
-    private Boolean overrideAi;
-}
-

+ 12 - 0
zxyj-backend/src/main/java/com/zxyj/dto/LoginResultDTO.java

@@ -0,0 +1,12 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class LoginResultDTO {
+    private String token;
+    private Long userId;
+    private String role;
+    private Long familyId;
+    private String nickname;
+}

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/dto/PhoneLoginDTO.java

@@ -9,4 +9,3 @@ public class PhoneLoginDTO {
     private String nickname;
     private String avatar;
 }
-

+ 0 - 9
zxyj-backend/src/main/java/com/zxyj/dto/RewardDTO.java

@@ -2,14 +2,6 @@ package com.zxyj.dto;
 
 import lombok.Data;
 
-@Data
-public class CreateRewardDTO {
-    private String title;
-    private Integer pointsRequired;
-    private String category;
-    private Long childId;
-}
-
 @Data
 public class RewardDTO {
     private Long id;
@@ -20,4 +12,3 @@ public class RewardDTO {
     private Integer exchangeApproved;
     private Integer progress;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/dto/SendCodeDTO.java

@@ -7,4 +7,3 @@ public class SendCodeDTO {
     private String phone;
     private String type;
 }
-

+ 8 - 0
zxyj-backend/src/main/java/com/zxyj/dto/SetPasswordDTO.java

@@ -0,0 +1,8 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class SetPasswordDTO {
+    private String password;
+}

+ 12 - 0
zxyj-backend/src/main/java/com/zxyj/dto/TaskReviewDTO.java

@@ -0,0 +1,12 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class TaskReviewDTO {
+    private String result;
+    private String aiSuggestion;
+    private Boolean overrideAi;
+}

+ 12 - 0
zxyj-backend/src/main/java/com/zxyj/dto/UpdateChildDTO.java

@@ -0,0 +1,12 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class UpdateChildDTO {
+    private String nickname;
+    private Integer age;
+    private String danLevel;
+    private Integer penaltyEnabled;
+    private String theme;
+}

+ 8 - 0
zxyj-backend/src/main/java/com/zxyj/dto/VerifyPasswordDTO.java

@@ -0,0 +1,8 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class VerifyPasswordDTO {
+    private String password;
+}

+ 11 - 0
zxyj-backend/src/main/java/com/zxyj/dto/WechatLoginDTO.java

@@ -0,0 +1,11 @@
+package com.zxyj.dto;
+
+import lombok.Data;
+
+@Data
+public class WechatLoginDTO {
+    private String code;
+    private String userInfo;
+    private String nickname;
+    private String avatar;
+}

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/dto/WechatPhoneLoginDTO.java

@@ -10,4 +10,3 @@ public class WechatPhoneLoginDTO {
     private String nickname;
     private String avatar;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/Admin.java

@@ -30,4 +30,3 @@ public class Admin {
 
     private Date updatedAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/Child.java

@@ -45,4 +45,3 @@ public class Child implements Serializable {
 
     private Date updatedAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/Family.java

@@ -23,4 +23,3 @@ public class Family implements Serializable {
 
     private Date updatedAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/PointsLog.java

@@ -27,4 +27,3 @@ public class PointsLog implements Serializable {
 
     private Date createdAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/Reward.java

@@ -37,4 +37,3 @@ public class Reward implements Serializable {
 
     private Date updatedAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/Task.java

@@ -45,4 +45,3 @@ public class Task implements Serializable {
 
     private Date updatedAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/User.java

@@ -33,4 +33,3 @@ public class User implements Serializable {
 
     private Date updatedAt;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/entity/VerificationCode.java

@@ -28,4 +28,3 @@ public class VerificationCode {
 
     private Integer used;
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/AdminMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface AdminMapper extends BaseMapper<Admin> {
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/ChildMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface ChildMapper extends BaseMapper<Child> {
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/FamilyMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface FamilyMapper extends BaseMapper<Family> {
 }
-

+ 7 - 2
zxyj-backend/src/main/java/com/zxyj/mapper/PointsLogMapper.java

@@ -1,10 +1,15 @@
 package com.zxyj.mapper;
 
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.zxyj.entity.PointsLog;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 @Mapper
 public interface PointsLogMapper extends BaseMapper<PointsLog> {
-}
-
+    
+    @Select("SELECT COALESCE(SUM(points), 0) FROM points_log ${'$'}{ew.customSqlSegment}")
+    Integer selectSum(@Param("ew") LambdaQueryWrapper<PointsLog> wrapper);
+}

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/RewardMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface RewardMapper extends BaseMapper<Reward> {
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/TaskMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface TaskMapper extends BaseMapper<Task> {
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/UserMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface UserMapper extends BaseMapper<User> {
 }
-

+ 0 - 1
zxyj-backend/src/main/java/com/zxyj/mapper/VerificationCodeMapper.java

@@ -7,4 +7,3 @@ import org.apache.ibatis.annotations.Mapper;
 @Mapper
 public interface VerificationCodeMapper extends BaseMapper<VerificationCode> {
 }
-

+ 4 - 3
zxyj-backend/src/main/java/com/zxyj/service/PointsService.java

@@ -31,7 +31,8 @@ public class PointsService {
 
         Map<String, Object> result = new HashMap<>();
         result.put("balance", child.getTotalPoints());
-        // 下个æœ?æ—?ç‚?        java.util.Calendar cal = java.util.Calendar.getInstance();
+        // 下个月1日0点
+        java.util.Calendar cal = java.util.Calendar.getInstance();
         cal.set(java.util.Calendar.DAY_OF_MONTH, 1);
         cal.set(java.util.Calendar.HOUR_OF_DAY, 0);
         cal.set(java.util.Calendar.MINUTE, 0);
@@ -50,7 +51,8 @@ public class PointsService {
 
     @Transactional
     public Map<String, Object> adjustPoints(Long childId, Integer amount, String reason, String password, Long userId) {
-        // 验证密码(简化版,实际应从数据库验证ï¼?        // 这里需要调用UserService验证密码
+        // 验证密码(简化版,实际应从数据库验证)
+        // 这里需要调用UserService验证密码
         
         Child child = childMapper.selectById(childId);
         if (child == null) {
@@ -83,4 +85,3 @@ public class PointsService {
         return result;
     }
 }
-

+ 12 - 6
zxyj-backend/src/main/java/com/zxyj/service/RewardService.java

@@ -14,8 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 @Service
@@ -92,7 +94,8 @@ public class RewardService {
         child.setUpdatedAt(new Date());
         childMapper.updateById(child);
 
-        // 记录积分消�        PointsLog log = new PointsLog();
+        // 记录积分消耗
+        PointsLog log = new PointsLog();
         log.setChildId(childId);
         log.setAmount(-reward.getPointsRequired());
         log.setType("spend");
@@ -100,7 +103,9 @@ public class RewardService {
         log.setCreatedAt(new Date());
         pointsLogMapper.insert(log);
 
-        // 更新奖励状�        reward.setStatus("pending"); // 待审�        reward.setUpdatedAt(new Date());
+        // 更新奖励状�
+        reward.setStatus("pending"); // 待审批
+        reward.setUpdatedAt(new Date());
         rewardMapper.updateById(reward);
 
         Map<String, Object> result = new java.util.HashMap<>();
@@ -121,16 +126,18 @@ public class RewardService {
             reward.setExchangeApproved(1);
             reward.setExchangedAt(new Date());
         } else {
-            // 拒�,返还积�            Child child = childMapper.selectById(reward.getChildId());
+            // 拒�,返还积分
+            Child child = childMapper.selectById(reward.getChildId());
             child.setTotalPoints(child.getTotalPoints() + reward.getPointsRequired());
             child.setUpdatedAt(new Date());
             childMapper.updateById(child);
 
-            // 记录积分退�            PointsLog log = new PointsLog();
+            // 记录积分退还
+            PointsLog log = new PointsLog();
             log.setChildId(reward.getChildId());
             log.setAmount(reward.getPointsRequired());
             log.setType("refund");
-            log.setDescription("奖励兑�被拒�,积分退�);
+            log.setDescription("奖励兑�被拒�,积分退还");
             log.setCreatedAt(new Date());
             pointsLogMapper.insert(log);
 
@@ -155,4 +162,3 @@ public class RewardService {
                 .orderByDesc(Reward::getExchangedAt));
     }
 }
-

+ 20 - 11
zxyj-backend/src/main/java/com/zxyj/service/TaskService.java

@@ -28,7 +28,9 @@ public class TaskService {
     private UserService userService;
 
     private static final int EARLY_BONUS = 1;       // ��完�奖励
-    private static final int PENALTY_MAX_DAILY = 5; // �日最多扣�    private static final int LATE_GRACE_MINUTES = 10; // 10分钟内�算迟�
+    private static final int PENALTY_MAX_DAILY = 5; // �日最多扣分
+    private static final int LATE_GRACE_MINUTES = 10; // 10分钟内�算迟到
+
     @Transactional
     public Long createTask(Long userId, CreateTaskDTO dto) {
         Task task = new Task();
@@ -95,11 +97,13 @@ public class TaskService {
         
         // 计算积分
         if (isEarly || isLateGrace) {
-            // ��完�或宽�期内完�,获得基础�+ ��奖励
+            // ��完�或宽�期内完�,获得基础分 + ��奖励
             pointsEarned += EARLY_BONUS;
         } else {
-            // 超时,检查是�开�扣�            if (child.getPenaltyEnabled() != null && child.getPenaltyEnabled() == 1) {
-                // 检查今日已扣分�                Calendar cal = Calendar.getInstance();
+            // 超时,检查是�开�扣分
+            if (child.getPenaltyEnabled() != null && child.getPenaltyEnabled() == 1) {
+                // 检查今日已扣分数
+                Calendar cal = Calendar.getInstance();
                 cal.set(Calendar.HOUR_OF_DAY, 0);
                 cal.set(Calendar.MINUTE, 0);
                 cal.set(Calendar.SECOND, 0);
@@ -120,10 +124,12 @@ public class TaskService {
                     pointsEarned = 0; // 达到�日扣分上�
                 }
             } else {
-                pointsEarned = 0; // 扣分未开�            }
+                pointsEarned = 0; // 扣分未开�
+            }
         }
 
-        // 更新任务状�        task.setStatus("completed");
+        // 更新任务状�
+        task.setStatus("completed");
         task.setCompletedAt(now);
         task.setUpdatedAt(new Date());
         taskMapper.updateById(task);
@@ -139,8 +145,10 @@ public class TaskService {
         Date yesterday = cal.getTime();
         
         if (lastTaskDate == null || lastTaskDate.before(yesterday)) {
-            child.setStreakDays(1); // �新开�        } else if (lastTaskDate != null && isSameDay(lastTaskDate, today)) {
-            // 今天已�完�过任务,�增加天�        } else {
+            child.setStreakDays(1); // �新开始
+        } else if (lastTaskDate != null && isSameDay(lastTaskDate, today)) {
+            // 今天已�完�过任务,�增加天数
+        } else {
             child.setStreakDays(child.getStreakDays() + 1);
         }
         child.setLastTaskDate(today);
@@ -177,10 +185,12 @@ public class TaskService {
             return false;
         }
 
-        // 更新任务状�        if ("pass".equals(dto.getResult())) {
+        // 更新任务状�
+        if ("pass".equals(dto.getResult())) {
             task.setStatus("completed");
         } else {
-            task.setStatus("pending"); // 审核�通过,任务��        }
+            task.setStatus("pending"); // 审核�通过,任务�置
+        }
         task.setUpdatedAt(new Date());
         taskMapper.updateById(task);
 
@@ -214,4 +224,3 @@ public class TaskService {
                 && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR);
     }
 }
-

+ 7 - 5
zxyj-backend/src/main/java/com/zxyj/service/UserService.java

@@ -42,7 +42,8 @@ public class UserService {
                 .eq(User::getOpenid, openid));
 
         if (user == null) {
-            // 新用户,创建家庭和用�?            Family family = new Family();
+            // 新用户,创建家庭和用户
+            Family family = new Family();
             family.setName("我的家庭");
             family.setInviteCode(generateInviteCode());
             family.setCreatedAt(new Date());
@@ -87,7 +88,8 @@ public class UserService {
                 .eq(User::getOpenid, "phone:" + phone));
 
         if (user == null) {
-            // 新用户,创建家庭和用�?            Family family = new Family();
+            // 新用户,创建家庭和用户
+            Family family = new Family();
             family.setName("我的家庭");
             family.setInviteCode(generateInviteCode());
             family.setCreatedAt(new Date());
@@ -166,7 +168,8 @@ public class UserService {
         child.setNickname(dto.getNickname());
         child.setAge(dto.getAge());
         child.setDanLevel(dto.getDanLevel());
-        // 根据年龄设置扣分开关:6岁以下默认关闭,6岁及以上默认开�?        child.setPenaltyEnabled(dto.getAge() >= 6 ? 1 : 0);
+        // 根据年龄设置扣分开关:6岁以下默认关闭,6岁及以上默认开启
+        child.setPenaltyEnabled(dto.getAge() >= 6 ? 1 : 0);
         child.setTheme("default");
         child.setTotalPoints(0);
         child.setStreakDays(0);
@@ -219,7 +222,7 @@ public class UserService {
     }
 
     private String encryptPassword(String password) {
-        return DigestUtils.md5DigestAsHex(("zxyj_salt_" + password).getBytes(StandardCharsets.UTF_8));
+        return DigestUtils.md5DigestAsHex(("xzyj_salt_" + password).getBytes(StandardCharsets.UTF_8));
     }
 
     private String generateInviteCode() {
@@ -240,4 +243,3 @@ public class UserService {
         return dto;
     }
 }
-

+ 16 - 10
zxyj-backend/src/main/java/com/zxyj/service/VerificationCodeService.java

@@ -21,11 +21,14 @@ public class VerificationCodeService {
     private static final int VALID_MINUTES = 5;
 
     /**
-     * ���撉諹��?     */
+     * ���撉諹���
+     */
     public String generateCode(String phone, String type) {
-        // ���6雿漤��箸㺭摮?        String code = generateRandomCode();
+        // ���6雿漤��箸㺭摮�
+        String code = generateRandomCode();
         
-        // ����方砲�𧢲㦤�瑚��滨�撉諹��?        verificationCodeMapper.delete(new LambdaQueryWrapper<VerificationCode>()
+        // ����方砲�𧢲㦤�瑚��滨�撉諹���
+        verificationCodeMapper.delete(new LambdaQueryWrapper<VerificationCode>()
                 .eq(VerificationCode::getPhone, phone)
                 .eq(VerificationCode::getType, type));
 
@@ -41,13 +44,14 @@ public class VerificationCodeService {
         verificationCodeMapper.insert(verificationCode);
 
         // TODO: 靚�鍂�凋縑撟喳蝱�煾���霂��
-        log.info("���撉諹��? phone={}, code={}, type={}", phone, code, type);
+        log.info("���撉諹���: phone={}, code={}, type={}", phone, code, type);
         
         return code;
     }
 
     /**
-     * 撉諹�撉諹��?     */
+     * 撉諹�撉諹���
+     */
     public boolean verifyCode(String phone, String code, String type) {
         VerificationCode verificationCode = verificationCodeMapper.selectOne(
                 new LambdaQueryWrapper<VerificationCode>()
@@ -62,7 +66,8 @@ public class VerificationCodeService {
             return false;
         }
 
-        // 璉��交糓�西��?        if (verificationCode.getExpiresAt().before(new Date())) {
+        // 璉��交糓�西���
+        if (verificationCode.getExpiresAt().before(new Date())) {
             log.warn("撉諹���歇餈��: phone={}", phone);
             return false;
         }
@@ -71,12 +76,13 @@ public class VerificationCodeService {
         verificationCode.setUsed(1);
         verificationCodeMapper.updateById(verificationCode);
 
-        log.info("撉諹����霂���? phone={}", phone);
+        log.info("撉諹����霂����: phone={}", phone);
         return true;
     }
 
     /**
-     * 璉��仿�霂���臬炏�㗇�嚗����扇銝箏歇雿輻鍂嚗?     */
+     * 璉��仿�霂���臬炏�㗇�嚗����扇銝箏歇雿輻鍂嚗�
+     */
     public boolean checkCodeValid(String phone, String code, String type) {
         VerificationCode verificationCode = verificationCodeMapper.selectOne(
                 new LambdaQueryWrapper<VerificationCode>()
@@ -90,7 +96,8 @@ public class VerificationCodeService {
             return false;
         }
 
-        // 璉��交糓�西��?        return !verificationCode.getExpiresAt().before(new Date());
+        // 璉��交糓�西���
+        return !verificationCode.getExpiresAt().before(new Date());
     }
 
     /**
@@ -105,4 +112,3 @@ public class VerificationCodeService {
         return code.toString();
     }
 }
-