Эх сурвалжийг харах

feat: 添加Service接口规范(TaskService,RewardService,UserService)

User 4 сар өмнө
parent
commit
a1a3ca4515

+ 87 - 0
zxyj-backend/src/main/java/com/zxyj/controller/guide/GuideRecordController.java

@@ -0,0 +1,87 @@
+package com.zxyj.controller.guide;
+
+import com.zxyj.common.Result;
+import com.zxyj.entity.AssessmentResult;
+import com.zxyj.entity.DanAssessmentResult;
+import com.zxyj.service.AssessmentPermissionService;
+import com.zxyj.service.AssessmentService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+@Tag(name = "成长规划师记录", description = "成长规划师录入测评结果(含孩子快照)")
+@RestController
+@RequestMapping("/api/guide/record")
+public class GuideRecordController {
+
+    @Resource
+    private AssessmentService assessmentService;
+
+    @Resource
+    private AssessmentPermissionService assessmentPermissionService;
+
+    @Operation(summary = "录入测评结果(含孩子快照)")
+    @PostMapping("/create")
+    public Result<AssessmentResult> createRecord(
+            @RequestAttribute("userId") Long userId,
+            @RequestAttribute("role") String role,
+            @RequestBody AssessmentResult result) {
+        if (!"teacher".equals(role)) {
+            return Result.error("只有成长规划师可以录入测评结果");
+        }
+        result.setTeacherId(userId);
+        result.setStatus("completed");
+        result.setCreatedAt(new Date());
+        result.setUpdatedAt(new Date());
+        if (result.getAssessmentDate() == null) {
+            result.setAssessmentDate(new Date());
+        }
+        AssessmentResult saved = assessmentService.recordResult(result);
+        return Result.success(saved);
+    }
+
+    @Operation(summary = "查询我的测评记录列表")
+    @PostMapping("/my-records")
+    public Result<List<AssessmentResult>> getMyRecords(@RequestAttribute("userId") Long userId) {
+        List<AssessmentResult> results = assessmentService.getResultsByGuide(userId);
+        return Result.success(results);
+    }
+
+    @Operation(summary = "获取测评记录详情")
+    @PostMapping("/detail/{id}")
+    public Result<AssessmentResult> getRecordDetail(
+            @RequestAttribute("userId") Long userId,
+            @RequestAttribute("role") String role,
+            @PathVariable Long id) {
+        if (!assessmentPermissionService.canViewAssessment(userId, id)) {
+            return Result.error("无权查看该记录");
+        }
+        DanAssessmentResult danResult = assessmentPermissionService.getAssessmentById(id);
+        if (danResult == null) {
+            return Result.error("记录不存在");
+        }
+        AssessmentResult result = new AssessmentResult();
+        result.setId(danResult.getId());
+        result.setChildId(danResult.getChildId());
+        result.setTeacherId(danResult.getTeacherId());
+        result.setAppointmentId(danResult.getAppointmentId());
+        result.setDanLevel(danResult.getDanLevel());
+        result.setAttentionScore(danResult.getAttentionScore());
+        result.setFocusScore(danResult.getFocusScore());
+        result.setMemoryScore(danResult.getMemoryScore());
+        result.setLogicScore(danResult.getLogicScore());
+        result.setOverallScore(danResult.getOverallScore());
+        result.setAssessmentDate(danResult.getAssessmentDate());
+        result.setDurationMinutes(danResult.getDurationMinutes());
+        result.setAnalysisReport(danResult.getAnalysisReport());
+        result.setGrowthSuggestions(danResult.getGrowthSuggestions());
+        result.setNextReviewDate(danResult.getNextReviewDate());
+        result.setStatus(danResult.getStatus());
+        result.setCreatedAt(danResult.getCreatedAt());
+        return Result.success(result);
+    }
+}

+ 4 - 0
zxyj-backend/src/main/java/com/zxyj/entity/AssessmentAppointment.java

@@ -21,6 +21,10 @@ public class AssessmentAppointment implements Serializable {
 
     private Long childId;
 
+    private Long guideId;
+
+    private Long packageId;
+
     private Date appointmentDate;
 
     private Date appointmentTime;

+ 35 - 0
zxyj-backend/src/main/java/com/zxyj/entity/AssessmentOrder.java

@@ -0,0 +1,35 @@
+package com.zxyj.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("assessment_orders")
+public class AssessmentOrder implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private String orderNo;
+    private Long familyId;
+    private Long userId;
+    private Long childId;
+    private Long guideId;
+    private Long packageId;
+    private String guideName;
+    private String packageName;
+    private Long totalPrice;
+    private Long discountAmount;
+    private Long actualPrice;
+    private String status; // pending/paid/cancelled/refunded
+    private String payTime;
+    private String payType; // wechat/alipay
+    private String transactionId;
+    private Date createdAt;
+    private Date updatedAt;
+}

