20 changed files with 480 additions and 563 deletions
@ -0,0 +1,22 @@ |
|||
package com.project.information.application; |
|||
|
|||
import com.project.base.domain.result.Result; |
|||
import com.project.information.domain.entity.KnowledgePointDraftEntity; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 知识点草稿审核应用服务 |
|||
*/ |
|||
public interface DraftReviewApplicationService { |
|||
|
|||
Result<List<KnowledgePointDraftEntity>> listDrafts(Long informationId); |
|||
|
|||
Result<String> updateDraft(Long draftId, String content); |
|||
|
|||
Result<String> deleteDraft(Long draftId); |
|||
|
|||
Result<String> addDraft(Long informationId, String content, Integer knowledgeType); |
|||
|
|||
Result<String> confirm(Long informationId); |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
package com.project.information.application; |
|||
|
|||
import com.project.base.domain.result.Result; |
|||
import com.project.information.domain.dto.UploadedFileDTO; |
|||
import com.project.information.domain.param.UploadFilesParam; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 原始资料文件上传应用服务 |
|||
* Step1:只上传文件到 MinIO,不建表记录 |
|||
*/ |
|||
public interface UploadFilesApplicationService { |
|||
|
|||
/** |
|||
* 上传原始资料文件 |
|||
* 校验:最多5个文件,单个<100MB |
|||
* 只上传到 MinIO,返回文件信息列表(不建表) |
|||
* |
|||
* @param param 上传参数 |
|||
* @return 文件信息列表 |
|||
*/ |
|||
Result<List<UploadedFileDTO>> uploadFiles(UploadFilesParam param) throws Exception; |
|||
} |
|||
@ -0,0 +1,106 @@ |
|||
package com.project.information.application.impl; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.project.base.domain.exception.BusinessErrorException; |
|||
import com.project.base.domain.result.Result; |
|||
import com.project.information.application.DraftReviewApplicationService; |
|||
import com.project.information.domain.entity.InformationEntity; |
|||
import com.project.information.domain.entity.KnowledgePointDraftEntity; |
|||
import com.project.information.domain.enums.AuditStatusEnum; |
|||
import com.project.information.domain.enums.DraftStatusEnum; |
|||
import com.project.information.domain.service.ConfirmKnowledgePointDraftDomainService; |
|||
import com.project.information.domain.service.InformationBaseService; |
|||
import com.project.information.domain.service.KnowledgePointDraftBaseService; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 知识点草稿审核应用服务实现 |
|||
* 简单 CRUD 直接调 BaseService,确认固化调 DomainService |
|||
*/ |
|||
@Service |
|||
public class DraftReviewApplicationServiceImpl implements DraftReviewApplicationService { |
|||
|
|||
@Autowired |
|||
private KnowledgePointDraftBaseService knowledgePointDraftBaseService; |
|||
|
|||
@Autowired |
|||
private InformationBaseService informationBaseService; |
|||
|
|||
@Autowired |
|||
private ConfirmKnowledgePointDraftDomainService confirmKnowledgePointDraftDomainService; |
|||
|
|||
@Override |
|||
public Result<List<KnowledgePointDraftEntity>> listDrafts(Long informationId) { |
|||
if (informationId == null) { |
|||
throw new BusinessErrorException("资料ID不能为空"); |
|||
} |
|||
List<KnowledgePointDraftEntity> drafts = knowledgePointDraftBaseService.list( |
|||
new LambdaQueryWrapper<KnowledgePointDraftEntity>() |
|||
.eq(KnowledgePointDraftEntity::getInformationId, informationId) |
|||
.orderByAsc(KnowledgePointDraftEntity::getId)); |
|||
return Result.success(drafts); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> updateDraft(Long draftId, String content) { |
|||
if (draftId == null) { |
|||
throw new BusinessErrorException("草稿ID不能为空"); |
|||
} |
|||
KnowledgePointDraftEntity draft = knowledgePointDraftBaseService.getById(draftId); |
|||
if (draft == null) { |
|||
throw new BusinessErrorException("草稿不存在"); |
|||
} |
|||
if (!AuditStatusEnum.PENDING.getValue().equals(draft.getAuditStatus())) { |
|||
throw new BusinessErrorException("已固化的草稿不可修改"); |
|||
} |
|||
draft.setContent(content); |
|||
knowledgePointDraftBaseService.updateById(draft); |
|||
return Result.success("修改成功"); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> deleteDraft(Long draftId) { |
|||
if (draftId == null) { |
|||
throw new BusinessErrorException("草稿ID不能为空"); |
|||
} |
|||
KnowledgePointDraftEntity draft = knowledgePointDraftBaseService.getById(draftId); |
|||
if (draft == null) { |
|||
throw new BusinessErrorException("草稿不存在"); |
|||
} |
|||
if (!AuditStatusEnum.PENDING.getValue().equals(draft.getAuditStatus())) { |
|||
throw new BusinessErrorException("已固化的草稿不可删除"); |
|||
} |
|||
knowledgePointDraftBaseService.removeById(draftId); |
|||
return Result.success("删除成功"); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> addDraft(Long informationId, String content, Integer knowledgeType) { |
|||
if (informationId == null) { |
|||
throw new BusinessErrorException("资料ID不能为空"); |
|||
} |
|||
InformationEntity information = informationBaseService.getById(informationId); |
|||
if (information == null) { |
|||
throw new BusinessErrorException("资料不存在"); |
|||
} |
|||
if (!DraftStatusEnum.PENDING.getValue().equals(information.getDraftStatus())) { |
|||
throw new BusinessErrorException("该资料不在待审核状态,无法新增草稿"); |
|||
} |
|||
KnowledgePointDraftEntity draft = new KnowledgePointDraftEntity(); |
|||
draft.setInformationId(informationId); |
|||
draft.setContent(content); |
|||
draft.setAiContent(content); |
|||
draft.setKnowledgeType(knowledgeType); |
|||
draft.setAuditStatus(AuditStatusEnum.PENDING.getValue()); |
|||
knowledgePointDraftBaseService.save(draft); |
|||
return Result.success("新增成功"); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> confirm(Long informationId) { |
|||
return confirmKnowledgePointDraftDomainService.confirm(informationId); |
|||
} |
|||
} |
|||
@ -0,0 +1,95 @@ |
|||
package com.project.information.application.impl; |
|||
|
|||
import cn.hutool.core.io.FileUtil; |
|||
import com.project.base.config.CustomIdGenerator; |
|||
import com.project.base.domain.exception.BusinessErrorException; |
|||
import com.project.base.domain.result.Result; |
|||
import com.project.information.application.UploadFilesApplicationService; |
|||
import com.project.information.domain.dto.UploadedFileDTO; |
|||
import com.project.information.domain.enums.ContentCategoryEnum; |
|||
import com.project.information.domain.param.UploadFilesParam; |
|||
import com.project.information.utils.MinIoUtils; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.Date; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 原始资料文件上传应用服务实现 |
|||
* Step1:只上传文件到 MinIO,不建表记录 |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class UploadFilesApplicationServiceImpl implements UploadFilesApplicationService { |
|||
|
|||
private static final int MAX_FILE_COUNT = 5; |
|||
private static final long MAX_FILE_SIZE = 100 * 1024 * 1024L; // 100MB
|
|||
|
|||
@Autowired |
|||
private MinIoUtils minIoUtils; |
|||
|
|||
@Autowired |
|||
private CustomIdGenerator customIdGenerator; |
|||
|
|||
@Override |
|||
public Result<List<UploadedFileDTO>> uploadFiles(UploadFilesParam param) throws Exception { |
|||
MultipartFile[] files = param.getFiles(); |
|||
List<Integer> categories = param.getContentCategories(); |
|||
|
|||
// 参数校验
|
|||
if (files == null || files.length == 0) { |
|||
throw new BusinessErrorException("上传文件不能为空"); |
|||
} |
|||
if (files.length > MAX_FILE_COUNT) { |
|||
throw new BusinessErrorException("最多上传" + MAX_FILE_COUNT + "个文件"); |
|||
} |
|||
if (categories == null || categories.size() != files.length) { |
|||
throw new BusinessErrorException("每个文件需要对应一个内容分类"); |
|||
} |
|||
// 校验内容分类是否合法
|
|||
for (int i = 0; i < categories.size(); i++) { |
|||
if (!ContentCategoryEnum.isValid(categories.get(i))) { |
|||
throw new BusinessErrorException("第" + (i + 1) + "个文件的内容分类不合法"); |
|||
} |
|||
} |
|||
|
|||
List<UploadedFileDTO> result = new ArrayList<>(); |
|||
|
|||
for (int i = 0; i < files.length; i++) { |
|||
MultipartFile file = files[i]; |
|||
|
|||
// 单文件大小校验
|
|||
if (file.getSize() > MAX_FILE_SIZE) { |
|||
throw new BusinessErrorException("文件「" + file.getOriginalFilename() + "」超过100MB限制"); |
|||
} |
|||
|
|||
String originalFilename = file.getOriginalFilename(); |
|||
String suffix = FileUtil.getSuffix(originalFilename); |
|||
|
|||
// MinIO 路径规范:classicpaper/{yyyyMMdd}/{uuid}.{ext}
|
|||
String filePath = String.format("classicpaper/%s/%s.%s", |
|||
new java.text.SimpleDateFormat("yyyyMMdd").format(new Date()), |
|||
customIdGenerator.nextId(null), |
|||
suffix); |
|||
|
|||
// 上传到 MinIO
|
|||
minIoUtils.uploadFile(file.getInputStream(), filePath); |
|||
|
|||
// 构建返回结果(不建表)
|
|||
UploadedFileDTO dto = new UploadedFileDTO(); |
|||
dto.setFileName(originalFilename); |
|||
dto.setFilePath(filePath); |
|||
dto.setFileSuffix(suffix); |
|||
dto.setContentCategory(categories.get(i)); |
|||
result.add(dto); |
|||
|
|||
log.info(">>> [文件上传] 上传成功, fileName={}, filePath={}", originalFilename, filePath); |
|||
} |
|||
|
|||
return Result.success(result); |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
package com.project.information.domain.dto; |
|||
|
|||
import lombok.Data; |
|||
|
|||
/** |
|||
* 上传文件结果 DTO |
|||
* Step1 返回,Step2 提交时回传 |
|||
*/ |
|||
@Data |
|||
public class UploadedFileDTO { |
|||
/** 原始文件名 */ |
|||
private String fileName; |
|||
/** MinIO 存储路径 */ |
|||
private String filePath; |
|||
/** 文件后缀 */ |
|||
private String fileSuffix; |
|||
/** 内容分类 */ |
|||
private Integer contentCategory; |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
package com.project.information.domain.param; |
|||
|
|||
import lombok.Data; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 原始资料文件上传请求参数 |
|||
* Step1:只上传文件到 MinIO,不建表记录 |
|||
*/ |
|||
@Data |
|||
public class UploadFilesParam { |
|||
|
|||
/** 上传的文件列表(1-5个,单个<100MB) */ |
|||
private MultipartFile[] files; |
|||
|
|||
/** 每个文件对应的内容分类(与 files 数组一一对应):0-产品类,1-知识类,2-规范类,3-流程类 */ |
|||
private List<Integer> contentCategories; |
|||
} |
|||
@ -1,52 +0,0 @@ |
|||
package com.project.information.domain.service; |
|||
|
|||
import com.project.base.domain.result.Result; |
|||
import com.project.information.domain.entity.KnowledgePointDraftEntity; |
|||
|
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 知识点草稿审核域服务 |
|||
* 处理草稿的增删改查和确认固化 |
|||
*/ |
|||
public interface DraftReviewDomainService { |
|||
|
|||
/** |
|||
* 查询草稿列表 |
|||
* @param informationId 虚拟资料ID |
|||
* @return 草稿列表 |
|||
*/ |
|||
Result<List<KnowledgePointDraftEntity>> listDrafts(Long informationId); |
|||
|
|||
/** |
|||
* 修改单条草稿(仅修改 content,aiContent 保持不变) |
|||
* @param draftId 草稿ID |
|||
* @param content 用户修改后的内容 |
|||
*/ |
|||
Result<String> updateDraft(Long draftId, String content); |
|||
|
|||
/** |
|||
* 删除单条草稿 |
|||
* @param draftId 草稿ID |
|||
*/ |
|||
Result<String> deleteDraft(Long draftId); |
|||
|
|||
/** |
|||
* 新增草稿 |
|||
* @param informationId 虚拟资料ID |
|||
* @param content 知识点内容 |
|||
* @param knowledgeType 类型(0-精准,1-模糊) |
|||
*/ |
|||
Result<String> addDraft(Long informationId, String content, Integer knowledgeType); |
|||
|
|||
/** |
|||
* 确认提交(固化,不可逆) |
|||
* 1. 幂等校验:draftStatus 已是 APPROVED 则直接返回 |
|||
* 2. 将草稿的 content 复制到 evaluator_knowledge_point 正式表 |
|||
* 3. 更新草稿 auditStatus 为已通过 |
|||
* 4. 更新虚拟资料 draftStatus = APPROVED(2) |
|||
* 5. 触发聚类 |
|||
* @param informationId 虚拟资料ID |
|||
*/ |
|||
Result<String> confirm(Long informationId); |
|||
} |
|||
@ -1,172 +0,0 @@ |
|||
package com.project.information.domain.service.impl; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.project.base.domain.exception.BusinessErrorException; |
|||
import com.project.base.domain.result.Result; |
|||
import com.project.information.domain.dto.KnowledgePointDTO; |
|||
import com.project.information.domain.entity.InformationEntity; |
|||
import com.project.information.domain.entity.KnowledgePointDraftEntity; |
|||
import com.project.information.domain.entity.KnowledgePointEntity; |
|||
import com.project.information.domain.enums.AuditStatusEnum; |
|||
import com.project.information.domain.enums.DraftStatusEnum; |
|||
import com.project.information.domain.service.*; |
|||
import com.project.interaction.application.AlgorithmApplicationService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 知识点草稿审核域服务实现 |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class DraftReviewDomainServiceImpl implements DraftReviewDomainService { |
|||
|
|||
@Autowired |
|||
private KnowledgePointDraftBaseService knowledgePointDraftBaseService; |
|||
|
|||
@Autowired |
|||
private InformationBaseService informationBaseService; |
|||
|
|||
@Autowired |
|||
private KnowledgePointBaseService knowledgePointBaseService; |
|||
|
|||
@Autowired |
|||
private AlgorithmApplicationService algorithmApplicationService; |
|||
|
|||
@Override |
|||
public Result<List<KnowledgePointDraftEntity>> listDrafts(Long informationId) { |
|||
if (informationId == null) { |
|||
throw new BusinessErrorException("资料ID不能为空"); |
|||
} |
|||
List<KnowledgePointDraftEntity> drafts = knowledgePointDraftBaseService.list( |
|||
new LambdaQueryWrapper<KnowledgePointDraftEntity>() |
|||
.eq(KnowledgePointDraftEntity::getInformationId, informationId) |
|||
.orderByAsc(KnowledgePointDraftEntity::getId)); |
|||
return Result.success(drafts); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> updateDraft(Long draftId, String content) { |
|||
if (draftId == null) { |
|||
throw new BusinessErrorException("草稿ID不能为空"); |
|||
} |
|||
KnowledgePointDraftEntity draft = knowledgePointDraftBaseService.getById(draftId); |
|||
if (draft == null) { |
|||
throw new BusinessErrorException("草稿不存在"); |
|||
} |
|||
// 仅待审核状态的草稿可修改
|
|||
if (!AuditStatusEnum.PENDING.getValue().equals(draft.getAuditStatus())) { |
|||
throw new BusinessErrorException("已固化的草稿不可修改"); |
|||
} |
|||
draft.setContent(content); |
|||
knowledgePointDraftBaseService.updateById(draft); |
|||
return Result.success("修改成功"); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> deleteDraft(Long draftId) { |
|||
if (draftId == null) { |
|||
throw new BusinessErrorException("草稿ID不能为空"); |
|||
} |
|||
KnowledgePointDraftEntity draft = knowledgePointDraftBaseService.getById(draftId); |
|||
if (draft == null) { |
|||
throw new BusinessErrorException("草稿不存在"); |
|||
} |
|||
if (!AuditStatusEnum.PENDING.getValue().equals(draft.getAuditStatus())) { |
|||
throw new BusinessErrorException("已固化的草稿不可删除"); |
|||
} |
|||
knowledgePointDraftBaseService.removeById(draftId); |
|||
return Result.success("删除成功"); |
|||
} |
|||
|
|||
@Override |
|||
public Result<String> addDraft(Long informationId, String content, Integer knowledgeType) { |
|||
if (informationId == null) { |
|||
throw new BusinessErrorException("资料ID不能为空"); |
|||
} |
|||
// 校验资料存在且为待审核状态
|
|||
InformationEntity information = informationBaseService.getById(informationId); |
|||
if (information == null) { |
|||
throw new BusinessErrorException("资料不存在"); |
|||
} |
|||
if (!DraftStatusEnum.PENDING.getValue().equals(information.getDraftStatus())) { |
|||
throw new BusinessErrorException("该资料不在待审核状态,无法新增草稿"); |
|||
} |
|||
KnowledgePointDraftEntity draft = new KnowledgePointDraftEntity(); |
|||
draft.setInformationId(informationId); |
|||
draft.setContent(content); |
|||
draft.setAiContent(content); // 手动新增的草稿,aiContent 与 content 一致
|
|||
draft.setKnowledgeType(knowledgeType); |
|||
draft.setAuditStatus(AuditStatusEnum.PENDING.getValue()); |
|||
knowledgePointDraftBaseService.save(draft); |
|||
return Result.success("新增成功"); |
|||
} |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public Result<String> confirm(Long informationId) { |
|||
if (informationId == null) { |
|||
throw new BusinessErrorException("资料ID不能为空"); |
|||
} |
|||
|
|||
// 1. 查询资料,幂等校验
|
|||
InformationEntity information = informationBaseService.getById(informationId); |
|||
if (information == null) { |
|||
throw new BusinessErrorException("资料不存在"); |
|||
} |
|||
if (DraftStatusEnum.APPROVED.getValue().equals(information.getDraftStatus())) { |
|||
return Result.success("已固化,不可重复操作"); |
|||
} |
|||
if (!DraftStatusEnum.PENDING.getValue().equals(information.getDraftStatus())) { |
|||
throw new BusinessErrorException("该资料不在待审核状态"); |
|||
} |
|||
|
|||
// 2. 查询所有待审核草稿
|
|||
List<KnowledgePointDraftEntity> drafts = knowledgePointDraftBaseService.list( |
|||
new LambdaQueryWrapper<KnowledgePointDraftEntity>() |
|||
.eq(KnowledgePointDraftEntity::getInformationId, informationId) |
|||
.eq(KnowledgePointDraftEntity::getAuditStatus, AuditStatusEnum.PENDING.getValue())); |
|||
if (drafts.isEmpty()) { |
|||
throw new BusinessErrorException("没有待审核的草稿"); |
|||
} |
|||
|
|||
// 3. 将草稿 content 复制到正式知识点表
|
|||
List<KnowledgePointEntity> knowledgePoints = new ArrayList<>(); |
|||
for (KnowledgePointDraftEntity draft : drafts) { |
|||
KnowledgePointEntity kp = new KnowledgePointEntity(); |
|||
kp.setContent(draft.getContent()); |
|||
kp.setKnowledgeType(draft.getKnowledgeType()); |
|||
kp.setInformationId(informationId); |
|||
kp.setParseName(draft.getParseName()); |
|||
knowledgePoints.add(kp); |
|||
} |
|||
knowledgePointBaseService.saveBatch(knowledgePoints); |
|||
|
|||
// 4. 更新草稿 auditStatus 为已通过
|
|||
List<Long> draftIds = drafts.stream().map(KnowledgePointDraftEntity::getId).toList(); |
|||
knowledgePointDraftBaseService.lambdaUpdate() |
|||
.in(KnowledgePointDraftEntity::getId, draftIds) |
|||
.set(KnowledgePointDraftEntity::getAuditStatus, AuditStatusEnum.APPROVED.getValue()) |
|||
.update(); |
|||
|
|||
// 5. 更新虚拟资料 draftStatus = APPROVED(2)
|
|||
informationBaseService.lambdaUpdate() |
|||
.eq(InformationEntity::getId, informationId) |
|||
.set(InformationEntity::getDraftStatus, DraftStatusEnum.APPROVED.getValue()) |
|||
.update(); |
|||
|
|||
// 6. 触发聚类
|
|||
List<KnowledgePointDTO> kpList = knowledgePoints.stream() |
|||
.map(entity -> entity.toDTO(KnowledgePointDTO::new)) |
|||
.toList(); |
|||
algorithmApplicationService.postToClusteringByInformationId(informationId, kpList); |
|||
|
|||
log.info(">>> [草稿审核] 确认固化完成, informationId={}, 草稿数={}", informationId, drafts.size()); |
|||
return Result.success("确认成功"); |
|||
} |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
package com.project.interaction.domain.service; |
|||
|
|||
import com.project.interaction.domain.dto.AiExtractCallbackDTO; |
|||
|
|||
/** |
|||
* 算法服务知识点提取回调处理 |
|||
* 接收算法服务返回的草稿知识点,写入草稿表 |
|||
*/ |
|||
public interface AiExtractCallbackDomainService { |
|||
|
|||
/** |
|||
* 处理算法服务知识点提取回调 |
|||
* @param callback 回调参数 |
|||
*/ |
|||
void handleCallback(AiExtractCallbackDTO callback); |
|||
} |
|||
@ -1,16 +0,0 @@ |
|||
package com.project.interaction.domain.service; |
|||
|
|||
import com.project.interaction.domain.dto.DataExtractCallbackDTO; |
|||
|
|||
/** |
|||
* 数据服务解析回调处理 |
|||
* 每个子文件解析完成后回调,检查批次是否全部完成,全部完成则触发算法服务 |
|||
*/ |
|||
public interface DataExtractCallbackDomainService { |
|||
|
|||
/** |
|||
* 处理数据服务解析回调 |
|||
* @param callback 回调参数 |
|||
*/ |
|||
void handleCallback(DataExtractCallbackDTO callback); |
|||
} |
|||
@ -1,71 +0,0 @@ |
|||
package com.project.interaction.domain.service.impl; |
|||
|
|||
import com.project.information.domain.entity.InformationEntity; |
|||
import com.project.information.domain.entity.KnowledgePointDraftEntity; |
|||
import com.project.information.domain.enums.AuditStatusEnum; |
|||
import com.project.information.domain.enums.DraftStatusEnum; |
|||
import com.project.information.domain.service.InformationBaseService; |
|||
import com.project.information.domain.service.KnowledgePointDraftBaseService; |
|||
import com.project.interaction.domain.dto.AiExtractCallbackDTO; |
|||
import com.project.interaction.domain.service.AiExtractCallbackDomainService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.transaction.annotation.Transactional; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 算法服务知识点提取回调处理实现 |
|||
* 1. 将算法返回的草稿知识点写入 evaluator_knowledge_point_draft |
|||
* 2. 更新虚拟资料 draftStatus = PENDING(1) |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class AiExtractCallbackDomainServiceImpl implements AiExtractCallbackDomainService { |
|||
|
|||
@Autowired |
|||
private KnowledgePointDraftBaseService knowledgePointDraftBaseService; |
|||
|
|||
@Autowired |
|||
private InformationBaseService informationBaseService; |
|||
|
|||
@Override |
|||
@Transactional(rollbackFor = Exception.class) |
|||
public void handleCallback(AiExtractCallbackDTO callback) { |
|||
Long informationId = callback.getInformationId(); |
|||
List<AiExtractCallbackDTO.DraftItem> drafts = callback.getDrafts(); |
|||
|
|||
log.info(">>> [算法服务回调] 收到知识点提取回调, informationId={}, 草稿数={}", |
|||
informationId, drafts != null ? drafts.size() : 0); |
|||
|
|||
if (drafts == null || drafts.isEmpty()) { |
|||
log.warn(">>> [算法服务回调] 算法返回的草稿为空, informationId={}", informationId); |
|||
return; |
|||
} |
|||
|
|||
// 1. 保存草稿(aiContent = content 的副本)
|
|||
List<KnowledgePointDraftEntity> draftEntities = new ArrayList<>(); |
|||
for (AiExtractCallbackDTO.DraftItem item : drafts) { |
|||
KnowledgePointDraftEntity draft = new KnowledgePointDraftEntity(); |
|||
draft.setInformationId(informationId); |
|||
draft.setContent(item.getContent()); |
|||
draft.setAiContent(item.getContent()); |
|||
draft.setKnowledgeType(item.getKnowledgeType()); |
|||
draft.setParseName(item.getParseName()); |
|||
draft.setAuditStatus(AuditStatusEnum.PENDING.getValue()); |
|||
draftEntities.add(draft); |
|||
} |
|||
knowledgePointDraftBaseService.saveBatch(draftEntities); |
|||
|
|||
// 2. 更新虚拟资料 draftStatus = PENDING(1)
|
|||
// 注意:原始资料创建时已是 PENDING,此处为兜底保障
|
|||
informationBaseService.lambdaUpdate() |
|||
.eq(InformationEntity::getId, informationId) |
|||
.set(InformationEntity::getDraftStatus, DraftStatusEnum.PENDING.getValue()) |
|||
.update(); |
|||
|
|||
log.info(">>> [算法服务回调] 草稿保存完成, informationId={}, 草稿数={}", informationId, draftEntities.size()); |
|||
} |
|||
} |
|||
@ -1,106 +0,0 @@ |
|||
package com.project.interaction.domain.service.impl; |
|||
|
|||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
|||
import com.project.information.domain.entity.InformationEntity; |
|||
import com.project.information.domain.entity.InformationFileEntity; |
|||
import com.project.information.domain.enums.FileParseStatusEnum; |
|||
import com.project.information.domain.service.InformationBaseService; |
|||
import com.project.information.domain.service.InformationFileBaseService; |
|||
import com.project.interaction.domain.dto.AiExtractRequestDTO; |
|||
import com.project.interaction.domain.dto.DataExtractCallbackDTO; |
|||
import com.project.interaction.domain.service.DataExtractCallbackDomainService; |
|||
import com.project.interaction.domain.service.PostToAiExtractDomainService; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Service; |
|||
|
|||
import java.util.ArrayList; |
|||
import java.util.List; |
|||
|
|||
/** |
|||
* 数据服务解析回调处理实现 |
|||
* 1. 更新子文件解析状态和解析文本 |
|||
* 2. 检查该虚拟资料下所有子文件是否全部完成 |
|||
* 3. 全部完成 → 调用算法服务知识点提取 |
|||
*/ |
|||
@Service |
|||
@Slf4j |
|||
public class DataExtractCallbackDomainServiceImpl implements DataExtractCallbackDomainService { |
|||
|
|||
@Autowired |
|||
private InformationFileBaseService informationFileBaseService; |
|||
|
|||
@Autowired |
|||
private InformationBaseService informationBaseService; |
|||
|
|||
@Autowired |
|||
private PostToAiExtractDomainService postToAiExtractDomainService; |
|||
|
|||
@Override |
|||
public void handleCallback(DataExtractCallbackDTO callback) { |
|||
Long fileId = callback.getFileId(); |
|||
Long informationId = callback.getInformationId(); |
|||
|
|||
log.info(">>> [数据服务回调] 收到子文件解析回调, fileId={}, informationId={}, status={}", |
|||
fileId, informationId, callback.getParseStatus()); |
|||
|
|||
// 1. 更新子文件解析状态
|
|||
InformationFileEntity file = informationFileBaseService.getById(fileId); |
|||
if (file == null) { |
|||
log.error(">>> [数据服务回调] 子文件不存在, fileId={}", fileId); |
|||
return; |
|||
} |
|||
file.setParseStatus(callback.getParseStatus()); |
|||
if (FileParseStatusEnum.Success.getValue().equals(callback.getParseStatus())) { |
|||
file.setParsedText(callback.getParsedText()); |
|||
} |
|||
informationFileBaseService.updateById(file); |
|||
|
|||
// 2. 如果解析失败,记录日志(不阻断其他文件)
|
|||
if (!FileParseStatusEnum.Success.getValue().equals(callback.getParseStatus())) { |
|||
log.warn(">>> [数据服务回调] 子文件解析失败, fileId={}, error={}", fileId, callback.getErrorMsg()); |
|||
return; |
|||
} |
|||
|
|||
// 3. 检查该虚拟资料下所有子文件是否全部完成
|
|||
List<InformationFileEntity> allFiles = informationFileBaseService.list( |
|||
new LambdaQueryWrapper<InformationFileEntity>() |
|||
.eq(InformationFileEntity::getInformationId, informationId)); |
|||
|
|||
boolean allDone = allFiles.stream() |
|||
.allMatch(f -> FileParseStatusEnum.Success.getValue().equals(f.getParseStatus()) |
|||
|| FileParseStatusEnum.Failed.getValue().equals(f.getParseStatus())); |
|||
|
|||
if (!allDone) { |
|||
log.info(">>> [数据服务回调] 虚拟资料 {} 下还有子文件未完成解析,等待中", informationId); |
|||
return; |
|||
} |
|||
|
|||
// 4. 全部完成 → 调用算法服务知识点提取
|
|||
log.info(">>> [数据服务回调] 虚拟资料 {} 下所有子文件解析完成,开始调用算法服务", informationId); |
|||
|
|||
// 查询虚拟资料获取内容分类信息(从子文件中获取)
|
|||
List<AiExtractRequestDTO.FileContent> fileContents = new ArrayList<>(); |
|||
for (InformationFileEntity f : allFiles) { |
|||
// 只传解析成功的文件
|
|||
if (FileParseStatusEnum.Success.getValue().equals(f.getParseStatus()) && f.getParsedText() != null) { |
|||
AiExtractRequestDTO.FileContent fc = new AiExtractRequestDTO.FileContent(); |
|||
fc.setFileName(f.getFileName()); |
|||
fc.setContentCategory(String.valueOf(f.getContentCategory())); |
|||
fc.setParsedText(f.getParsedText()); |
|||
fileContents.add(fc); |
|||
} |
|||
} |
|||
|
|||
if (fileContents.isEmpty()) { |
|||
log.warn(">>> [数据服务回调] 虚拟资料 {} 下没有成功解析的子文件", informationId); |
|||
return; |
|||
} |
|||
|
|||
AiExtractRequestDTO request = new AiExtractRequestDTO(); |
|||
request.setInformationId(informationId); |
|||
request.setFiles(fileContents); |
|||
|
|||
postToAiExtractDomainService.postToAiExtract(request); |
|||
} |
|||
} |
|||
Loading…
Reference in new issue