QA问答对审核功能以及历史记录归档管理优化
This commit is contained in:
@@ -4,6 +4,7 @@ import com.labelsys.backend.context.UserContext;
|
|||||||
import com.labelsys.backend.dto.common.PageResult;
|
import com.labelsys.backend.dto.common.PageResult;
|
||||||
import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery;
|
import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery;
|
||||||
import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse;
|
import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse;
|
||||||
|
import com.labelsys.backend.dto.response.FileContentResponse;
|
||||||
import com.labelsys.backend.service.AnnotationResultArchiveService;
|
import com.labelsys.backend.service.AnnotationResultArchiveService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.Parameter;
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
@@ -38,4 +39,12 @@ public class AnnotationResultArchiveController {
|
|||||||
@PathVariable Long id) {
|
@PathVariable Long id) {
|
||||||
return ResponseEntity.ok(annotationResultArchiveService.getHistory(UserContext.requireUser(), id));
|
return ResponseEntity.ok(annotationResultArchiveService.getHistory(UserContext.requireUser(), id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "加载归档文件内容")
|
||||||
|
@GetMapping("/{id}/content")
|
||||||
|
public ResponseEntity<FileContentResponse> loadFileContent(
|
||||||
|
@Parameter(description = "历史记录ID", example = "901")
|
||||||
|
@PathVariable Long id) {
|
||||||
|
return ResponseEntity.ok(annotationResultArchiveService.loadFileContent(UserContext.requireUser(), id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -7,14 +7,20 @@ import java.time.LocalDateTime;
|
|||||||
|
|
||||||
@Schema(description = "归档历史响应")
|
@Schema(description = "归档历史响应")
|
||||||
public record AnnotationResultHistoryResponse(
|
public record AnnotationResultHistoryResponse(
|
||||||
@Schema(description = "历史记录ID", example = "901") Long id,
|
@Schema(description = "历史记录ID, 不显示", example = "901") Long id,
|
||||||
@Schema(description = "来源结果ID", example = "802") Long sourceResultId,
|
//@Schema(description = "来源结果ID", example = "802") Long sourceResultId,
|
||||||
@Schema(description = "任务ID", example = "701") Long taskId,
|
@Schema(description = "任务ID", example = "191000000000000301") Long taskId,
|
||||||
@Schema(description = "资源ID", example = "601") Long resourceId,
|
@Schema(description = "任务名称", example = "产品说明书标注") String taskName, // 新增
|
||||||
|
@Schema(description = "资源ID", example = "191000000000000101") Long resourceId,
|
||||||
|
@Schema(description = "资源名称", example = "产品A说明书.pdf") String resourceName, // 新增
|
||||||
|
|
||||||
@Schema(description = "问答内容文件路径", example = "annotation-results/2/qa/802.json") String qaContentFilePath,
|
@Schema(description = "问答内容文件路径", example = "annotation-results/2/qa/802.json") String qaContentFilePath,
|
||||||
@Schema(description = "归档原因", example = "审核通过后归档") String archiveReason,
|
@Schema(description = "归档原因", example = "审核通过后归档") String archiveReason,
|
||||||
@Schema(description = "归档操作人ID", example = "5") Long archivedBy,
|
@Schema(description = "归档操作人ID", example = "5") Long archivedBy,
|
||||||
@Schema(description = "归档时间", example = "2026-05-06T10:30:00") LocalDateTime archivedAt,
|
@Schema(description = "归档时间", example = "2026-05-06T10:30:00") LocalDateTime archivedAt,
|
||||||
@Schema(description = "创建时间", example = "2026-05-06T10:30:00") LocalDateTime createdAt
|
@Schema(description = "创建时间", example = "2026-05-06T10:30:00") LocalDateTime createdAt,
|
||||||
|
@Schema(description = "审核人ID,自动归档时为null", example = "5") Long reviewerId,
|
||||||
|
@Schema(description = "审核人姓名,自动归档时为auto", example = "张三") String reviewerName,
|
||||||
|
@Schema(description = "审核意见,自动归档时为auto", example = "内容符合要求") String reviewerComment
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,9 @@ import java.time.LocalDateTime;
|
|||||||
public record AnnotationResultResponse(
|
public record AnnotationResultResponse(
|
||||||
@Schema(description = "结果ID", example = "191000000000000401") Long id,
|
@Schema(description = "结果ID", example = "191000000000000401") Long id,
|
||||||
@Schema(description = "任务ID", example = "191000000000000301") Long taskId,
|
@Schema(description = "任务ID", example = "191000000000000301") Long taskId,
|
||||||
|
@Schema(description = "任务名称", example = "产品说明书标注") String taskName, // 新增
|
||||||
@Schema(description = "资源ID", example = "191000000000000101") Long resourceId,
|
@Schema(description = "资源ID", example = "191000000000000101") Long resourceId,
|
||||||
|
@Schema(description = "资源名称", example = "产品A说明书.pdf") String resourceName, // 新增
|
||||||
@Schema(description = "标注结果状态", example = "MANUAL_REVIEW_PENDING") AnnotationResultStatus runtimeStatus,
|
@Schema(description = "标注结果状态", example = "MANUAL_REVIEW_PENDING") AnnotationResultStatus runtimeStatus,
|
||||||
@Schema(description = "是否需要人工审核", example = "true") Boolean requiresManualReview,
|
@Schema(description = "是否需要人工审核", example = "true") Boolean requiresManualReview,
|
||||||
@Schema(description = "是否已删除", example = "false") Boolean isDeleted,
|
@Schema(description = "是否已删除", example = "false") Boolean isDeleted,
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.labelsys.backend.dto.response;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
|
@Schema(description = "文件内容响应")
|
||||||
|
public record FileContentResponse(
|
||||||
|
@Schema(description = "文件路径", example = "annotation-results/2/qa/801.json") String filePath,
|
||||||
|
@Schema(description = "文件内容") String content,
|
||||||
|
@Schema(description = "文件大小(字节)", example = "1024") Integer size
|
||||||
|
) {
|
||||||
|
}
|
||||||
@@ -33,6 +33,13 @@ public class AnnotationResult {
|
|||||||
@TableField("resource_id")
|
@TableField("resource_id")
|
||||||
private Long resourceId;
|
private Long resourceId;
|
||||||
|
|
||||||
|
// 添加字段
|
||||||
|
@TableField("task_name")
|
||||||
|
private String taskName;
|
||||||
|
|
||||||
|
@TableField("resource_name")
|
||||||
|
private String resourceName;
|
||||||
|
|
||||||
@TableField("qa_content_file_path")
|
@TableField("qa_content_file_path")
|
||||||
private String qaContentFilePath;
|
private String qaContentFilePath;
|
||||||
|
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package com.labelsys.backend.entity;
|
|||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.labelsys.backend.enums.UserRole;
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@Builder
|
@Builder
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@@ -17,18 +17,25 @@ import lombok.NoArgsConstructor;
|
|||||||
@TableName("annotation_result_history")
|
@TableName("annotation_result_history")
|
||||||
public class AnnotationResultHistory {
|
public class AnnotationResultHistory {
|
||||||
@TableId(type = IdType.INPUT)
|
@TableId(type = IdType.INPUT)
|
||||||
private Long id;
|
private Long id;
|
||||||
private Long companyId;
|
private Long companyId;
|
||||||
private Long creatorId;
|
private Long creatorId;
|
||||||
private String creatorRole;
|
private String creatorRole;
|
||||||
private Long sourceResultId;
|
private Long sourceResultId;
|
||||||
private Long taskId;
|
private Long taskId;
|
||||||
private Long resourceId;
|
private Long resourceId;
|
||||||
|
private String taskName;
|
||||||
|
private String resourceName;
|
||||||
//private String qaContentJson;
|
//private String qaContentJson;
|
||||||
private String qaContentStorageMode;
|
// private String qaContentStorageMode;
|
||||||
private String qaContentFilePath;
|
private String qaContentFilePath;
|
||||||
private String archiveReason;
|
private String archiveReason;
|
||||||
private Long archivedBy;
|
private Long archivedBy;
|
||||||
private LocalDateTime archivedAt;
|
private LocalDateTime archivedAt;
|
||||||
private LocalDateTime createdAt;
|
private LocalDateTime createdAt;
|
||||||
|
|
||||||
|
// 新增审核人相关字段
|
||||||
|
private Long reviewerId;
|
||||||
|
private String reviewerName;
|
||||||
|
private String reviewerComment;
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import com.labelsys.backend.context.LoginUser;
|
|||||||
import com.labelsys.backend.dto.common.PageResult;
|
import com.labelsys.backend.dto.common.PageResult;
|
||||||
import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery;
|
import com.labelsys.backend.dto.request.AnnotationResultHistoryPageQuery;
|
||||||
import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse;
|
import com.labelsys.backend.dto.response.AnnotationResultHistoryResponse;
|
||||||
|
import com.labelsys.backend.dto.response.FileContentResponse;
|
||||||
import com.labelsys.backend.dto.response.MergeReviewResultResponse;
|
import com.labelsys.backend.dto.response.MergeReviewResultResponse;
|
||||||
import com.labelsys.backend.entity.AnnotationResult;
|
import com.labelsys.backend.entity.AnnotationResult;
|
||||||
import com.labelsys.backend.entity.AnnotationResultHistory;
|
import com.labelsys.backend.entity.AnnotationResultHistory;
|
||||||
@@ -91,14 +92,19 @@ public class AnnotationResultArchiveService {
|
|||||||
private AnnotationResultHistoryResponse toResponse(AnnotationResultHistory history) {
|
private AnnotationResultHistoryResponse toResponse(AnnotationResultHistory history) {
|
||||||
return new AnnotationResultHistoryResponse(
|
return new AnnotationResultHistoryResponse(
|
||||||
history.getId(),
|
history.getId(),
|
||||||
history.getSourceResultId(),
|
// history.getSourceResultId(),
|
||||||
history.getTaskId(),
|
history.getTaskId(),
|
||||||
|
history.getTaskName(), // 新增
|
||||||
history.getResourceId(),
|
history.getResourceId(),
|
||||||
|
history.getResourceName(), // 新增
|
||||||
history.getQaContentFilePath(),
|
history.getQaContentFilePath(),
|
||||||
history.getArchiveReason(),
|
history.getArchiveReason(),
|
||||||
history.getArchivedBy(),
|
history.getArchivedBy(),
|
||||||
history.getArchivedAt(),
|
history.getArchivedAt(),
|
||||||
history.getCreatedAt()
|
history.getCreatedAt(),
|
||||||
|
history.getReviewerId(),
|
||||||
|
history.getReviewerName(),
|
||||||
|
history.getReviewerComment()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +141,7 @@ public class AnnotationResultArchiveService {
|
|||||||
LocalDateTime archivedAt = LocalDateTime.now();
|
LocalDateTime archivedAt = LocalDateTime.now();
|
||||||
|
|
||||||
// 从对象存储读取 qa.json 内容
|
// 从对象存储读取 qa.json 内容
|
||||||
String qaContentJson = loadQaContentJson(result);
|
// String qaContentJson = loadQaContentJson(result);
|
||||||
|
|
||||||
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
||||||
.id(IdGenerator.nextId())
|
.id(IdGenerator.nextId())
|
||||||
@@ -144,12 +150,17 @@ public class AnnotationResultArchiveService {
|
|||||||
.creatorRole(result.getCreatorRole())
|
.creatorRole(result.getCreatorRole())
|
||||||
.sourceResultId(result.getId())
|
.sourceResultId(result.getId())
|
||||||
.taskId(result.getTaskId())
|
.taskId(result.getTaskId())
|
||||||
|
.taskName(result.getTaskName())
|
||||||
.resourceId(result.getResourceId())
|
.resourceId(result.getResourceId())
|
||||||
|
.resourceName(result.getResourceName())
|
||||||
//.qaContentJson(qaContentJson) // 使用从对象存储读取的内容
|
//.qaContentJson(qaContentJson) // 使用从对象存储读取的内容
|
||||||
.qaContentFilePath(result.getQaContentFilePath())
|
.qaContentFilePath(result.getQaContentFilePath())
|
||||||
.archiveReason(archiveReason)
|
.archiveReason(archiveReason)
|
||||||
.archivedBy(reviewerId)
|
.archivedBy(reviewerId)
|
||||||
.archivedAt(archivedAt)
|
.archivedAt(archivedAt)
|
||||||
|
.reviewerId(null)
|
||||||
|
.reviewerName("auto")
|
||||||
|
.reviewerComment("auto")
|
||||||
.build();
|
.build();
|
||||||
annotationResultHistoryMapper.insert(history);
|
annotationResultHistoryMapper.insert(history);
|
||||||
|
|
||||||
@@ -208,4 +219,35 @@ public class AnnotationResultArchiveService {
|
|||||||
int firstSlash = filePath.indexOf('/');
|
int firstSlash = filePath.indexOf('/');
|
||||||
return firstSlash > 0 ? filePath.substring(firstSlash + 1) : "";
|
return firstSlash > 0 ? filePath.substring(firstSlash + 1) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载归档记录的文件内容
|
||||||
|
* @param currentUser 当前用户
|
||||||
|
* @param historyId 历史记录ID
|
||||||
|
* @return 文件内容响应
|
||||||
|
*/
|
||||||
|
public FileContentResponse loadFileContent(LoginUser currentUser, Long historyId) {
|
||||||
|
AnnotationResultHistory history = annotationResultHistoryMapper.selectById(historyId);
|
||||||
|
if (history == null || !history.getCompanyId().equals(currentUser.companyId())) {
|
||||||
|
throw new BusinessException(ResultCode.NOT_FOUND, "历史记录不存在");
|
||||||
|
}
|
||||||
|
//assertHistoryPermission(currentUser, history);
|
||||||
|
|
||||||
|
String filePath = history.getQaContentFilePath();
|
||||||
|
if (filePath == null || filePath.isEmpty()) {
|
||||||
|
throw new BusinessException(ResultCode.ERROR, "文件路径为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String bucketName = extractBucketName(filePath);
|
||||||
|
String objectKey = extractObjectKey(filePath);
|
||||||
|
byte[] content = objectStorageService.download(bucketName, objectKey);
|
||||||
|
String contentStr = new String(content, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
return new FileContentResponse(filePath, contentStr, content.length);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Failed to load file content, historyId={}, filePath={}", historyId, filePath, e);
|
||||||
|
throw new BusinessException(ResultCode.ERROR, "加载文件内容失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,6 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
@@ -48,6 +47,7 @@ public class AnnotationResultService {
|
|||||||
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
|
boolean shouldFilterByUserId = dataPermissionService.shouldFilterByUserId(currentUser);
|
||||||
|
|
||||||
var wrapper = new LambdaQueryWrapper<AnnotationResult>()
|
var wrapper = new LambdaQueryWrapper<AnnotationResult>()
|
||||||
|
.eq(AnnotationResult::getIsDeleted, Boolean.FALSE)
|
||||||
.eq(AnnotationResult::getCompanyId, currentUser.companyId())
|
.eq(AnnotationResult::getCompanyId, currentUser.companyId())
|
||||||
.eq(query.taskId() != null, AnnotationResult::getTaskId, query.taskId())
|
.eq(query.taskId() != null, AnnotationResult::getTaskId, query.taskId())
|
||||||
.eq(query.resourceId() != null, AnnotationResult::getResourceId, query.resourceId())
|
.eq(query.resourceId() != null, AnnotationResult::getResourceId, query.resourceId())
|
||||||
@@ -95,7 +95,7 @@ public class AnnotationResultService {
|
|||||||
//assertResultPermission(currentUser, result);
|
//assertResultPermission(currentUser, result);
|
||||||
|
|
||||||
QaContent qaContent = loadQaContent(result);
|
QaContent qaContent = loadQaContent(result);
|
||||||
DiffContent diffContent = StringUtils.hasText(result.getDiffSummaryFilePath()) ?
|
DiffContent diffContent = Boolean.TRUE.equals(result.getRequiresManualReview()) ?
|
||||||
loadDiffSummary(result) : null;
|
loadDiffSummary(result) : null;
|
||||||
|
|
||||||
SourceResource resource = sourceResourceMapper.selectById(result.getResourceId());
|
SourceResource resource = sourceResourceMapper.selectById(result.getResourceId());
|
||||||
@@ -170,14 +170,15 @@ public class AnnotationResultService {
|
|||||||
saveQaContent(result, updatedQaContent);
|
saveQaContent(result, updatedQaContent);
|
||||||
|
|
||||||
// 更新数据库记录
|
// 更新数据库记录
|
||||||
|
result.setIsDeleted(Boolean.TRUE);
|
||||||
result.setReviewerId(currentUser.userId());
|
result.setReviewerId(currentUser.userId());
|
||||||
result.setReviewComment(request.reviewComment());
|
result.setReviewComment(request.reviewComment());
|
||||||
result.setReviewedAt(LocalDateTime.now());
|
result.setReviewedAt(LocalDateTime.now());
|
||||||
result.setRequiresManualReview(false);
|
result.setRequiresManualReview(false);
|
||||||
annotationResultMapper.updateById(result);
|
annotationResultMapper.updateById(result);
|
||||||
|
|
||||||
// 归档到历史表
|
// 归档到历史表(人工审核后归档)
|
||||||
archiveToHistory(result, currentUser, "审核通过后归档");
|
archiveToHistory(result, currentUser, "审核通过后归档", false);
|
||||||
|
|
||||||
log.info("merged review result, companyId={}, userId={}, resultId={}",
|
log.info("merged review result, companyId={}, userId={}, resultId={}",
|
||||||
currentUser.companyId(), currentUser.userId(), resultId);
|
currentUser.companyId(), currentUser.userId(), resultId);
|
||||||
@@ -187,7 +188,9 @@ public class AnnotationResultService {
|
|||||||
return new AnnotationResultResponse(
|
return new AnnotationResultResponse(
|
||||||
result.getId(),
|
result.getId(),
|
||||||
result.getTaskId(),
|
result.getTaskId(),
|
||||||
|
result.getTaskName(), // 新增
|
||||||
result.getResourceId(),
|
result.getResourceId(),
|
||||||
|
result.getResourceName(), // 新增
|
||||||
deriveStatus(result),
|
deriveStatus(result),
|
||||||
result.getRequiresManualReview(),
|
result.getRequiresManualReview(),
|
||||||
result.getIsDeleted(),
|
result.getIsDeleted(),
|
||||||
@@ -262,31 +265,55 @@ public class AnnotationResultService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void archiveToHistory(AnnotationResult result, LoginUser currentUser, String archiveReason) {
|
/**
|
||||||
|
* 归档到历史表
|
||||||
|
* @param result 标注结果
|
||||||
|
* @param currentUser 当前用户
|
||||||
|
* @param archiveReason 归档原因
|
||||||
|
* @param isAutoArchive 是否自动归档(true=自动归档,false=人工审核后归档)
|
||||||
|
*/
|
||||||
|
private void archiveToHistory(AnnotationResult result, LoginUser currentUser, String archiveReason, boolean isAutoArchive) {
|
||||||
try {
|
try {
|
||||||
// 读取 qa.json 内容用于归档
|
// 读取 qa.json 内容用于归档
|
||||||
QaContent qaContent = loadQaContent(result);
|
QaContent qaContent = loadQaContent(result);
|
||||||
|
|
||||||
// 构建归档记录
|
// 构建归档记录
|
||||||
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
AnnotationResultHistory.AnnotationResultHistoryBuilder historyBuilder = AnnotationResultHistory.builder()
|
||||||
.id(IdGenerator.nextId())
|
.id(IdGenerator.nextId())
|
||||||
.companyId(result.getCompanyId())
|
.companyId(result.getCompanyId())
|
||||||
.creatorId(currentUser.userId())
|
.creatorId(result.getCreatorId())
|
||||||
.creatorRole(currentUser.role().name())
|
.creatorRole(result.getCreatorRole())
|
||||||
.sourceResultId(result.getId())
|
.sourceResultId(result.getId())
|
||||||
.taskId(result.getTaskId())
|
.taskId(result.getTaskId())
|
||||||
|
.taskName(result.getTaskName())
|
||||||
.resourceId(result.getResourceId())
|
.resourceId(result.getResourceId())
|
||||||
|
.resourceName(result.getResourceName())
|
||||||
//.qaContentJson(objectMapper.writeValueAsString(qaContent))
|
//.qaContentJson(objectMapper.writeValueAsString(qaContent))
|
||||||
.qaContentFilePath(result.getQaContentFilePath())
|
.qaContentFilePath(result.getQaContentFilePath())
|
||||||
.archiveReason(archiveReason)
|
.archiveReason(archiveReason)
|
||||||
.archivedBy(currentUser.userId())
|
.archivedBy(currentUser.userId())
|
||||||
.archivedAt(LocalDateTime.now())
|
.archivedAt(LocalDateTime.now())
|
||||||
.createdAt(LocalDateTime.now())
|
.createdAt(LocalDateTime.now());
|
||||||
.build();
|
|
||||||
|
|
||||||
annotationResultHistoryMapper.insert(history);
|
// 根据归档类型设置审核人信息
|
||||||
|
if (isAutoArchive) {
|
||||||
|
// 自动归档:reviewer_id为NULL,name和comment为"auto"
|
||||||
|
historyBuilder
|
||||||
|
.reviewerId(null)
|
||||||
|
.reviewerName("auto")
|
||||||
|
.reviewerComment("auto");
|
||||||
|
} else {
|
||||||
|
// 人工审核后归档:使用审核人信息
|
||||||
|
historyBuilder
|
||||||
|
.reviewerId(result.getReviewerId())
|
||||||
|
.reviewerName(currentUser.realName())
|
||||||
|
.reviewerComment(result.getReviewComment());
|
||||||
|
}
|
||||||
|
|
||||||
log.info("archived result to history, resultId={}, historyId={}", result.getId(), history.getId());
|
annotationResultHistoryMapper.insert(historyBuilder.build());
|
||||||
|
|
||||||
|
log.info("archived result to history, resultId={}, historyId={}, isAutoArchive={}",
|
||||||
|
result.getId(), historyBuilder.build().getId(), isAutoArchive);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to archive result to history, resultId={}", result.getId(), e);
|
log.error("Failed to archive result to history, resultId={}", result.getId(), e);
|
||||||
throw new BusinessException(ResultCode.ERROR, "归档失败");
|
throw new BusinessException(ResultCode.ERROR, "归档失败");
|
||||||
|
|||||||
@@ -84,27 +84,27 @@ INSERT INTO annotation_task_resource (
|
|||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
INSERT INTO annotation_result (
|
INSERT INTO annotation_result (
|
||||||
id, company_id, creator_id, creator_role, task_id, resource_id,
|
id, company_id, creator_id, creator_role, task_id, task_name, resource_id, resource_name,
|
||||||
qa_content_file_path, diff_summary_file_path,
|
qa_content_file_path, diff_summary_file_path,
|
||||||
requires_manual_review, is_deleted, reviewer_id, review_comment, reviewed_at
|
requires_manual_review, is_deleted, reviewer_id, review_comment, reviewed_at
|
||||||
) VALUES
|
) VALUES
|
||||||
(801, 2, 3, 'EMPLOYEE', 701, 601,
|
(801, 2, 3, 'EMPLOYEE', 701, '多资源问答抽取任务', 601, '设备巡检规范.txt',
|
||||||
'annotation-results/qa/801.json',
|
'annotation-results/qa/801.json',
|
||||||
'annotation-results/diff/801.json',
|
'annotation-results/diff/801.json',
|
||||||
TRUE, FALSE, NULL, NULL, NULL),
|
TRUE, FALSE, NULL, NULL, NULL),
|
||||||
(802, 2, 3, 'EMPLOYEE', 702, 602,
|
(802, 2, 3, 'EMPLOYEE', 702, '图片问答抽取任务', 602, '控制柜照片.jpg',
|
||||||
'annotation-results/qa/802.json',
|
'annotation-results/qa/802.json',
|
||||||
NULL,
|
NULL,
|
||||||
FALSE, FALSE, 5, '结果可通过。', CURRENT_TIMESTAMP)
|
FALSE, FALSE, 5, '结果可通过。', CURRENT_TIMESTAMP)
|
||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
INSERT INTO annotation_result_history (
|
INSERT INTO annotation_result_history (
|
||||||
id, company_id, creator_id, creator_role, source_result_id, task_id, resource_id,
|
id, company_id, creator_id, creator_role, source_result_id, task_id, task_name, resource_id, resource_name,
|
||||||
qa_content_file_path, archive_reason, archived_by, archived_at
|
qa_content_file_path, reviewer_id, reviewer_name, reviewer_comment, archive_reason, archived_by, archived_at
|
||||||
) VALUES
|
) VALUES
|
||||||
(901, 2, 3, 'EMPLOYEE', 802, 702, 602,
|
(901, 2, 3, 'EMPLOYEE', 802, 702, '图片问答抽取任务', 602, '控制柜照片.jpg',
|
||||||
'annotation-results/2/qa/802.json',
|
'annotation-results/2/qa/802.json',
|
||||||
'审核通过后归档', 5, CURRENT_TIMESTAMP)
|
5, '甲公司审核员', '结果可通过。', '审核通过后归档', 5, CURRENT_TIMESTAMP)
|
||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
INSERT INTO image_bbox_annotation (
|
INSERT INTO image_bbox_annotation (
|
||||||
|
|||||||
@@ -163,14 +163,14 @@ COMMENT ON COLUMN source_resource.updated_at IS '更新时间。';
|
|||||||
CREATE TABLE IF NOT EXISTS image_bbox_annotation
|
CREATE TABLE IF NOT EXISTS image_bbox_annotation
|
||||||
(
|
(
|
||||||
id BIGINT PRIMARY KEY,
|
id BIGINT PRIMARY KEY,
|
||||||
company_id BIGINT NOT NULL,
|
company_id BIGINT NOT NULL,
|
||||||
resource_id BIGINT NOT NULL,
|
resource_id BIGINT NOT NULL,
|
||||||
bbox_json TEXT,
|
bbox_json TEXT,
|
||||||
remark VARCHAR(500),
|
remark VARCHAR(500),
|
||||||
creator_id BIGINT NOT NULL,
|
creator_id BIGINT NOT NULL,
|
||||||
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
|
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
CONSTRAINT fk_image_bbox_annotation_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
|
CONSTRAINT fk_image_bbox_annotation_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
|
||||||
CONSTRAINT fk_image_bbox_annotation_resource FOREIGN KEY (resource_id) REFERENCES source_resource (id),
|
CONSTRAINT fk_image_bbox_annotation_resource FOREIGN KEY (resource_id) REFERENCES source_resource (id),
|
||||||
CONSTRAINT fk_image_bbox_annotation_creator FOREIGN KEY (creator_id) REFERENCES sys_user (id)
|
CONSTRAINT fk_image_bbox_annotation_creator FOREIGN KEY (creator_id) REFERENCES sys_user (id)
|
||||||
@@ -244,24 +244,26 @@ COMMENT ON COLUMN annotation_task_resource.task_id IS '任务ID。';
|
|||||||
COMMENT ON COLUMN annotation_task_resource.resource_id IS '资源ID。';
|
COMMENT ON COLUMN annotation_task_resource.resource_id IS '资源ID。';
|
||||||
COMMENT ON COLUMN annotation_task_resource.created_at IS '创建时间。';
|
COMMENT ON COLUMN annotation_task_resource.created_at IS '创建时间。';
|
||||||
|
|
||||||
|
drop table if exists annotation_result;
|
||||||
CREATE TABLE IF NOT EXISTS annotation_result
|
CREATE TABLE IF NOT EXISTS annotation_result
|
||||||
(
|
(
|
||||||
id BIGINT PRIMARY KEY,
|
id BIGINT PRIMARY KEY,
|
||||||
company_id BIGINT NOT NULL,
|
company_id BIGINT NOT NULL,
|
||||||
creator_id BIGINT NOT NULL,
|
creator_id BIGINT NOT NULL,
|
||||||
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
|
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
|
||||||
task_id BIGINT NOT NULL,
|
task_id BIGINT NOT NULL,
|
||||||
resource_id BIGINT NOT NULL,
|
resource_id BIGINT NOT NULL,
|
||||||
qa_content_file_path VARCHAR(512) NOT NULL,
|
task_name VARCHAR(256),
|
||||||
diff_summary_file_path VARCHAR(512),
|
resource_name VARCHAR(512),
|
||||||
requires_manual_review BOOLEAN NOT NULL DEFAULT FALSE,
|
qa_content_file_path VARCHAR(512) NOT NULL,
|
||||||
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
diff_summary_file_path VARCHAR(512),
|
||||||
reviewer_id BIGINT,
|
requires_manual_review BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
review_comment TEXT,
|
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
reviewed_at TIMESTAMP,
|
reviewer_id BIGINT,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
review_comment TEXT,
|
||||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
reviewed_at TIMESTAMP,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
CONSTRAINT fk_annotation_result_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
|
CONSTRAINT fk_annotation_result_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
|
||||||
CONSTRAINT fk_annotation_result_creator FOREIGN KEY (creator_id) REFERENCES sys_user (id),
|
CONSTRAINT fk_annotation_result_creator FOREIGN KEY (creator_id) REFERENCES sys_user (id),
|
||||||
CONSTRAINT fk_annotation_result_task FOREIGN KEY (task_id) REFERENCES annotation_task (id),
|
CONSTRAINT fk_annotation_result_task FOREIGN KEY (task_id) REFERENCES annotation_task (id),
|
||||||
@@ -285,28 +287,35 @@ COMMENT ON COLUMN annotation_result.review_comment IS '审核意见。';
|
|||||||
COMMENT ON COLUMN annotation_result.reviewed_at IS '审核时间。';
|
COMMENT ON COLUMN annotation_result.reviewed_at IS '审核时间。';
|
||||||
COMMENT ON COLUMN annotation_result.created_at IS '创建时间。';
|
COMMENT ON COLUMN annotation_result.created_at IS '创建时间。';
|
||||||
COMMENT ON COLUMN annotation_result.updated_at IS '更新时间。';
|
COMMENT ON COLUMN annotation_result.updated_at IS '更新时间。';
|
||||||
|
COMMENT ON COLUMN annotation_result.task_name IS '任务名称(冗余字段)。';
|
||||||
|
COMMENT ON COLUMN annotation_result.resource_name IS '资源名称(冗余字段)。';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS annotation_result_history
|
CREATE TABLE IF NOT EXISTS annotation_result_history
|
||||||
(
|
(
|
||||||
id BIGINT PRIMARY KEY,
|
id BIGINT PRIMARY KEY,
|
||||||
company_id BIGINT NOT NULL,
|
company_id BIGINT NOT NULL,
|
||||||
creator_id BIGINT NOT NULL,
|
creator_id BIGINT NOT NULL,
|
||||||
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
|
creator_role VARCHAR(32) NOT NULL DEFAULT 'EMPLOYEE',
|
||||||
source_result_id BIGINT,
|
source_result_id BIGINT,
|
||||||
task_id BIGINT NOT NULL,
|
task_id BIGINT NOT NULL,
|
||||||
resource_id BIGINT NOT NULL,
|
resource_id BIGINT NOT NULL,
|
||||||
|
task_name VARCHAR(256),
|
||||||
|
resource_name VARCHAR(512),
|
||||||
qa_content_file_path VARCHAR(512) NOT NULL,
|
qa_content_file_path VARCHAR(512) NOT NULL,
|
||||||
archive_reason VARCHAR(256),
|
reviewer_id BIGINT,
|
||||||
archived_by BIGINT,
|
reviewer_name VARCHAR(128),
|
||||||
archived_at TIMESTAMP,
|
reviewer_comment TEXT,
|
||||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
archive_reason VARCHAR(256),
|
||||||
|
archived_by BIGINT,
|
||||||
|
archived_at TIMESTAMP,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
CONSTRAINT fk_annotation_result_history_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
|
CONSTRAINT fk_annotation_result_history_company FOREIGN KEY (company_id) REFERENCES sys_company (id),
|
||||||
CONSTRAINT fk_annotation_result_history_creator FOREIGN KEY (creator_id) REFERENCES sys_user (id),
|
CONSTRAINT fk_annotation_result_history_creator FOREIGN KEY (creator_id) REFERENCES sys_user (id),
|
||||||
CONSTRAINT fk_annotation_result_history_result FOREIGN KEY (source_result_id) REFERENCES annotation_result (id),
|
CONSTRAINT fk_annotation_result_history_result FOREIGN KEY (source_result_id) REFERENCES annotation_result (id),
|
||||||
CONSTRAINT fk_annotation_result_history_task FOREIGN KEY (task_id) REFERENCES annotation_task (id),
|
CONSTRAINT fk_annotation_result_history_task FOREIGN KEY (task_id) REFERENCES annotation_task (id),
|
||||||
CONSTRAINT fk_annotation_result_history_resource FOREIGN KEY (resource_id) REFERENCES source_resource (id),
|
CONSTRAINT fk_annotation_result_history_resource FOREIGN KEY (resource_id) REFERENCES source_resource (id),
|
||||||
CONSTRAINT fk_annotation_result_history_archived_by FOREIGN KEY (archived_by) REFERENCES sys_user (id)
|
CONSTRAINT fk_annotation_result_history_archived_by FOREIGN KEY (archived_by) REFERENCES sys_user (id),
|
||||||
|
CONSTRAINT fk_annotation_result_history_reviewer FOREIGN KEY (reviewer_id) REFERENCES sys_user (id)
|
||||||
);
|
);
|
||||||
|
|
||||||
COMMENT ON TABLE annotation_result_history IS '历史归档结果表。问答内容存储在对象存储中。';
|
COMMENT ON TABLE annotation_result_history IS '历史归档结果表。问答内容存储在对象存储中。';
|
||||||
@@ -322,6 +331,11 @@ COMMENT ON COLUMN annotation_result_history.archive_reason IS '归档原因说
|
|||||||
COMMENT ON COLUMN annotation_result_history.archived_by IS '归档操作人用户ID。';
|
COMMENT ON COLUMN annotation_result_history.archived_by IS '归档操作人用户ID。';
|
||||||
COMMENT ON COLUMN annotation_result_history.archived_at IS '归档时间。';
|
COMMENT ON COLUMN annotation_result_history.archived_at IS '归档时间。';
|
||||||
COMMENT ON COLUMN annotation_result_history.created_at IS '创建时间。';
|
COMMENT ON COLUMN annotation_result_history.created_at IS '创建时间。';
|
||||||
|
COMMENT ON COLUMN annotation_result_history.reviewer_id IS '审核人用户ID。自动归档时为NULL。';
|
||||||
|
COMMENT ON COLUMN annotation_result_history.reviewer_name IS '审核人姓名。自动归档时为"auto"。';
|
||||||
|
COMMENT ON COLUMN annotation_result_history.reviewer_comment IS '审核意见。自动归档时为"auto"。';
|
||||||
|
COMMENT ON COLUMN annotation_result_history.task_name IS '任务名称(冗余字段)。';
|
||||||
|
COMMENT ON COLUMN annotation_result_history.resource_name IS '资源名称(冗余字段)。';
|
||||||
|
|
||||||
CREATE TABLE IF NOT EXISTS training_dataset
|
CREATE TABLE IF NOT EXISTS training_dataset
|
||||||
(
|
(
|
||||||
|
|||||||
Reference in New Issue
Block a user