|
|
@@ -0,0 +1,334 @@
|
|
|
+package com.lingyue.extract.service;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import com.lingyue.extract.dto.request.CreateGenerationRequest;
|
|
|
+import com.lingyue.extract.dto.request.GenerationProgressResponse;
|
|
|
+import com.lingyue.extract.dto.response.GenerationResponse;
|
|
|
+import com.lingyue.extract.entity.Generation;
|
|
|
+import com.lingyue.extract.entity.SourceFile;
|
|
|
+import com.lingyue.extract.entity.Template;
|
|
|
+import com.lingyue.extract.entity.Variable;
|
|
|
+import com.lingyue.extract.repository.GenerationRepository;
|
|
|
+import com.lingyue.extract.repository.SourceFileRepository;
|
|
|
+import com.lingyue.extract.repository.TemplateRepository;
|
|
|
+import com.lingyue.extract.repository.VariableRepository;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.UUID;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 生成任务服务
|
|
|
+ *
|
|
|
+ * @author lingyue
|
|
|
+ * @since 2026-01-24
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class GenerationService {
|
|
|
+
|
|
|
+ private final GenerationRepository generationRepository;
|
|
|
+ private final TemplateRepository templateRepository;
|
|
|
+ private final SourceFileRepository sourceFileRepository;
|
|
|
+ private final VariableRepository variableRepository;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建生成任务
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public Generation create(String userId, CreateGenerationRequest request) {
|
|
|
+ // 验证模板
|
|
|
+ Template template = templateRepository.selectById(request.getTemplateId());
|
|
|
+ if (template == null) {
|
|
|
+ throw new RuntimeException("模板不存在");
|
|
|
+ }
|
|
|
+ if (!Template.STATUS_PUBLISHED.equals(template.getStatus())) {
|
|
|
+ throw new RuntimeException("模板未发布,无法使用");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 验证来源文件
|
|
|
+ List<SourceFile> requiredFiles = sourceFileRepository.findRequiredByTemplateId(request.getTemplateId());
|
|
|
+ for (SourceFile sf : requiredFiles) {
|
|
|
+ if (!request.getSourceFileMap().containsKey(sf.getAlias())) {
|
|
|
+ throw new RuntimeException("缺少必须的来源文件: " + sf.getAlias());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取变量列表,初始化变量值
|
|
|
+ List<Variable> variables = variableRepository.findByTemplateId(request.getTemplateId());
|
|
|
+ Map<String, Generation.VariableValue> variableValues = new HashMap<>();
|
|
|
+ for (Variable v : variables) {
|
|
|
+ Generation.VariableValue vv = new Generation.VariableValue();
|
|
|
+ vv.setVariableName(v.getName());
|
|
|
+ vv.setDisplayName(v.getDisplayName());
|
|
|
+ vv.setStatus(Generation.VariableValue.STATUS_PENDING);
|
|
|
+ variableValues.put(v.getName(), vv);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建生成任务
|
|
|
+ Generation generation = new Generation();
|
|
|
+ generation.setId(UUID.randomUUID().toString().replace("-", ""));
|
|
|
+ generation.setTemplateId(request.getTemplateId());
|
|
|
+ generation.setUserId(userId);
|
|
|
+ generation.setName(request.getName() != null ? request.getName() : template.getName() + " - " + new Date());
|
|
|
+ generation.setSourceFileMap(request.getSourceFileMap());
|
|
|
+ generation.setVariableValues(variableValues);
|
|
|
+ generation.setStatus(Generation.STATUS_PENDING);
|
|
|
+ generation.setProgress(0);
|
|
|
+ generation.setCreateTime(new Date());
|
|
|
+
|
|
|
+ generationRepository.insert(generation);
|
|
|
+
|
|
|
+ // 增加模板使用次数
|
|
|
+ templateRepository.incrementUseCount(request.getTemplateId());
|
|
|
+
|
|
|
+ log.info("创建生成任务成功: id={}, templateId={}, userId={}",
|
|
|
+ generation.getId(), request.getTemplateId(), userId);
|
|
|
+
|
|
|
+ return generation;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据ID获取
|
|
|
+ */
|
|
|
+ public Generation getById(String id) {
|
|
|
+ return generationRepository.selectById(id);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取任务详情(包含模板名称)
|
|
|
+ */
|
|
|
+ public GenerationResponse getDetail(String id) {
|
|
|
+ Generation generation = generationRepository.selectById(id);
|
|
|
+ if (generation == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ GenerationResponse response = GenerationResponse.fromEntity(generation);
|
|
|
+
|
|
|
+ // 填充模板名称
|
|
|
+ Template template = templateRepository.selectById(generation.getTemplateId());
|
|
|
+ if (template != null) {
|
|
|
+ response.setTemplateName(template.getName());
|
|
|
+ }
|
|
|
+
|
|
|
+ return response;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页查询用户的生成任务
|
|
|
+ */
|
|
|
+ public Page<GenerationResponse> listByUserId(String userId, int page, int size) {
|
|
|
+ Page<Generation> pageRequest = new Page<>(page, size);
|
|
|
+
|
|
|
+ LambdaQueryWrapper<Generation> wrapper = new LambdaQueryWrapper<>();
|
|
|
+ wrapper.eq(Generation::getUserId, userId)
|
|
|
+ .orderByDesc(Generation::getCreateTime);
|
|
|
+
|
|
|
+ Page<Generation> generationPage = generationRepository.selectPage(pageRequest, wrapper);
|
|
|
+
|
|
|
+ // 转换为响应对象
|
|
|
+ Page<GenerationResponse> responsePage = new Page<>(page, size, generationPage.getTotal());
|
|
|
+ List<GenerationResponse> records = generationPage.getRecords().stream()
|
|
|
+ .map(generation -> {
|
|
|
+ GenerationResponse response = GenerationResponse.fromEntity(generation);
|
|
|
+ // 填充模板名称
|
|
|
+ Template template = templateRepository.selectById(generation.getTemplateId());
|
|
|
+ if (template != null) {
|
|
|
+ response.setTemplateName(template.getName());
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ responsePage.setRecords(records);
|
|
|
+
|
|
|
+ return responsePage;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按模板查询生成任务
|
|
|
+ */
|
|
|
+ public List<GenerationResponse> listByTemplateId(String templateId) {
|
|
|
+ List<Generation> generations = generationRepository.findByTemplateId(templateId);
|
|
|
+ return generations.stream()
|
|
|
+ .map(GenerationResponse::fromEntity)
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行提取(异步处理,这里只更新状态)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public Generation execute(String id) {
|
|
|
+ Generation generation = generationRepository.selectById(id);
|
|
|
+ if (generation == null) {
|
|
|
+ throw new RuntimeException("生成任务不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!Generation.STATUS_PENDING.equals(generation.getStatus()) &&
|
|
|
+ !Generation.STATUS_ERROR.equals(generation.getStatus())) {
|
|
|
+ throw new RuntimeException("当前状态不允许执行: " + generation.getStatus());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态为提取中
|
|
|
+ generation.setStatus(Generation.STATUS_EXTRACTING);
|
|
|
+ generation.setProgress(0);
|
|
|
+ generation.setErrorMessage(null);
|
|
|
+ generationRepository.updateById(generation);
|
|
|
+
|
|
|
+ // TODO: 发送消息到队列,异步执行提取
|
|
|
+ // messageQueue.send("generation.extract", generation.getId());
|
|
|
+
|
|
|
+ log.info("开始执行生成任务: id={}", id);
|
|
|
+
|
|
|
+ return generation;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取执行进度
|
|
|
+ */
|
|
|
+ public GenerationProgressResponse getProgress(String id) {
|
|
|
+ Generation generation = generationRepository.selectById(id);
|
|
|
+ if (generation == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ int total = 0;
|
|
|
+ int completed = 0;
|
|
|
+ String currentVariable = null;
|
|
|
+
|
|
|
+ if (generation.getVariableValues() != null) {
|
|
|
+ total = generation.getVariableValues().size();
|
|
|
+ for (Generation.VariableValue vv : generation.getVariableValues().values()) {
|
|
|
+ if (Generation.VariableValue.STATUS_EXTRACTED.equals(vv.getStatus()) ||
|
|
|
+ Generation.VariableValue.STATUS_MANUAL.equals(vv.getStatus())) {
|
|
|
+ completed++;
|
|
|
+ } else if ("extracting".equals(vv.getStatus())) {
|
|
|
+ currentVariable = vv.getDisplayName();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return GenerationProgressResponse.of(
|
|
|
+ id,
|
|
|
+ generation.getStatus(),
|
|
|
+ generation.getProgress(),
|
|
|
+ total,
|
|
|
+ completed,
|
|
|
+ currentVariable
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新变量值
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public Generation updateVariableValue(String id, String variableName, String value) {
|
|
|
+ Generation generation = generationRepository.selectById(id);
|
|
|
+ if (generation == null) {
|
|
|
+ throw new RuntimeException("生成任务不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (generation.getVariableValues() == null) {
|
|
|
+ throw new RuntimeException("变量列表为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ Generation.VariableValue vv = generation.getVariableValues().get(variableName);
|
|
|
+ if (vv == null) {
|
|
|
+ throw new RuntimeException("变量不存在: " + variableName);
|
|
|
+ }
|
|
|
+
|
|
|
+ vv.setValue(value);
|
|
|
+ vv.setStatus(Generation.VariableValue.STATUS_MANUAL);
|
|
|
+
|
|
|
+ generationRepository.updateById(generation);
|
|
|
+ log.info("更新变量值成功: generationId={}, variable={}", id, variableName);
|
|
|
+
|
|
|
+ return generation;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 确认并生成文档
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public Generation confirm(String id) {
|
|
|
+ Generation generation = generationRepository.selectById(id);
|
|
|
+ if (generation == null) {
|
|
|
+ throw new RuntimeException("生成任务不存在");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!Generation.STATUS_REVIEW.equals(generation.getStatus())) {
|
|
|
+ throw new RuntimeException("当前状态不允许确认: " + generation.getStatus());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否所有必须的变量都有值
|
|
|
+ if (generation.getVariableValues() != null) {
|
|
|
+ for (Map.Entry<String, Generation.VariableValue> entry : generation.getVariableValues().entrySet()) {
|
|
|
+ Generation.VariableValue vv = entry.getValue();
|
|
|
+ if (vv.getValue() == null || vv.getValue().isEmpty()) {
|
|
|
+ // TODO: 检查变量是否必须
|
|
|
+ log.warn("变量 {} 没有值", entry.getKey());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新状态为生成中
|
|
|
+ generation.setStatus(Generation.STATUS_GENERATING);
|
|
|
+ generationRepository.updateById(generation);
|
|
|
+
|
|
|
+ // TODO: 发送消息到队列,异步生成文档
|
|
|
+ // messageQueue.send("generation.generate", generation.getId());
|
|
|
+
|
|
|
+ log.info("确认生成任务,开始生成文档: id={}", id);
|
|
|
+
|
|
|
+ return generation;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除生成任务
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public boolean delete(String id) {
|
|
|
+ Generation generation = generationRepository.selectById(id);
|
|
|
+ if (generation == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 不允许删除正在执行的任务
|
|
|
+ if (Generation.STATUS_EXTRACTING.equals(generation.getStatus()) ||
|
|
|
+ Generation.STATUS_GENERATING.equals(generation.getStatus())) {
|
|
|
+ throw new RuntimeException("任务正在执行中,无法删除");
|
|
|
+ }
|
|
|
+
|
|
|
+ generationRepository.deleteById(id);
|
|
|
+ log.info("删除生成任务成功: id={}", id);
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户最近的生成任务
|
|
|
+ */
|
|
|
+ public List<GenerationResponse> getRecentByUserId(String userId, int limit) {
|
|
|
+ List<Generation> generations = generationRepository.findRecentByUserId(userId, limit);
|
|
|
+ return generations.stream()
|
|
|
+ .map(generation -> {
|
|
|
+ GenerationResponse response = GenerationResponse.fromEntity(generation);
|
|
|
+ Template template = templateRepository.selectById(generation.getTemplateId());
|
|
|
+ if (template != null) {
|
|
|
+ response.setTemplateName(template.getName());
|
|
|
+ }
|
|
|
+ return response;
|
|
|
+ })
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ }
|
|
|
+}
|