feat: parse uploaded review mind maps
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package com.guo.learningprogresstracker.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.guo.learningprogresstracker.dto.ReviewFeedItem;
|
||||
import com.guo.learningprogresstracker.dto.ReviewTaskStats;
|
||||
import com.guo.learningprogresstracker.dto.request.CreateReviewApplicationRequest;
|
||||
@@ -13,6 +14,8 @@ import com.guo.learningprogresstracker.entity.StudyReportsEntity;
|
||||
import com.guo.learningprogresstracker.entity.StudySessionsEntity;
|
||||
import com.guo.learningprogresstracker.entity.TaskEntity;
|
||||
import com.guo.learningprogresstracker.enums.ReviewApplicationStatusEnum;
|
||||
import com.guo.learningprogresstracker.enums.ReviewMindMapFileFormatEnum;
|
||||
import com.guo.learningprogresstracker.enums.ReviewMindMapParseStatusEnum;
|
||||
import com.guo.learningprogresstracker.exception.NotFindEntitiesException;
|
||||
import com.guo.learningprogresstracker.mapper.ReviewApplicationMapper;
|
||||
import com.guo.learningprogresstracker.mapper.ReviewMindMapMapper;
|
||||
@@ -24,7 +27,14 @@ import com.guo.learningprogresstracker.service.ReviewService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -43,6 +53,8 @@ public class ReviewServiceImpl implements ReviewService {
|
||||
private static final int MAX_LIMIT = 100;
|
||||
private static final String RANDOM_MODE = "random";
|
||||
private static final String DEFAULT_MIND_MAP_FORMAT = "TEXT";
|
||||
private static final String MANUAL_SOURCE_TYPE = "MANUAL";
|
||||
private static final String FILE_SOURCE_TYPE = "FILE";
|
||||
|
||||
private final StudyReportsMapper studyReportsMapper;
|
||||
private final StudyReportFragmentsMapper studyReportFragmentsMapper;
|
||||
@@ -50,6 +62,7 @@ public class ReviewServiceImpl implements ReviewService {
|
||||
private final TasksMapper tasksMapper;
|
||||
private final ReviewApplicationMapper reviewApplicationMapper;
|
||||
private final ReviewMindMapMapper reviewMindMapMapper;
|
||||
private final MindMapFileParser mindMapFileParser = new MindMapFileParser(new ObjectMapper());
|
||||
|
||||
@Override
|
||||
public List<ReviewFeedItem> getReviewFeed(int limit, String mode) {
|
||||
@@ -208,6 +221,66 @@ public class ReviewServiceImpl implements ReviewService {
|
||||
entity.setTitle(request.getTitle());
|
||||
entity.setContent(request.getContent());
|
||||
entity.setContentFormat(normalizeMindMapFormat(request.getContentFormat()));
|
||||
entity.setSourceType(MANUAL_SOURCE_TYPE);
|
||||
entity.setFileName(null);
|
||||
entity.setFilePath(null);
|
||||
entity.setFileFormat(null);
|
||||
entity.setParsedContent(null);
|
||||
entity.setSummary(null);
|
||||
entity.setLastParsedTime(null);
|
||||
entity.setParseStatus(ReviewMindMapParseStatusEnum.SUCCESS.getCode());
|
||||
entity.setParseError(null);
|
||||
if (create) {
|
||||
reviewMindMapMapper.insert(entity);
|
||||
} else {
|
||||
reviewMindMapMapper.updateById(entity);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReviewMindMapEntity uploadMindMap(String taskNum, MultipartFile file) throws NotFindEntitiesException, IOException {
|
||||
ensureTaskExists(taskNum);
|
||||
if (file == null || file.isEmpty()) {
|
||||
throw new IOException("思维导图文件不可为空");
|
||||
}
|
||||
|
||||
String originalFileName = StringUtils.cleanPath(
|
||||
Optional.ofNullable(file.getOriginalFilename()).orElse("mind-map.txt"));
|
||||
ReviewMindMapFileFormatEnum format = ReviewMindMapFileFormatEnum.fromFileName(originalFileName);
|
||||
Path storedPath = storeMindMapFile(taskNum, originalFileName, file);
|
||||
|
||||
ReviewMindMapEntity entity = getMindMap(taskNum);
|
||||
boolean create = entity == null;
|
||||
if (create) {
|
||||
entity = new ReviewMindMapEntity();
|
||||
entity.setTaskNum(taskNum);
|
||||
}
|
||||
|
||||
entity.setSourceType(FILE_SOURCE_TYPE);
|
||||
entity.setFileName(originalFileName);
|
||||
entity.setFilePath(storedPath.toString());
|
||||
entity.setFileFormat(format.getCode());
|
||||
entity.setContentFormat("JSON");
|
||||
entity.setLastParsedTime(LocalDateTime.now());
|
||||
|
||||
try {
|
||||
MindMapFileParser.ParseResult parseResult = mindMapFileParser.parse(file, format);
|
||||
entity.setTitle(StringUtils.hasText(parseResult.title()) ? parseResult.title() : originalFileName);
|
||||
entity.setContent(parseResult.outline());
|
||||
entity.setParsedContent(parseResult.parsedContent());
|
||||
entity.setSummary(parseResult.summary());
|
||||
entity.setParseStatus(ReviewMindMapParseStatusEnum.SUCCESS.getCode());
|
||||
entity.setParseError(null);
|
||||
} catch (IOException e) {
|
||||
entity.setTitle(originalFileName);
|
||||
entity.setContent("");
|
||||
entity.setParsedContent(null);
|
||||
entity.setSummary(null);
|
||||
entity.setParseStatus(ReviewMindMapParseStatusEnum.FAILED.getCode());
|
||||
entity.setParseError(e.getMessage());
|
||||
}
|
||||
|
||||
if (create) {
|
||||
reviewMindMapMapper.insert(entity);
|
||||
} else {
|
||||
@@ -323,6 +396,17 @@ public class ReviewServiceImpl implements ReviewService {
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private Path storeMindMapFile(String taskNum, String originalFileName, MultipartFile file) throws IOException {
|
||||
Path directory = Paths.get("uploads", "review-mind-maps", taskNum);
|
||||
Files.createDirectories(directory);
|
||||
String storedFileName = UUID.randomUUID() + "-" + originalFileName.replaceAll("[\\\\/:*?\"<>|]", "_");
|
||||
Path target = directory.resolve(storedFileName);
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
Files.copy(inputStream, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private void fillReviewTaskStats(List<ReviewTaskStats> statsList) {
|
||||
Map<String, ReviewTaskStats> statsByTaskNum = statsList.stream()
|
||||
.filter(item -> StringUtils.hasText(item.getTaskNum()))
|
||||
|
||||
Reference in New Issue
Block a user