Procházet zdrojové kódy

feat(backend): add food suitability parsing to PdfParseService

Sisyphus před 2 měsíci
rodič
revize
0e6ea3b20a

+ 73 - 0
cfc-backend/src/main/java/com/etotem/cfc/service/PdfParseService.java

@@ -2,8 +2,10 @@ package com.etotem.cfc.service;
 
 import com.etotem.cfc.dto.ParsedDiseaseRisk;
 import com.etotem.cfc.dto.ParsedGutFlora;
+import com.etotem.cfc.dto.ParsedFoodSuitability;
 import com.etotem.cfc.dto.ParsedIndicator;
 import com.etotem.cfc.dto.ParsedReportResult;
+import java.math.BigDecimal;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.text.PDFTextStripper;
@@ -94,6 +96,10 @@ public class PdfParseService {
         result.setProbioticSpecies(probioticSpecies);
         result.setIndicators(indicators);
 
+        // 解析食材推荐
+        List<ParsedFoodSuitability> foodSuitability = parseFoodSuitability(fullText);
+        result.setFoodSuitability(foodSuitability);
+
         return result;
     }
 
@@ -644,4 +650,71 @@ public class PdfParseService {
         // 保留百分比,"ND"
         return str.replaceAll("[\\uF000-\\uFFFF]", "").trim();
     }
+
+    public List<ParsedFoodSuitability> parseFoodSuitability(String fullText) {
+        List<ParsedFoodSuitability> result = new ArrayList<>();
+        String foodSection = findSection(fullText, "食材推荐", "食材评分", "食物适宜度");
+        if (foodSection == null || foodSection.trim().isEmpty()) {
+            return result;
+        }
+
+        String[] lines = foodSection.split("\n");
+        for (String line : lines) {
+            line = line.trim();
+            if (line.isEmpty()) continue;
+            String[] parts = line.split(",");
+            if (parts.length < 4) continue;
+
+            try {
+                ParsedFoodSuitability item = new ParsedFoodSuitability();
+                item.setFoodName(parts[0].trim());
+                item.setCategory(parts[1].trim());
+                item.setScore(Integer.parseInt(parts[2].trim()));
+
+                if (parts.length > 3) item.setEnergyKj(new BigDecimal(parts[3].trim()));
+                if (parts.length > 4) item.setProtein(new BigDecimal(parts[4].trim()));
+                if (parts.length > 5) item.setFat(new BigDecimal(parts[5].trim()));
+                if (parts.length > 6) item.setCarbs(new BigDecimal(parts[6].trim()));
+                if (parts.length > 7) item.setStarch(new BigDecimal(parts[7].trim()));
+                if (parts.length > 8) item.setFiber(new BigDecimal(parts[8].trim()));
+                if (parts.length > 9) item.setCholesterol(new BigDecimal(parts[9].trim()));
+
+                result.add(item);
+            } catch (NumberFormatException e) {
+                log.warn("解析食材行失败: {}", line);
+            }
+        }
+        return result;
+    }
+
+    private String findSection(String text, String... keywords) {
+        String[] lines = text.split("\\r?\\n");
+        int startIdx = -1;
+        for (int i = 0; i < lines.length; i++) {
+            String line = lines[i].trim();
+            for (String keyword : keywords) {
+                if (line.contains(keyword)) {
+                    startIdx = i + 1;
+                    break;
+                }
+            }
+            if (startIdx >= 0) break;
+        }
+        if (startIdx < 0 || startIdx >= lines.length) return null;
+
+        StringBuilder section = new StringBuilder();
+        for (int i = startIdx; i < lines.length; i++) {
+            String line = lines[i].trim();
+            if (i > startIdx && line.isEmpty()) {
+                if (i + 1 < lines.length) {
+                    String next = lines[i + 1].trim();
+                    if (!next.isEmpty() && !next.matches("^[\\d.,%\\s]+$")) {
+                        break;
+                    }
+                }
+            }
+            section.append(line).append("\n");
+        }
+        return section.toString().trim();
+    }
 }