+ 67 - 0
zxyj-backend/src/main/java/com/zxyj/entity/AssessmentResult.java

@@ -0,0 +1,67 @@
+package com.zxyj.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+@TableName("assessment_results")
+public class AssessmentResult implements Serializable {
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    private Long childId;
+    private Long teacherId;
+    private Long appointmentId;
+    private String danLevel;
+    private Integer attentionScore;
+    private Integer focusScore;
+    private Integer memoryScore;
+    private Integer logicScore;
+    private Integer overallScore;
+    private Date assessmentDate;
+    private Integer durationMinutes;
+    private String analysisReport;
+    private String growthSuggestions;
+    private Date nextReviewDate;
+    private String status;
+    private Date createdAt;
+    private Date updatedAt;
+
+    // 孩子快照字段
+    private String childName;
+    private Date childBirthday;
+    private String childGender;
+    private Integer childAge;
+    private String school;
+    private String grade;
+    private String gradeClass;
+    private Integer height;
+    private Integer weight;
+    private String familyStatus;
+    private String parentDegree;
+    private String nation;
+    private String province;
+    private String city;
+    private String district;
+    private String address;
+    private String singleChild;
+    private String schoolScore;
+    private String urgentName;
+    private String urgentPhone;
+
+    // 媒体字段
+    private String pics;
+    private String videos;
+    private String audio;
+    private String audioUrl;
+
+    // 扩展字段
+    private String processDesc;
+    private String resultDesc;
+}

+ 33 - 1
zxyj-backend/src/main/java/com/zxyj/entity/DanAssessmentResult.java

@@ -45,9 +45,41 @@ public class DanAssessmentResult implements Serializable {
 
     private Date nextReviewDate;  // 下次复测日期
 
-    private String status;  // draft/completed/archived
+    private String status; // draft/completed/archived
 
     private Date createdAt;
 
     private Date updatedAt;
+
+    // === 孩子快照字段(每次测评时快照,存当时的值) ===
+    private String childName; // 孩子姓名
+    private Date childBirthday; // 出生日期
+    private String childGender; // 性别
+    private Integer childAge; // 年龄(快照时计算)
+    private String school; // 学校
+    private String grade; // 年级
+    private String gradeClass; // 班级
+    private Integer height; // 身高(CM)
+    private Integer weight; // 体重(KG)
+    private String familyStatus; // 家庭状况
+    private String parentDegree; // 父母最高学历
+    private String nation; // 民族
+    private String province; // 省
+    private String city; // 市
+    private String district; // 区
+    private String address; // 详细地址
+    private String singleChild; // 是否独生子女 (0=是, 1=否)
+    private String schoolScore; // 在校成绩
+    private String urgentName; // 紧急联系人姓名
+    private String urgentPhone; // 紧急联系人电话
+
+    // === 媒体字段 ===
+    private String pics; // 图片 IDs(逗号分隔)
+    private String videos; // 视频 IDs(逗号分隔)
+    private String audio; // 音频 ID
+    private String audioUrl; // 音频访问URL
+
+    // === 扩展字段 ===
+    private String processDesc; // 过程描述
+    private String resultDesc; // 结果描述(简评)
 }

+ 9 - 0
zxyj-backend/src/main/java/com/zxyj/mapper/AssessmentOrderMapper.java

@@ -0,0 +1,9 @@
+package com.zxyj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zxyj.entity.AssessmentOrder;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AssessmentOrderMapper extends BaseMapper<AssessmentOrder> {
+}

+ 9 - 0
zxyj-backend/src/main/java/com/zxyj/mapper/AssessmentResultMapper.java

@@ -0,0 +1,9 @@
+package com.zxyj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.zxyj.entity.AssessmentResult;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface AssessmentResultMapper extends BaseMapper<AssessmentResult> {
+}

+ 84 - 0
zxyj-backend/src/main/java/com/zxyj/service/AssessmentOrderService.java

