package com.labelsys.backend.service; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.labelsys.backend.common.ResultCode; import com.labelsys.backend.common.exception.BusinessException; import com.labelsys.backend.context.LoginUser; import com.labelsys.backend.dto.common.PageResult; import com.labelsys.backend.dto.request.AnnotationResultPageQuery; 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.mapper.AnnotationResultMapper; import com.labelsys.backend.mapper.SourceResourceMapper; import java.util.Comparator; import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class AnnotationResultService { private final AnnotationResultMapper annotationResultMapper; private final SourceResourceMapper sourceResourceMapper; public PageResult pageResults(LoginUser currentUser, AnnotationResultPageQuery query) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper() .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()) .orderByDesc(AnnotationResult::getCreatedAt); List records = annotationResultMapper.selectList(wrapper).stream() .map(this::toResponse) .filter(response -> query.runtimeStatus() == null || query.runtimeStatus().equals(response.runtimeStatus())) .sorted(Comparator.comparing(AnnotationResultResponse::createdAt, Comparator.nullsLast(Comparator.naturalOrder())).reversed()) .toList(); return paginate(records, query.pageNo(), query.pageSize()); } public AnnotationResultResponse getResult(LoginUser currentUser, Long resultId) { AnnotationResult result = annotationResultMapper.selectById(resultId); if (result == null || !currentUser.companyId().equals(result.getCompanyId())) { throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在"); } return toResponse(result); } public AnnotationResultCompareResponse compareResult(LoginUser currentUser, Long resultId) { AnnotationResult result = annotationResultMapper.selectById(resultId); if (result == null || !currentUser.companyId().equals(result.getCompanyId())) { throw new BusinessException(ResultCode.NOT_FOUND, "结果不存在"); } 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()); } 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 deriveStatus(AnnotationResult result) { if (Boolean.TRUE.equals(result.getIsDeleted())) { return RuntimeResultStatus.ARCHIVED.name(); } if (Boolean.TRUE.equals(result.getRequiresManualReview())) { return RuntimeResultStatus.MANUAL_REVIEW_PENDING.name(); } return RuntimeResultStatus.AUTO_ARCHIVE_PENDING.name(); } private PageResult paginate(List records, Integer pageNo, Integer pageSize) { int actualPageNo = pageNo == null || pageNo < 1 ? 1 : pageNo; int actualPageSize = pageSize == null || pageSize < 1 ? 10 : pageSize; int fromIndex = Math.min((actualPageNo - 1) * actualPageSize, records.size()); int toIndex = Math.min(fromIndex + actualPageSize, records.size()); return new PageResult<>(records.subList(fromIndex, toIndex), (long) records.size(), actualPageNo, actualPageSize); } }