fix(annotation): fix use_new_version to support files without annotation

Problem:
use_new_version returned 404 annotation not found for files without
annotation, preventing users from switching to new versions.

Solution:
1. Query latest file by logical_path
2. Update LabelingProjectFile to point to latest version
3. If annotation exists: clear it and update file_id
4. If no annotation: just update project file snapshot
5. Return new file_id in response
This commit is contained in:
2026-02-06 15:22:57 +08:00
parent 1f6c821cbc
commit cd5f5ef6da

View File

@@ -1723,16 +1723,19 @@ class AnnotationEditorService:
""" """
使用文件新版本并清空标注 使用文件新版本并清空标注
如果文件有多个版本(通过 logical_path 关联),将标注切换到最新版本。
如果存在标注记录,会清空标注内容。
Args: Args:
project_id: 标注项目ID project_id: 标注项目ID
file_id: 文件ID file_id: 文件ID(当前关联的文件ID)
Returns: Returns:
操作结果 操作结果
""" """
project = await self._get_project_or_404(project_id) project = await self._get_project_or_404(project_id)
# 获取文件信息 # 获取当前文件信息
file_result = await self.db.execute( file_result = await self.db.execute(
select(DatasetFiles) select(DatasetFiles)
.join(LabelingProjectFile, LabelingProjectFile.file_id == DatasetFiles.id) .join(LabelingProjectFile, LabelingProjectFile.file_id == DatasetFiles.id)
@@ -1748,7 +1751,46 @@ class AnnotationEditorService:
status_code=404, detail=f"文件不存在或不属于该项目: {file_id}" status_code=404, detail=f"文件不存在或不属于该项目: {file_id}"
) )
# 获取标注信息 # 获取同一逻辑路径下的最新版本文件
logical_path = file_record.logical_path
latest_file_result = await self.db.execute(
select(DatasetFiles)
.where(
DatasetFiles.dataset_id == project.dataset_id,
DatasetFiles.logical_path == logical_path,
DatasetFiles.status == "ACTIVE",
)
.order_by(DatasetFiles.version.desc())
.limit(1)
)
latest_file = latest_file_result.scalar_one_or_none()
if not latest_file:
raise HTTPException(
status_code=404, detail=f"找不到该文件的最新版本: {logical_path}"
)
# 如果当前文件已经是最新版本,无需更新
if latest_file.id == file_id:
return {
"fileId": file_id,
"previousFileVersion": file_record.version,
"currentFileVersion": latest_file.version,
"message": "当前文件已是最新版本,无需切换",
}
# 更新 LabelingProjectFile 指向最新版本
project_file_result = await self.db.execute(
select(LabelingProjectFile).where(
LabelingProjectFile.project_id == project.id,
LabelingProjectFile.file_id == file_id,
)
)
project_file = project_file_result.scalar_one_or_none()
if project_file:
project_file.file_id = str(latest_file.id)
# 获取标注信息(基于原 file_id)
annotation_result = await self.db.execute( annotation_result = await self.db.execute(
select(AnnotationResult) select(AnnotationResult)
.where( .where(
@@ -1759,22 +1801,12 @@ class AnnotationEditorService:
) )
annotation = annotation_result.scalar_one_or_none() annotation = annotation_result.scalar_one_or_none()
current_file_version = file_record.version now = datetime.utcnow()
if not annotation:
raise HTTPException(status_code=404, detail=f"标注不存在: {file_id}")
if annotation:
# 存在标注记录:清空标注并更新文件版本
previous_file_version = annotation.file_version previous_file_version = annotation.file_version
if annotation.file_version is not None:
if current_file_version <= annotation.file_version:
raise HTTPException(
status_code=400,
detail=f"文件版本({current_file_version})未更新或低于标注版本({annotation.file_version}",
)
# 清空标注并更新版本号
now = datetime.utcnow()
cleared_payload: Dict[str, Any] = {} cleared_payload: Dict[str, Any] = {}
if isinstance(annotation.annotation, dict) and self._is_segmented_annotation( if isinstance(annotation.annotation, dict) and self._is_segmented_annotation(
annotation.annotation annotation.annotation
@@ -1799,9 +1831,11 @@ class AnnotationEditorService:
SEGMENT_TOTAL_KEY: total_segments, SEGMENT_TOTAL_KEY: total_segments,
} }
# 更新标注记录指向新文件
annotation.file_id = str(latest_file.id)
annotation.annotation = cleared_payload annotation.annotation = cleared_payload
annotation.annotation_status = ANNOTATION_STATUS_NO_ANNOTATION annotation.annotation_status = ANNOTATION_STATUS_NO_ANNOTATION
annotation.file_version = current_file_version annotation.file_version = latest_file.version
annotation.updated_at = now annotation.updated_at = now
await self.db.commit() await self.db.commit()
@@ -1809,14 +1843,24 @@ class AnnotationEditorService:
await self._sync_annotation_to_knowledge( await self._sync_annotation_to_knowledge(
project, project,
file_record, latest_file,
cleared_payload, cleared_payload,
annotation.updated_at or now, annotation.updated_at or now,
) )
return { return {
"fileId": file_id, "fileId": str(latest_file.id),
"previousFileVersion": previous_file_version, "previousFileVersion": previous_file_version,
"currentFileVersion": current_file_version, "currentFileVersion": latest_file.version,
"message": "使用新版本并清空标注", "message": "切换到新版本并清空标注",
}
else:
# 不存在标注记录:只需更新项目文件快照
await self.db.commit()
return {
"fileId": str(latest_file.id),
"previousFileVersion": file_record.version,
"currentFileVersion": latest_file.version,
"message": "已切换到新版本",
} }