@@ -0,0 +1,84 @@
+package com.zxyj.service;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zxyj.entity.AssessmentOrder;
+import com.zxyj.mapper.AssessmentOrderMapper;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Random;
+
+@Service
+public class AssessmentOrderService extends ServiceImpl<AssessmentOrderMapper, AssessmentOrder> {
+
+    @Resource
+    private AssessmentOrderMapper assessmentOrderMapper;
+
+    public AssessmentOrder createOrder(Long familyId, Long userId, Long childId,
+                                       Long guideId, Long packageId,
+                                       String guideName, String packageName,
+                                       Long totalPrice, Long discountAmount) {
+        AssessmentOrder order = new AssessmentOrder();
+        order.setOrderNo(generateOrderNo());
+        order.setFamilyId(familyId);
+        order.setUserId(userId);
+        order.setChildId(childId);
+        order.setGuideId(guideId);
+        order.setPackageId(packageId);
+        order.setGuideName(guideName);
+        order.setPackageName(packageName);
+        order.setTotalPrice(totalPrice);
+        order.setDiscountAmount(discountAmount != null ? discountAmount : 0L);
+        order.setActualPrice(totalPrice - (discountAmount != null ? discountAmount : 0L));
+        order.setStatus("pending");
+        order.setCreatedAt(new Date());
+        order.setUpdatedAt(new Date());
+        this.save(order);
+        return order;
+    }
+
+    private String generateOrderNo() {
+        return "A" + System.currentTimeMillis() + String.format("%04d", new Random().nextInt(10000));
+    }
+
+    public boolean paySuccess(String orderNo, String transactionId, String payType) {
+        LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        AssessmentOrder order = this.getOne(wrapper);
+        if (order == null) return false;
+        order.setStatus("paid");
+        order.setPayTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
+        order.setPayType(payType);
+        order.setTransactionId(transactionId);
+        order.setUpdatedAt(new Date());
+        return this.updateById(order);
+    }
+
+    public boolean cancelOrder(String orderNo) {
+        LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        AssessmentOrder order = this.getOne(wrapper);
+        if (order == null) return false;
+        if ("paid".equals(order.getStatus())) return false;
+        order.setStatus("cancelled");
+        order.setUpdatedAt(new Date());
+        return this.updateById(order);
+    }
+
+    public AssessmentOrder getByOrderNo(String orderNo) {
+        LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AssessmentOrder::getOrderNo, orderNo);
+        return this.getOne(wrapper);
+    }
+
+    public List<AssessmentOrder> getFamilyOrders(Long familyId) {
+        LambdaQueryWrapper<AssessmentOrder> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AssessmentOrder::getFamilyId, familyId);
+        wrapper.orderByDesc(AssessmentOrder::getCreatedAt);
+        return this.list(wrapper);
+    }
+}

+ 38 - 0
zxyj-backend/src/main/java/com/zxyj/service/AssessmentService.java

@@ -5,14 +5,17 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.zxyj.entity.AssessmentMaterial;
 import com.zxyj.entity.AssessmentPointsConfig;
 import com.zxyj.entity.AssessmentRecord;
+import com.zxyj.entity.AssessmentResult;
 import com.zxyj.entity.FamilyAssessmentConfig;
 import com.zxyj.mapper.AssessmentMaterialMapper;
 import com.zxyj.mapper.AssessmentPointsConfigMapper;
 import com.zxyj.mapper.AssessmentRecordMapper;
+import com.zxyj.mapper.AssessmentResultMapper;
 import com.zxyj.mapper.FamilyAssessmentConfigMapper;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
+import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.List;
@@ -29,6 +32,9 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
     @Resource
     private AssessmentRecordMapper recordMapper;
 
+    @Resource
+    private AssessmentResultMapper assessmentResultMapper;
+
     public AssessmentMaterial getActiveMaterial() {
         LambdaQueryWrapper<AssessmentMaterial> wrapper = new LambdaQueryWrapper<>();
         wrapper.eq(AssessmentMaterial::getStatus, "active");
@@ -167,4 +173,36 @@ public class AssessmentService extends ServiceImpl<AssessmentMaterialMapper, Ass
         wrapper.last("LIMIT 1");
         return recordMapper.selectOne(wrapper);
     }
+
+    public AssessmentResult recordResult(AssessmentResult result) {
+        result.setStatus("completed");
+        result.setCreatedAt(new Date());
+        result.setUpdatedAt(new Date());
+        if (result.getAssessmentDate() == null) {
+            result.setAssessmentDate(new Date());
+        }
+        assessmentResultMapper.insert(result);
+        return result;
+    }
+
+    public List<AssessmentResult> getResultsByGuide(Long guideId) {
+        LambdaQueryWrapper<AssessmentResult> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AssessmentResult::getTeacherId, guideId);
+        wrapper.orderByDesc(AssessmentResult::getCreatedAt);
+        return assessmentResultMapper.selectList(wrapper);
+    }
+
+    public AssessmentResult getByAppointmentId(Long appointmentId) {
+        LambdaQueryWrapper<AssessmentResult> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AssessmentResult::getAppointmentId, appointmentId);
+        wrapper.last("LIMIT 1");
+        return assessmentResultMapper.selectOne(wrapper);
+    }
+
+    public List<AssessmentResult> getAccessibleResults(Long userId, String role) {
+        if ("teacher".equals(role)) {
+            return getResultsByGuide(userId);
+        }
+        return new ArrayList<>();
+    }
 }

+ 1 - 1
zxyj-backend/src/main/java/com/zxyj/service/PackagePurchaseService.java

