数据库去掉industrytype,适配QA新结构,解决自动和手动归档产生两次记录问题
This commit is contained in:
@@ -1,6 +1,5 @@
|
|||||||
package com.labelsys.backend.dto.request;
|
package com.labelsys.backend.dto.request;
|
||||||
|
|
||||||
import com.labelsys.backend.enums.IndustryType;
|
|
||||||
import com.labelsys.backend.enums.TaskType;
|
import com.labelsys.backend.enums.TaskType;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.NotBlank;
|
import jakarta.validation.constraints.NotBlank;
|
||||||
@@ -12,7 +11,6 @@ import java.util.List;
|
|||||||
@Schema(description = "创建标注任务请求")
|
@Schema(description = "创建标注任务请求")
|
||||||
public record CreateAnnotationTaskRequest(
|
public record CreateAnnotationTaskRequest(
|
||||||
@Schema(description = "任务名称", example = "运输文档问答抽取任务") @NotBlank(message = "任务名称不能为空") String taskName,
|
@Schema(description = "任务名称", example = "运输文档问答抽取任务") @NotBlank(message = "任务名称不能为空") String taskName,
|
||||||
@Schema(description = "行业类型", defaultValue = "TRANSPORT", example = "TRANSPORT") @NotNull(message = "行业类型不能为空") IndustryType industryType,
|
|
||||||
@Schema(description = "任务类型", defaultValue = "EXTRACT_QA", example = "EXTRACT_QA") @NotNull(message = "任务类型不能为空") TaskType taskType,
|
@Schema(description = "任务类型", defaultValue = "EXTRACT_QA", example = "EXTRACT_QA") @NotNull(message = "任务类型不能为空") TaskType taskType,
|
||||||
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") @NotEmpty(message = "资源列表不能为空") List<Long> resourceIds) {
|
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") @NotEmpty(message = "资源列表不能为空") List<Long> resourceIds) {
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,12 @@ package com.labelsys.backend.dto.request;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.labelsys.backend.enums.IndustryType;
|
|
||||||
import com.labelsys.backend.enums.TaskType;
|
import com.labelsys.backend.enums.TaskType;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
@Schema(description = "更新标注任务请求")
|
@Schema(description = "更新标注任务请求")
|
||||||
public record UpdateAnnotationTaskRequest(
|
public record UpdateAnnotationTaskRequest(
|
||||||
@Schema(description = "行业类型", example = "TRANSPORT") IndustryType industryType,
|
|
||||||
@Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType,
|
@Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType,
|
||||||
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds) {
|
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds) {
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.labelsys.backend.dto.response;
|
package com.labelsys.backend.dto.response;
|
||||||
|
|
||||||
import com.labelsys.backend.enums.IndustryType;
|
|
||||||
import com.labelsys.backend.enums.TaskType;
|
import com.labelsys.backend.enums.TaskType;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
|
||||||
@@ -11,7 +10,6 @@ import java.util.List;
|
|||||||
public record AnnotationTaskResponse(
|
public record AnnotationTaskResponse(
|
||||||
@Schema(description = "任务ID", example = "191000000000000301") Long id,
|
@Schema(description = "任务ID", example = "191000000000000301") Long id,
|
||||||
@Schema(description = "任务名称", example = "运输文档问答抽取任务") String taskName,
|
@Schema(description = "任务名称", example = "运输文档问答抽取任务") String taskName,
|
||||||
@Schema(description = "行业类型", example = "transport") IndustryType industryType,
|
|
||||||
@Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType,
|
@Schema(description = "任务类型", example = "EXTRACT_QA") TaskType taskType,
|
||||||
@Schema(description = "任务状态", example = "PENDING") String taskStatus,
|
@Schema(description = "任务状态", example = "PENDING") String taskStatus,
|
||||||
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds,
|
@Schema(description = "资源ID列表", example = "[191000000000000101,191000000000000102]") List<Long> resourceIds,
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.IdType;
|
|||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableLogic;
|
import com.baomidou.mybatisplus.annotation.TableLogic;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
import com.labelsys.backend.enums.IndustryType;
|
|
||||||
import com.labelsys.backend.enums.TaskType;
|
import com.labelsys.backend.enums.TaskType;
|
||||||
import com.labelsys.backend.enums.UserRole;
|
import com.labelsys.backend.enums.UserRole;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
@@ -26,7 +25,6 @@ public class AnnotationTask {
|
|||||||
private Long creatorId;
|
private Long creatorId;
|
||||||
private UserRole creatorRole;
|
private UserRole creatorRole;
|
||||||
private String taskName;
|
private String taskName;
|
||||||
private IndustryType industryType;
|
|
||||||
private TaskType taskType;
|
private TaskType taskType;
|
||||||
private String taskStatus;
|
private String taskStatus;
|
||||||
@TableLogic(value = "false", delval = "true")
|
@TableLogic(value = "false", delval = "true")
|
||||||
|
|||||||
@@ -12,4 +12,8 @@ public interface AnnotationResultMapper extends BaseMapper<AnnotationResult> {
|
|||||||
int markArchived(@Param("id") Long id,
|
int markArchived(@Param("id") Long id,
|
||||||
@Param("companyId") Long companyId,
|
@Param("companyId") Long companyId,
|
||||||
@Param("reviewerId") Long reviewerId);
|
@Param("reviewerId") Long reviewerId);
|
||||||
|
|
||||||
|
int markReviewedAndArchived(@Param("id") Long id,
|
||||||
|
@Param("companyId") Long companyId,
|
||||||
|
@Param("reviewerId") Long reviewerId);
|
||||||
}
|
}
|
||||||
@@ -211,8 +211,13 @@ public class AnnotationResultArchiveService {
|
|||||||
String archiveReason) {
|
String archiveReason) {
|
||||||
LocalDateTime archivedAt = LocalDateTime.now();
|
LocalDateTime archivedAt = LocalDateTime.now();
|
||||||
|
|
||||||
// 从对象存储读取 qa.json 内容
|
int updated = annotationResultMapper.markArchived(
|
||||||
// String qaContentJson = loadQaContentJson(result);
|
result.getId(),
|
||||||
|
result.getCompanyId(),
|
||||||
|
reviewerId);
|
||||||
|
if (updated == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
AnnotationResultHistory history = AnnotationResultHistory.builder()
|
||||||
.id(IdGenerator.nextId())
|
.id(IdGenerator.nextId())
|
||||||
@@ -229,18 +234,11 @@ public class AnnotationResultArchiveService {
|
|||||||
.archiveReason(archiveReason)
|
.archiveReason(archiveReason)
|
||||||
.archivedBy(reviewerId)
|
.archivedBy(reviewerId)
|
||||||
.archivedAt(archivedAt)
|
.archivedAt(archivedAt)
|
||||||
|
.createdAt(archivedAt)
|
||||||
.reviewerId(null)
|
.reviewerId(null)
|
||||||
.reviewerName("auto")
|
.reviewerName("auto")
|
||||||
.build();
|
.build();
|
||||||
annotationResultHistoryMapper.insert(history);
|
annotationResultHistoryMapper.insert(history);
|
||||||
|
|
||||||
int updated = annotationResultMapper.markArchived(
|
|
||||||
result.getId(),
|
|
||||||
result.getCompanyId(),
|
|
||||||
reviewerId);
|
|
||||||
if (updated == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new MergeReviewResultResponse(result.getId(), history.getId(), archiveReason, archivedAt);
|
return new MergeReviewResultResponse(result.getId(), history.getId(), archiveReason, archivedAt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -296,8 +296,8 @@ public class AnnotationResultService {
|
|||||||
);
|
);
|
||||||
saveQaContent(result, updatedQaContent);
|
saveQaContent(result, updatedQaContent);
|
||||||
|
|
||||||
// 更新数据库记录(使用 markArchived 保证幂等性,防止并发重复归档)
|
// 用单条 SQL 原子完成人工审核归档,避免状态部分更新后再次被自动归档扫描到。
|
||||||
int updated = annotationResultMapper.markArchived(
|
int updated = annotationResultMapper.markReviewedAndArchived(
|
||||||
result.getId(),
|
result.getId(),
|
||||||
currentUser.companyId(),
|
currentUser.companyId(),
|
||||||
currentUser.userId());
|
currentUser.userId());
|
||||||
@@ -307,9 +307,9 @@ public class AnnotationResultService {
|
|||||||
throw new BusinessException(ResultCode.CONFLICT, "记录已被归档");
|
throw new BusinessException(ResultCode.CONFLICT, "记录已被归档");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新 requires_manual_review 字段
|
|
||||||
result.setRequiresManualReview(false);
|
result.setRequiresManualReview(false);
|
||||||
annotationResultMapper.updateById(result);
|
result.setIsDeleted(true);
|
||||||
|
result.setReviewerId(currentUser.userId());
|
||||||
|
|
||||||
// 归档到历史表(人工审核后归档)
|
// 归档到历史表(人工审核后归档)
|
||||||
archiveToHistory(result, currentUser, "审核通过后归档", false);
|
archiveToHistory(result, currentUser, "审核通过后归档", false);
|
||||||
@@ -453,7 +453,7 @@ public class AnnotationResultService {
|
|||||||
} else {
|
} else {
|
||||||
// 人工审核后归档:使用审核人信息
|
// 人工审核后归档:使用审核人信息
|
||||||
historyBuilder
|
historyBuilder
|
||||||
.reviewerId(result.getReviewerId())
|
.reviewerId(currentUser.userId())
|
||||||
.reviewerName(currentUser.realName());
|
.reviewerName(currentUser.realName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import com.labelsys.backend.dto.response.AnnotationTaskResponse;
|
|||||||
import com.labelsys.backend.entity.AnnotationTask;
|
import com.labelsys.backend.entity.AnnotationTask;
|
||||||
import com.labelsys.backend.entity.AnnotationTaskResource;
|
import com.labelsys.backend.entity.AnnotationTaskResource;
|
||||||
import com.labelsys.backend.entity.SourceResource;
|
import com.labelsys.backend.entity.SourceResource;
|
||||||
import com.labelsys.backend.enums.IndustryType;
|
|
||||||
import com.labelsys.backend.enums.TaskStatus;
|
import com.labelsys.backend.enums.TaskStatus;
|
||||||
import com.labelsys.backend.enums.TaskType;
|
import com.labelsys.backend.enums.TaskType;
|
||||||
import com.labelsys.backend.mapper.AnnotationTaskMapper;
|
import com.labelsys.backend.mapper.AnnotationTaskMapper;
|
||||||
@@ -53,7 +52,6 @@ public class AnnotationTaskService {
|
|||||||
.creatorId(currentUser.userId())
|
.creatorId(currentUser.userId())
|
||||||
.creatorRole(currentUser.role())
|
.creatorRole(currentUser.role())
|
||||||
.taskName(request.taskName())
|
.taskName(request.taskName())
|
||||||
.industryType(defaultIndustryType(request.industryType()))
|
|
||||||
.taskType(defaultTaskType(request.taskType()))
|
.taskType(defaultTaskType(request.taskType()))
|
||||||
.taskStatus(TaskStatus.PENDING.name())
|
.taskStatus(TaskStatus.PENDING.name())
|
||||||
.isDeleted(false)
|
.isDeleted(false)
|
||||||
@@ -97,10 +95,6 @@ public class AnnotationTaskService {
|
|||||||
resources = loadAndValidateResources(currentUser, request.resourceIds());
|
resources = loadAndValidateResources(currentUser, request.resourceIds());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request.industryType() != null) {
|
|
||||||
task.setIndustryType(request.industryType());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request.taskType() != null) {
|
if (request.taskType() != null) {
|
||||||
task.setTaskType(request.taskType());
|
task.setTaskType(request.taskType());
|
||||||
}
|
}
|
||||||
@@ -238,7 +232,6 @@ public class AnnotationTaskService {
|
|||||||
return new AnnotationTaskResponse(
|
return new AnnotationTaskResponse(
|
||||||
task.getId(),
|
task.getId(),
|
||||||
task.getTaskName(),
|
task.getTaskName(),
|
||||||
task.getIndustryType(),
|
|
||||||
task.getTaskType(),
|
task.getTaskType(),
|
||||||
task.getTaskStatus(),
|
task.getTaskStatus(),
|
||||||
resourceIds,
|
resourceIds,
|
||||||
@@ -264,10 +257,6 @@ public class AnnotationTaskService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IndustryType defaultIndustryType(IndustryType industryType) {
|
|
||||||
return industryType != null ? industryType : IndustryType.TRANSPORT;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TaskType defaultTaskType(TaskType taskType) {
|
private TaskType defaultTaskType(TaskType taskType) {
|
||||||
return taskType != null ? taskType : TaskType.EXTRACT_QA;
|
return taskType != null ? taskType : TaskType.EXTRACT_QA;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,14 @@
|
|||||||
and company_id = #{companyId}
|
and company_id = #{companyId}
|
||||||
and is_deleted = false
|
and is_deleted = false
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<update id="markReviewedAndArchived">
|
||||||
|
update annotation_result
|
||||||
|
set is_deleted = true,
|
||||||
|
requires_manual_review = false,
|
||||||
|
reviewer_id = #{reviewerId}
|
||||||
|
where id = #{id}
|
||||||
|
and company_id = #{companyId}
|
||||||
|
and is_deleted = false
|
||||||
|
</update>
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
<result column="creator_id" property="creatorId"/>
|
<result column="creator_id" property="creatorId"/>
|
||||||
<result column="creator_role" property="creatorRole"/>
|
<result column="creator_role" property="creatorRole"/>
|
||||||
<result column="task_name" property="taskName"/>
|
<result column="task_name" property="taskName"/>
|
||||||
<result column="industry_type" property="industryType"/>
|
|
||||||
<result column="task_type" property="taskType"/>
|
<result column="task_type" property="taskType"/>
|
||||||
<result column="task_status" property="taskStatus"/>
|
<result column="task_status" property="taskStatus"/>
|
||||||
<result column="is_deleted" property="isDeleted"/>
|
<result column="is_deleted" property="isDeleted"/>
|
||||||
@@ -19,7 +18,7 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="AnnotationTaskColumns">
|
<sql id="AnnotationTaskColumns">
|
||||||
id, company_id, creator_id, creator_role, task_name, industry_type, task_type,
|
id, company_id, creator_id, creator_role, task_name, task_type,
|
||||||
task_status, is_deleted, started_at, finished_at, error_message, created_at, updated_at
|
task_status, is_deleted, started_at, finished_at, error_message, created_at, updated_at
|
||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
|
|||||||
@@ -66,12 +66,12 @@ INSERT INTO source_resource (
|
|||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
INSERT INTO annotation_task (
|
INSERT INTO annotation_task (
|
||||||
id, company_id, creator_id, creator_role, task_name, industry_type, task_type,
|
id, company_id, creator_id, creator_role, task_name, task_type,
|
||||||
task_status, is_deleted, started_at, finished_at, error_message
|
task_status, is_deleted, started_at, finished_at, error_message
|
||||||
) VALUES
|
) VALUES
|
||||||
(701, 2, 4, 'EMPLOYEE', '多资源问答抽取任务', 'ELECTRICITY', 'EXTRACT_QA',
|
(701, 2, 4, 'EMPLOYEE', '多资源问答抽取任务', 'EXTRACT_QA',
|
||||||
'PENDING', FALSE, NULL, NULL, NULL),
|
'PENDING', FALSE, NULL, NULL, NULL),
|
||||||
(702, 2, 4, 'EMPLOYEE', '图片问答抽取任务', 'TRANSPORT', 'EXTRACT_QA',
|
(702, 2, 4, 'EMPLOYEE', '图片问答抽取任务', 'EXTRACT_QA',
|
||||||
'COMPLETED', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL)
|
'COMPLETED', FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL)
|
||||||
ON CONFLICT DO NOTHING;
|
ON CONFLICT DO NOTHING;
|
||||||
|
|
||||||
|
|||||||
@@ -199,7 +199,6 @@ CREATE TABLE IF NOT EXISTS annotation_task
|
|||||||
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_name VARCHAR(255) NOT NULL,
|
task_name VARCHAR(255) NOT NULL,
|
||||||
industry_type VARCHAR(32) NOT NULL DEFAULT 'GENERAL',
|
|
||||||
task_type VARCHAR(32) NOT NULL DEFAULT 'EXTRACT_QA',
|
task_type VARCHAR(32) NOT NULL DEFAULT 'EXTRACT_QA',
|
||||||
task_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
|
task_status VARCHAR(32) NOT NULL DEFAULT 'PENDING',
|
||||||
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
is_deleted BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
@@ -218,7 +217,6 @@ COMMENT ON COLUMN annotation_task.company_id IS '所属公司ID。';
|
|||||||
COMMENT ON COLUMN annotation_task.creator_id IS '任务创建人用户ID。';
|
COMMENT ON COLUMN annotation_task.creator_id IS '任务创建人用户ID。';
|
||||||
COMMENT ON COLUMN annotation_task.creator_role IS '任务创建人数据权限角色,默认 EMPLOYEE。';
|
COMMENT ON COLUMN annotation_task.creator_role IS '任务创建人数据权限角色,默认 EMPLOYEE。';
|
||||||
COMMENT ON COLUMN annotation_task.task_name IS '任务名称。';
|
COMMENT ON COLUMN annotation_task.task_name IS '任务名称。';
|
||||||
COMMENT ON COLUMN annotation_task.industry_type IS '行业类型简写,默认 transport,可选值按业务扩展。';
|
|
||||||
COMMENT ON COLUMN annotation_task.task_type IS '任务类型,默认 EXTRACT_QA。';
|
COMMENT ON COLUMN annotation_task.task_type IS '任务类型,默认 EXTRACT_QA。';
|
||||||
COMMENT ON COLUMN annotation_task.task_status IS '任务状态,默认 PENDING,可选 RUNNING、COMPLETED、FAILED。';
|
COMMENT ON COLUMN annotation_task.task_status IS '任务状态,默认 PENDING,可选 RUNNING、COMPLETED、FAILED。';
|
||||||
COMMENT ON COLUMN annotation_task.is_deleted IS '任务软删除标记,默认 FALSE。';
|
COMMENT ON COLUMN annotation_task.is_deleted IS '任务软删除标记,默认 FALSE。';
|
||||||
|
|||||||
Reference in New Issue
Block a user