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

perf(application): configure HikariCP pool size 50, remove duplicate datasource config

- Set maximum-pool-size:50, minimum-idle:10, connection-timeout:30s
- Removed duplicate jdbc-url/credentials from hikari block (was overriding spring.datasource)
- Fixed TrainingPlanService: RecommendationItem -> DimensionRecommendation
Xiaogang Liao пре 2 месеци
родитељ
комит
809382e7fd

+ 233 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/TrainingPlanService.java

@@ -0,0 +1,233 @@
+package com.etotem.cfc.service;
+
+import com.etotem.cfc.dto.CognitiveRecommendationDTO;
+import com.etotem.cfc.entity.TrainingPlan;
+import com.etotem.cfc.entity.TrainingPlanItem;
+import com.etotem.cfc.entity.TrainingPlanTask;
+import com.etotem.cfc.mapper.TrainingPlanMapper;
+import com.etotem.cfc.mapper.ChildMapper;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+@Service
+public class TrainingPlanService {
+
+    @Resource
+    private TrainingPlanMapper trainingPlanMapper;
+
+    @Resource
+    private ChildMapper childMapper;
+
+    @Resource
+    private CognitiveTrainingConfigService trainingConfigService;
+
+    @Resource
+    private TaskService taskService;
+
+    public List<TrainingPlan> getPlansByGuide(Long guideId) {
+        return trainingPlanMapper.selectByGuideId(guideId);
+    }
+
+    public List<TrainingPlan> getPlansByGuideAndChild(Long guideId, Long childId) {
+        return trainingPlanMapper.selectByGuideIdAndChildId(guideId, childId);
+    }
+
+    public TrainingPlan getPlanById(Long planId) {
+        return trainingPlanMapper.selectById(planId);
+    }
+
+    public List<TrainingPlanItem> getPlanItems(Long planId) {
+        return trainingPlanMapper.selectItemsByPlanId(planId);
+    }
+
+    @Transactional
+    public Long createPlan(Long guideId, Long childId, String title, String description, String source) {
+        TrainingPlan plan = new TrainingPlan();
+        plan.setGuideId(guideId);
+        plan.setChildId(childId);
+        plan.setTitle(title);
+        plan.setDescription(description);
+        plan.setSource(source != null ? source : "manual");
+        plan.setStatus("draft");
+        plan.setCreatedAt(new Date());
+        plan.setUpdatedAt(new Date());
+        trainingPlanMapper.insert(plan);
+        return plan.getId();
+    }
+
+    @Transactional
+    public void updatePlan(Long planId, String title, String description) {
+        TrainingPlan plan = trainingPlanMapper.selectById(planId);
+        if (plan != null) {
+            if (title != null) plan.setTitle(title);
+            if (description != null) plan.setDescription(description);
+            plan.setUpdatedAt(new Date());
+            trainingPlanMapper.updateById(plan);
+        }
+    }
+
+    @Transactional
+    public Long addItem(Long planId, TrainingPlanItem item) {
+        item.setPlanId(planId);
+        item.setStatus("pending");
+        item.setCreatedAt(new Date());
+        return trainingPlanMapper.insertItem(item);
+    }
+
+    @Transactional
+    public void updateItem(TrainingPlanItem item) {
+        trainingPlanMapper.updateItem(item);
+    }
+
+    @Transactional
+    public void deleteItem(Long itemId) {
+        trainingPlanMapper.deleteItem(itemId);
+    }
+
+    @Transactional
+    public Long generateFromRecommendations(Long guideId, Long childId) {
+        CognitiveRecommendationDTO rec = trainingConfigService.generateRecommendations(childId);
+        if (rec == null) {
+            return null;
+        }
+
+        TrainingPlan plan = new TrainingPlan();
+        plan.setGuideId(guideId);
+        plan.setChildId(childId);
+        plan.setTitle("认知训练方案 - " + new java.text.SimpleDateFormat("yyyy-MM-dd").format(new Date()));
+        plan.setSource("recommendations");
+        plan.setStatus("draft");
+        plan.setCreatedAt(new Date());
+        plan.setUpdatedAt(new Date());
+        trainingPlanMapper.insert(plan);
+        Long planId = plan.getId();
+
+        if (rec.getRecommendations() != null) {
+            int seq = 1;
+            for (Object rObj : rec.getRecommendations()) {
+                com.etotem.cfc.dto.CognitiveRecommendationDTO.DimensionRecommendation r =
+                    (com.etotem.cfc.dto.CognitiveRecommendationDTO.DimensionRecommendation) rObj;
+                TrainingPlanItem item = new TrainingPlanItem();
+                item.setPlanId(planId);
+                item.setSequence(seq++);
+                item.setDimensionKey(r.getDimensionKey());
+                item.setSuggestion(r.getSuggestion());
+                item.setTaskTitle(r.getLabel() + "训练");
+                item.setTaskDesc(r.getSuggestion());
+                item.setTaskPoints(2);
+                item.setDeadlineDays(7);
+                item.setStatus("pending");
+                item.setCreatedAt(new Date());
+                if (r.getGames() != null && !r.getGames().isEmpty()) {
+                    item.setMinigameCode(r.getGames().get(0).getCode());
+                }
+                if (r.getArticles() != null && !r.getArticles().isEmpty()) {
+                    item.setArticleId(r.getArticles().get(0).getId());
+                }
+                trainingPlanMapper.insertItem(item);
+            }
+        }
+
+        return planId;
+    }
+
+    @Transactional
+    public List<Long> deployPlan(Long planId, Long operatorId) {
+        TrainingPlan plan = trainingPlanMapper.selectById(planId);
+        if (plan == null || !"draft".equals(plan.getStatus())) {
+            return Collections.emptyList();
+        }
+
+        List<TrainingPlanItem> items = trainingPlanMapper.selectItemsByPlanId(planId);
+        List<Long> taskIds = new ArrayList<>();
+        Calendar cal = Calendar.getInstance();
+
+        for (TrainingPlanItem item : items) {
+            com.etotem.cfc.dto.CreateTaskDTO dto = new com.etotem.cfc.dto.CreateTaskDTO();
+            dto.setTitle(item.getTaskTitle());
+            dto.setDescription(item.getTaskDesc());
+            dto.setChildId(plan.getChildId());
+            dto.setCategory("认知训练");
+            dto.setMinigameCode(item.getMinigameCode());
+            dto.setPoints(item.getTaskPoints() != null ? item.getTaskPoints() : 2);
+
+            cal = Calendar.getInstance();
+            cal.add(Calendar.DAY_OF_MONTH, item.getDeadlineDays() != null ? item.getDeadlineDays() : 7);
+            dto.setDeadline(cal.getTime());
+
+            Long taskId = taskService.createTask(operatorId, dto);
+            taskIds.add(taskId);
+
+            TrainingPlanTask ppt = new TrainingPlanTask();
+            ppt.setPlanId(planId);
+            ppt.setPlanItemId(item.getId());
+            ppt.setTaskId(taskId);
+            ppt.setChildId(plan.getChildId());
+            ppt.setStatus("pending");
+            ppt.setCreatedAt(new Date());
+            trainingPlanMapper.insertPlanTask(ppt);
+        }
+
+        plan.setStatus("published");
+        plan.setDeployedAt(new Date());
+        plan.setUpdatedAt(new Date());
+        trainingPlanMapper.updateById(plan);
+
+        return taskIds;
+    }
+
+    public Map<String, Object> getExecutionBoard(Long planId) {
+        TrainingPlan plan = trainingPlanMapper.selectById(planId);
+        if (plan == null) {
+            return Collections.emptyMap();
+        }
+
+        List<TrainingPlanItem> items = trainingPlanMapper.selectItemsByPlanId(planId);
+        List<TrainingPlanTask> planTasks = trainingPlanMapper.selectTasksByPlanId(planId);
+
+        Map<Long, TrainingPlanTask> taskMap = new HashMap<>();
+        for (TrainingPlanTask pt : planTasks) {
+            taskMap.put(pt.getPlanItemId(), pt);
+        }
+
+        int total = items.size();
+        int completed = 0;
+        for (TrainingPlanItem item : items) {
+            if ("completed".equals(item.getStatus())) {
+                completed++;
+            }
+        }
+
+        Map<String, Object> board = new LinkedHashMap<>();
+        board.put("planId", planId);
+        board.put("title", plan.getTitle());
+        board.put("status", plan.getStatus());
+        board.put("totalItems", total);
+        board.put("completedItems", completed);
+        board.put("progress", total > 0 ? Math.round(completed * 100.0 / total) : 0);
+
+        List<Map<String, Object>> itemStatus = new ArrayList<>();
+        for (TrainingPlanItem item : items) {
+            Map<String, Object> m = new LinkedHashMap<>();
+            m.put("itemId", item.getId());
+            m.put("dimensionKey", item.getDimensionKey());
+            m.put("taskTitle", item.getTaskTitle());
+            m.put("status", item.getStatus());
+            TrainingPlanTask ppt = taskMap.get(item.getId());
+            m.put("taskId", ppt != null ? ppt.getTaskId() : null);
+            m.put("taskStatus", ppt != null ? ppt.getStatus() : null);
+            itemStatus.add(m);
+        }
+        board.put("itemStatus", itemStatus);
+
+        return board;
+    }
+
+    @Transactional
+    public void deletePlan(Long planId) {
+        trainingPlanMapper.deleteById(planId);
+    }
+}

+ 6 - 4
cfc-backend/src/main/resources/application.yml

@@ -20,10 +20,12 @@ spring:
     username: zxyj
     password: zxyj@123
     hikari:
-      jdbc-url: jdbc:mysql://192.168.16.251:3306/zxyj?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&createDatabaseIfNotExist=true
-      username: zxyj
-      password: zxyj@123
-      driver-class-name: com.mysql.cj.jdbc.Driver
+      maximum-pool-size: 50
+      minimum-idle: 10
+      connection-timeout: 30000
+      idle-timeout: 600000
+      max-lifetime: 1800000
+      pool-name: CfcHikariPool
 
 sfms:
   datasource: