标注结果比较优化

This commit is contained in:
wh
2026-04-29 14:02:01 +08:00
parent ca81514d43
commit 74674990d8
15 changed files with 129 additions and 52 deletions

View File

@@ -1,5 +1,6 @@
package com.labelsys.backend.service;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.springframework.stereotype.Service;
@@ -15,7 +16,8 @@ import com.labelsys.backend.dto.response.AnnotationResultCompareResponse;
import com.labelsys.backend.dto.response.AnnotationResultResponse;
import com.labelsys.backend.entity.AnnotationResult;
import com.labelsys.backend.entity.SourceResource;
import com.labelsys.backend.enums.RuntimeResultStatus;
import com.labelsys.backend.enums.AnnotationResultStatus;
import com.labelsys.backend.enums.QaContentStorageMode;
import com.labelsys.backend.mapper.AnnotationResultMapper;
import com.labelsys.backend.mapper.SourceResourceMapper;
@@ -30,17 +32,18 @@ public class AnnotationResultService {
private final AnnotationResultMapper annotationResultMapper;
private final SourceResourceMapper sourceResourceMapper;
private final DataPermissionService dataPermissionService;
private final ObjectStorageService objectStorageService;
public PageResult<AnnotationResultResponse> pageResults(LoginUser currentUser, AnnotationResultPageQuery query) {
List<String> allowedRoles = dataPermissionService.getAllowedRoles(currentUser);
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
LambdaQueryWrapper<AnnotationResult> wrapper =
new LambdaQueryWrapper<AnnotationResult>().eq(AnnotationResult::getCompanyId, currentUser.companyId())
LambdaQueryWrapper<AnnotationResult> wrapper = new LambdaQueryWrapper<AnnotationResult>()
.eq(AnnotationResult::getCompanyId, currentUser.companyId())
.eq(query.taskId() != null, AnnotationResult::getTaskId, query.taskId())
.eq(query.resourceId() != null, AnnotationResult::getResourceId, query.resourceId())
.eq(query.requiresManualReview() != null, AnnotationResult::getRequiresManualReview,
query.requiresManualReview());
query.requiresManualReview());
if (shouldFilterByUserId) {
wrapper.eq(AnnotationResult::getCreatorId, currentUser.userId());
@@ -54,49 +57,104 @@ public class AnnotationResultService {
Page<AnnotationResult> resultPage = annotationResultMapper.selectPage(page, wrapper);
List<AnnotationResultResponse> records = resultPage.getRecords().stream().map(this::toResponse)
.filter(response -> query.runtimeStatus() == null || query.runtimeStatus().equals(response.runtimeStatus()))
.toList();
.filter(response -> query.runtimeStatus() == null
|| query.runtimeStatus().equals(response.runtimeStatus()))
.toList();
return new PageResult<>(records, resultPage.getTotal(), (int)resultPage.getCurrent(),
(int)resultPage.getSize());
return new PageResult<>(records, resultPage.getTotal(), (int) resultPage.getCurrent(),
(int) resultPage.getSize());
}
public AnnotationResultResponse getResult(LoginUser currentUser, Long resultId) {
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
if (result == null) {
log.warn("Result not found or cross-tenant access attempt: resultId={}, companyId={}, userId={}", resultId,
currentUser.companyId(), currentUser.userId());
currentUser.companyId(), currentUser.userId());
throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在");
}
return toResponse(result);
}
private AnnotationResultResponse toResponse(AnnotationResult result) {
return new AnnotationResultResponse(result.getId(), result.getTaskId(), result.getResourceId(),
deriveStatus(result), result.getRequiresManualReview(), result.getIsDeleted(),
result.getQaContentStorageMode(), result.getReviewComment(), result.getReviewedAt(),
result.getCreatedAt());
}
private AnnotationResultStatus deriveStatus(AnnotationResult result) {
if (Boolean.TRUE.equals(result.getIsDeleted())) {
return AnnotationResultStatus.ARCHIVED;
}
if (Boolean.TRUE.equals(result.getRequiresManualReview())) {
return AnnotationResultStatus.MANUAL_REVIEW_PENDING;
}
return AnnotationResultStatus.AUTO_ARCHIVE_PENDING;
}
public AnnotationResultCompareResponse compareResult(LoginUser currentUser, Long resultId) {
AnnotationResult result = annotationResultMapper.findActiveByIdAndCompanyId(resultId, currentUser.companyId());
if (result == null) {
log.warn("Result not found or cross-tenant access attempt: resultId={}, companyId={}, userId={}", resultId,
currentUser.companyId(), currentUser.userId());
currentUser.companyId(), currentUser.userId());
throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在");
}
String qaContentJson = resolveQaContent(result);
SourceResource resource = sourceResourceMapper.selectById(result.getResourceId());
return new AnnotationResultCompareResponse(result.getId(), result.getTaskId(), result.getResourceId(),
result.getQaContentJson(), result.getDiffSummary(), result.getQaContentStorageMode(),
result.getQaContentFilePath(), resource == null ? null : resource.getFilePath());
return new AnnotationResultCompareResponse(
result.getId(),
result.getTaskId(),
result.getResourceId(),
qaContentJson,
result.getDiffSummary(),
result.getQaContentStorageMode(),
result.getQaContentFilePath(),
resource == null ? null : resource.getFilePath());
}
private AnnotationResultResponse toResponse(AnnotationResult result) {
return new AnnotationResultResponse(result.getId(), result.getTaskId(), result.getResourceId(),
deriveStatus(result), result.getRequiresManualReview(), result.getIsDeleted(),
result.getQaContentStorageMode(), result.getReviewComment(), result.getReviewedAt(), result.getCreatedAt());
private String resolveQaContent(AnnotationResult result) {
if (QaContentStorageMode.EXTERNAL.name().equals(result.getQaContentStorageMode())) {
if (result.getQaContentFilePath() == null || result.getQaContentFilePath().isBlank()) {
log.warn("External storage mode but file path is empty, resultId={}", result.getId());
return "{}";
}
try {
String filePath = result.getQaContentFilePath();
String bucketName = extractBucketName(filePath);
String objectKey = extractObjectKey(filePath);
byte[] content = objectStorageService.download(bucketName, objectKey);
return new String(content, StandardCharsets.UTF_8);
} catch (Exception e) {
log.error("Failed to download external qa content, resultId={}, filePath={}",
result.getId(), result.getQaContentFilePath(), e);
throw new BusinessException(ResultCode.ERROR, "下载问答内容失败");
}
} else {
return result.getQaContentJson() != null ? result.getQaContentJson() : "{}";
}
}
private String deriveStatus(AnnotationResult result) {
if (Boolean.TRUE.equals(result.getIsDeleted())) {
return RuntimeResultStatus.ARCHIVED.name();
private String extractBucketName(String filePath) {
if (filePath.startsWith("/")) {
filePath = filePath.substring(1);
}
if (Boolean.TRUE.equals(result.getRequiresManualReview())) {
return RuntimeResultStatus.MANUAL_REVIEW_PENDING.name();
int firstSlash = filePath.indexOf("/");
if (firstSlash > 0) {
return filePath.substring(0, firstSlash);
}
return RuntimeResultStatus.AUTO_ARCHIVE_PENDING.name();
throw new BusinessException(ResultCode.BAD_REQUEST, "无效的文件路径格式");
}
private String extractObjectKey(String filePath) {
if (filePath.startsWith("/")) {
filePath = filePath.substring(1);
}
int firstSlash = filePath.indexOf("/");
if (firstSlash > 0 && firstSlash < filePath.length() - 1) {
return filePath.substring(firstSlash + 1);
}
throw new BusinessException(ResultCode.BAD_REQUEST, "无效的文件路径格式");
}
}