|
|
@@ -2,35 +2,55 @@ package com.etotem.cfc.service.impl;
|
|
|
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
|
|
import com.etotem.cfc.entity.HealthPlan;
|
|
|
+import com.etotem.cfc.entity.Task;
|
|
|
import com.etotem.cfc.mapper.HealthPlanMapper;
|
|
|
+import com.etotem.cfc.mapper.TaskMapper;
|
|
|
import com.etotem.cfc.service.HealthPlanService;
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.http.ResponseEntity;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
import javax.annotation.Resource;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Calendar;
|
|
|
import java.util.Date;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.regex.Matcher;
|
|
|
+import java.util.regex.Pattern;
|
|
|
import com.etotem.cfc.util.SortUtil;
|
|
|
|
|
|
+@Slf4j
|
|
|
@Service
|
|
|
public class HealthPlanServiceImpl implements HealthPlanService {
|
|
|
- private static final Logger log = LoggerFactory.getLogger(HealthPlanServiceImpl.class);
|
|
|
|
|
|
@Resource
|
|
|
private HealthPlanMapper healthPlanMapper;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private TaskMapper taskMapper;
|
|
|
+
|
|
|
@Value("${cfc.langgraph.base-url:}")
|
|
|
private String langgraphBaseUrl;
|
|
|
|
|
|
+ // 匹配方案文本中的任务行(与前端 parseTasksFromPlan 保持一致)
|
|
|
+ private static final Pattern TASK_PATTERN = Pattern.compile(
|
|
|
+ "^(?:\\d+[\\.、\\)\\]]]|[-*•]|\\[.+\\]|【任务\\d+】)[\\s ]*([^\\n]+)"
|
|
|
+ );
|
|
|
+
|
|
|
@Override
|
|
|
public Long savePlan(HealthPlan plan) {
|
|
|
plan.setCreatedAt(new Date());
|
|
|
healthPlanMapper.insert(plan);
|
|
|
+ try {
|
|
|
+ generateDailyTasksFromPlan(plan);
|
|
|
+ log.info("方案{}自动生成任务完成,familyId={}, memberIds={}",
|
|
|
+ plan.getId(), plan.getFamilyId(), plan.getMemberIds());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.warn("方案{}自动生成任务失败,不影响方案保存: {}", plan.getId(), e.getMessage());
|
|
|
+ }
|
|
|
return plan.getId();
|
|
|
}
|
|
|
|
|
|
@@ -88,4 +108,77 @@ public class HealthPlanServiceImpl implements HealthPlanService {
|
|
|
sb.append("坚持执行以上方案,预计 4 周内可见明显改善。\n");
|
|
|
return sb.toString();
|
|
|
}
|
|
|
-}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析方案文本,为每个任务项创建当天的 Task 记录
|
|
|
+ */
|
|
|
+ private void generateDailyTasksFromPlan(HealthPlan plan) {
|
|
|
+ String content = plan.getPlanContent();
|
|
|
+ if (content == null || content.trim().isEmpty()) return;
|
|
|
+
|
|
|
+ List<String> taskLines = parseTaskLines(content);
|
|
|
+ if (taskLines.isEmpty()) return;
|
|
|
+
|
|
|
+ Long familyId = plan.getFamilyId();
|
|
|
+ String[] memberIdArray = (plan.getMemberIds() != null && !plan.getMemberIds().isEmpty())
|
|
|
+ ? plan.getMemberIds().split(",") : new String[0];
|
|
|
+ Long childId = memberIdArray.length > 0 ? Long.valueOf(memberIdArray[0]) : null;
|
|
|
+ Long executorId = childId != null ? childId : null;
|
|
|
+
|
|
|
+ // 当天截止:23:59:59
|
|
|
+ Calendar cal = Calendar.getInstance();
|
|
|
+ cal.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
+ cal.set(Calendar.MINUTE, 59);
|
|
|
+ cal.set(Calendar.SECOND, 59);
|
|
|
+ Date deadline = cal.getTime();
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+
|
|
|
+ for (String line : taskLines) {
|
|
|
+ // 幂等:同一方案同一天已有同名任务则跳过
|
|
|
+ boolean exists = taskMapper.selectCount(new QueryWrapper<Task>()
|
|
|
+ .eq("family_id", familyId)
|
|
|
+ .eq("source_type", "plan")
|
|
|
+ .eq("source_id", plan.getId())
|
|
|
+ .eq("title", line.trim())) > 0;
|
|
|
+ if (exists) continue;
|
|
|
+
|
|
|
+ Task task = new Task();
|
|
|
+ task.setFamilyId(familyId);
|
|
|
+ task.setChildId(childId);
|
|
|
+ task.setExecutorType("child");
|
|
|
+ task.setExecutorId(executorId);
|
|
|
+ task.setCreatorId(executorId != null ? executorId : 0L);
|
|
|
+ task.setTitle(line.trim());
|
|
|
+ task.setDescription("");
|
|
|
+ task.setPoints(10);
|
|
|
+ task.setDeadline(deadline);
|
|
|
+ task.setStatus("pending");
|
|
|
+ task.setSourceType("plan");
|
|
|
+ task.setSourceId(plan.getId());
|
|
|
+ task.setFrequency("daily");
|
|
|
+ task.setCategory("健康方案");
|
|
|
+ task.setNeedReview(0);
|
|
|
+ task.setCreatedAt(now);
|
|
|
+ task.setUpdatedAt(now);
|
|
|
+ taskMapper.insert(task);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从方案文本中提取任务行(与前端正则逻辑一致)
|
|
|
+ */
|
|
|
+ private List<String> parseTaskLines(String planText) {
|
|
|
+ String[] lines = planText.split("\n");
|
|
|
+ List<String> tasks = new java.util.ArrayList<>();
|
|
|
+ for (String line : lines) {
|
|
|
+ line = line.trim();
|
|
|
+ if (line.isEmpty()) continue;
|
|
|
+ Matcher m = TASK_PATTERN.matcher(line);
|
|
|
+ if (m.find()) {
|
|
|
+ tasks.add(m.group(1).trim());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return tasks;
|
|
|
+ }
|
|
|
+}
|