AiGlossaryService.java
package com.yumu.noveltranslator.domain.service;
import com.yumu.noveltranslator.domain.model.AiGlossary;
import com.yumu.noveltranslator.port.out.GlossaryRepositoryPort;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* AI 术语表服务
* 负责维护每个小说项目的 AI 提取术语
* 支持 upsert(同一项目 + 原文术语已存在则更新译文)
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class AiGlossaryService {
private final GlossaryRepositoryPort glossaryPort;
/**
* 获取项目所有已确认的术语
* 如果表不存在或查询失败,返回空列表(不阻断翻译流程)
*/
public List<AiGlossary> getProjectGlossary(Long projectId) {
try {
return glossaryPort.findAiGlossaryByProjectIdAndStatus(projectId, "confirmed");
} catch (Exception e) {
log.warn("获取 AI 术语表失败(可能表未创建): {}", e.getMessage());
return List.of();
}
}
/**
* 添加术语(upsert)
* 如果同一项目下 sourceWord 已存在,则更新 targetWord;否则插入新记录
* AI 提取的术语默认状态为 pending
*/
public void addTerm(Long projectId, String sourceWord, String targetWord,
String context, String entityType, Long chapterId) {
glossaryPort.upsertAiGlossary(projectId, sourceWord, targetWord, context, entityType, chapterId);
log.debug("AI 术语表 upsert: projectId={}, sourceWord={}", projectId, sourceWord);
}
/**
* 批量添加术语
*/
public void batchAddTerms(Long projectId, List<AiGlossary> terms) {
if (terms == null || terms.isEmpty()) {
return;
}
for (AiGlossary term : terms) {
term.setProjectId(projectId);
if (term.getStatus() == null) {
term.setStatus("pending");
}
if (term.getConfidence() == null) {
term.setConfidence(0.8);
}
addTerm(projectId, term.getSourceWord(), term.getTargetWord(),
term.getContext(), term.getEntityType(), term.getChapterId());
}
log.info("批量添加 AI 术语: projectId={}, count={}", projectId, terms.size());
}
/**
* 更新术语状态(pending -> confirmed / rejected)
*/
public boolean updateTermStatus(Long termId, String status) {
return glossaryPort.findAiGlossaryById(termId).map(term -> {
term.setStatus(status);
glossaryPort.updateAiGlossary(term);
return true;
}).orElseGet(() -> {
log.warn("术语不存在: termId={}", termId);
return false;
});
}
/**
* 删除术语
*/
public boolean deleteTerm(Long termId) {
glossaryPort.deleteAiGlossary(termId);
return true;
}
/**
* 获取项目的待确认术语
*/
public List<AiGlossary> getPendingTerms(Long projectId) {
return glossaryPort.findAiGlossaryByProjectIdAndStatus(projectId, "pending");
}
}