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