@@ -126,7 +126,7 @@ public class PackagePurchaseService {
      * 获取可用的指导师列表(针对特定套餐)
      */
     public List<Map<String, Object>> getAvailableGuides(Long packageId) {
-        return List.of();
+        return new java.util.ArrayList<>();
     }
 
     /**

+ 2 - 1
zxyj-backend/src/main/java/com/zxyj/service/RewardService.java

@@ -12,6 +12,7 @@ import com.zxyj.mapper.ChildMapper;
 import com.zxyj.mapper.PointsLogMapper;
 import com.zxyj.mapper.RewardMapper;
 import com.zxyj.mapper.UserMapper;
+import com.zxyj.service.api.RewardServiceInterface;
 import javax.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -25,7 +26,7 @@ import java.util.stream.Collectors;
 
 @Slf4j
 @Service
-public class RewardService {
+public class RewardService implements RewardServiceInterface {
 
 @Resource
 private RewardMapper rewardMapper;

+ 2 - 1
zxyj-backend/src/main/java/com/zxyj/service/StreetService.java

@@ -3,6 +3,7 @@ package com.zxyj.service;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.zxyj.entity.Street;
 import com.zxyj.mapper.StreetMapper;
+import com.zxyj.service.api.StreetServiceInterface;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
@@ -13,7 +14,7 @@ import java.util.stream.Collectors;
  * 街道服务 - 支持四级地址和区域回退匹配
  */
 @Service
-public class StreetService {
+public class StreetService implements StreetServiceInterface {
 
     @Resource
     private StreetMapper streetMapper;

+ 2 - 1
zxyj-backend/src/main/java/com/zxyj/service/TaskService.java

@@ -6,6 +6,7 @@ import com.zxyj.dto.CreateTaskDTO;
 import com.zxyj.dto.TaskReviewDTO;
 import com.zxyj.entity.*;
 import com.zxyj.mapper.*;
+import com.zxyj.service.api.TaskServiceInterface;
 import javax.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
@@ -15,7 +16,7 @@ import java.util.*;
 
 @Slf4j
 @Service
-public class TaskService {
+public class TaskService implements TaskServiceInterface {
 
     @Resource
     private TaskMapper taskMapper;

+ 23 - 0
zxyj-backend/src/main/java/com/zxyj/service/api/RewardServiceInterface.java

@@ -0,0 +1,23 @@
+package com.zxyj.service.api;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zxyj.dto.CreateRewardDTO;
+import com.zxyj.dto.RewardDTO;
+import com.zxyj.entity.Reward;
+import java.util.List;
+import java.util.Map;
+
+public interface RewardServiceInterface {
+    Long createWishlist(Long childId, CreateRewardDTO dto);
+    boolean approveWishlist(Long rewardId, Long parentId, Integer pointsRequired);
+    Long createReward(Long userId, CreateRewardDTO dto);
+    List<RewardDTO> getWishlist(Long childId);
+    Map<String, Object> exchangeReward(Long rewardId, Long childId);
+    boolean approveReward(Long rewardId, boolean approved);
+    List<Reward> getTemplates();
+    Page<Reward> getExchangeHistory(Long childId, Integer page, Integer size);
+    List<RewardDTO> getFamilyRewardLibrary(Long familyId);
+    boolean updateRewardPoints(Long rewardId, Long parentId, Integer newPoints);
+    List<RewardDTO> getChildPendingWishlists(Long childId);
+    List<RewardDTO> getPendingApprovalList(Long familyId);
+}

+ 24 - 0
zxyj-backend/src/main/java/com/zxyj/service/api/TaskServiceInterface.java

@@ -0,0 +1,24 @@
+package com.zxyj.service.api;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.zxyj.dto.CreateTaskDTO;
+import com.zxyj.dto.TaskReviewDTO;
+import com.zxyj.entity.Task;
+import java.util.List;
+import java.util.Map;
+
+public interface TaskServiceInterface {
+    Long createTask(Long userId, CreateTaskDTO dto);
+    List<Task> getTodayTasks(Long childId);
+    Map<String, Object> completeTask(Long taskId, Long childId, String photoUrl);
+    boolean reviewTask(Long taskId, TaskReviewDTO dto);
+    Page<Task> getTaskHistory(Long childId, Integer page, Integer size);
+    boolean deleteTask(Long taskId, Long userId);
+    List<Task> getPendingReviewTasks(Long userId);
+    List<Task> getTodayParentTasks(Long userId);
+    Map<String, Object> completeParentTask(Long taskId, Long userId);
+    List<Task> getPendingReviewTasksForChild(Long childId);
+    List<Task> getAllTasksByChild(Long childId);
+    Page<Task> getTaskHistoryByChild(Long childId, Integer page, Integer size, String status);
+    Map<String, Object> completeMinigameTask(Long taskId, Long childId, Integer completionTime, Integer score);
+}