|
|
|
@ -2,21 +2,38 @@ package com.project.milvus.domain.service.impl; |
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollectionUtil; |
|
|
|
import cn.hutool.core.util.EnumUtil; |
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|
|
|
import com.project.base.domain.exception.MissingParameterException; |
|
|
|
import com.project.information.domain.entity.KnowledgePointEntity; |
|
|
|
import com.project.information.domain.service.KnowledgePointBaseService; |
|
|
|
import com.project.milvus.domain.dto.TitleVector; |
|
|
|
import com.project.milvus.domain.service.CheckMilvusDomainService; |
|
|
|
import com.project.question.domain.dto.QuestionDTO; |
|
|
|
import com.project.question.domain.entity.QuestionEntity; |
|
|
|
import com.project.question.domain.service.QuestionBaseService; |
|
|
|
import com.project.task.domain.enums.QuestionTypeEnum; |
|
|
|
import org.apache.commons.codec.digest.DigestUtils; |
|
|
|
import org.apache.commons.collections4.CollectionUtils; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
|
|
|
|
import java.util.List; |
|
|
|
import java.util.*; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
|
|
|
|
/** |
|
|
|
* 校验扩展 |
|
|
|
*/ |
|
|
|
@Service |
|
|
|
public class CheckMilvusDomainServiceImpl implements CheckMilvusDomainService { |
|
|
|
@Autowired |
|
|
|
private KnowledgePointBaseService knowledgePointBaseService; |
|
|
|
@Autowired |
|
|
|
private QuestionBaseService questionBaseService; |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
public void check(TitleVector title) { |
|
|
|
public void checkBasic(TitleVector title) { |
|
|
|
if (title == null) { |
|
|
|
throw new MissingParameterException("请求参数缺失或格式错误"); |
|
|
|
} |
|
|
|
@ -32,8 +49,85 @@ public class CheckMilvusDomainServiceImpl implements CheckMilvusDomainService { |
|
|
|
throw new MissingParameterException("向量格式错误"); |
|
|
|
} |
|
|
|
|
|
|
|
if(!EnumUtil.contains(QuestionTypeEnum.class,title.getType())){ |
|
|
|
throw new MissingParameterException("题目类型不存在"); |
|
|
|
// 校验 QuestionDetailDTO 及其内部参数
|
|
|
|
QuestionDTO.QuestionDetailDTO detailDTO = title.QuestionDetailDTO; |
|
|
|
if (detailDTO == null) { |
|
|
|
throw new MissingParameterException("题目详情不能为空"); |
|
|
|
} |
|
|
|
|
|
|
|
if (StringUtils.isBlank(detailDTO.getQuestionContent())) { |
|
|
|
throw new MissingParameterException("题干不能为空"); |
|
|
|
} |
|
|
|
|
|
|
|
if (detailDTO.getType() == null) { |
|
|
|
throw new MissingParameterException("题目类型不能为空"); |
|
|
|
} |
|
|
|
|
|
|
|
// 校验题目类型值是否有效(1=单选题,2=多选题,3=判断题)
|
|
|
|
if (QuestionTypeEnum.findByValue(detailDTO.getType()) == null) { |
|
|
|
throw new MissingParameterException("题目类型值无效"); |
|
|
|
} |
|
|
|
|
|
|
|
if (CollectionUtil.isEmpty(detailDTO.getOptions())) { |
|
|
|
throw new MissingParameterException("选项不能为空"); |
|
|
|
} |
|
|
|
|
|
|
|
// 校验 options 的每个键值对都不为空
|
|
|
|
for (Map.Entry<String, String> entry : detailDTO.getOptions().entrySet()) { |
|
|
|
if (StringUtils.isBlank(entry.getKey())) { |
|
|
|
throw new MissingParameterException("选项键不能为空"); |
|
|
|
} |
|
|
|
if (StringUtils.isBlank(entry.getValue())) { |
|
|
|
throw new MissingParameterException("选项值不能为空"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (StringUtils.isBlank(detailDTO.getRightAnswer())) { |
|
|
|
throw new MissingParameterException("正确答案不能为空"); |
|
|
|
} |
|
|
|
|
|
|
|
if (StringUtils.isBlank(detailDTO.getAnalysis())) { |
|
|
|
throw new MissingParameterException("题目解析不能为空"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public void checkUnique(TitleVector title) { |
|
|
|
// 题目的 HASH 校验
|
|
|
|
String questionHash = buildQuestionHash(title.QuestionDetailDTO, title); |
|
|
|
QuestionEntity questionEntity = questionBaseService.getOne(new QueryWrapper<QuestionEntity>().eq("unique_hash", questionHash)); |
|
|
|
if (questionEntity != null) { |
|
|
|
throw new IllegalArgumentException("题目已存在"); // 空值防护
|
|
|
|
} |
|
|
|
title.setUniqueHash(questionHash); |
|
|
|
} |
|
|
|
public String buildQuestionHash(QuestionDTO.QuestionDetailDTO detailDTO, TitleVector title){ |
|
|
|
//查询知识点并提取非空的 parseName
|
|
|
|
List<KnowledgePointEntity> knowledgePointEntities = knowledgePointBaseService.listByIds(title.getPointIdsList()); |
|
|
|
if (CollectionUtils.isEmpty(knowledgePointEntities)) { |
|
|
|
throw new IllegalArgumentException("知识点不存在"); // 空值防护
|
|
|
|
} |
|
|
|
|
|
|
|
//提取非空 parseName 并去重,避免重复拼接
|
|
|
|
Set<String> parseNameSet = knowledgePointEntities.stream() |
|
|
|
.filter(entity -> StringUtils.isNotBlank(entity.getParseName())) // 更严谨的非空判断
|
|
|
|
.map(KnowledgePointEntity::getParseName) |
|
|
|
.collect(Collectors.toSet()); |
|
|
|
|
|
|
|
//知识点名称排序(保证拼接顺序固定,避免"a,b"和"b,a"生成不同 hash)
|
|
|
|
List<String> sortedParseNames = new ArrayList<>(parseNameSet); |
|
|
|
Collections.sort(sortedParseNames); // 修正原代码"排序 Set"的语法错误
|
|
|
|
|
|
|
|
//规范化拼接知识点名称(固定分隔符,避免歧义)
|
|
|
|
String canonicalKnowledgePoints = sortedParseNames.stream() |
|
|
|
.collect(Collectors.joining(",")); |
|
|
|
|
|
|
|
//生成最终哈希(拆分拼接逻辑,提升可读性;增加分隔符避免字符串拼接歧义)
|
|
|
|
String rawContent = String.format("%s|%s|%s", |
|
|
|
StringUtils.isNotBlank(detailDTO.getQuestionContent()) ? detailDTO.getQuestionContent() : "", |
|
|
|
StringUtils.isNotBlank(title.getPointIdsHash()) ? title.getPointIdsHash() : "", |
|
|
|
DigestUtils.md5Hex(canonicalKnowledgePoints) |
|
|
|
); |
|
|
|
return DigestUtils.md5Hex(rawContent); |
|
|
|
} |
|
|
|
} |
|
|
|
|