feat(annotation): 实现任务列表分页加载和优化排序功能

- 添加分页相关字段到EditorTaskListResponse类型定义
- 定义TASK_PAGE_START和TASK_PAGE_SIZE常量及NormalizedTaskList类型
- 实现mergeTaskItems、mergeTaskPages和normalizeTaskListResponse工具函数
- 添加taskPage、taskTotal、taskTotalPages和loadingMore状态管理
- 优化后端查询逻辑,使用case语句实现标注状态排序
- 集成外连接查询同时获取文件信息和标注结果
- 改进前端任务列表的数据合并和分页加载机制
This commit is contained in:
2026-01-27 18:22:17 +08:00
parent 3a93098b57
commit 1158647217
2 changed files with 178 additions and 43 deletions

View File

@@ -18,7 +18,7 @@ import hashlib
import json
import xml.etree.ElementTree as ET
from fastapi import HTTPException
from sqlalchemy import func, select
from sqlalchemy import case, func, select
from sqlalchemy.ext.asyncio import AsyncSession
from app.core.config import settings
@@ -420,38 +420,34 @@ class AnnotationEditorService:
)
total = int(count_result.scalar() or 0)
annotated_sort_key = case(
(AnnotationResult.id.isnot(None), 1),
else_=0,
)
files_result = await self.db.execute(
select(DatasetFiles)
select(DatasetFiles, AnnotationResult.id, AnnotationResult.updated_at)
.outerjoin(
AnnotationResult,
(AnnotationResult.file_id == DatasetFiles.id)
& (AnnotationResult.project_id == project_id),
)
.where(DatasetFiles.dataset_id == project.dataset_id)
.order_by(DatasetFiles.created_at.desc())
.order_by(annotated_sort_key.asc(), DatasetFiles.created_at.desc())
.offset(page * size)
.limit(size)
)
files = files_result.scalars().all()
file_ids = [str(f.id) for f in files] # type: ignore[arg-type]
updated_map: Dict[str, datetime] = {}
if file_ids:
ann_result = await self.db.execute(
select(AnnotationResult.file_id, AnnotationResult.updated_at).where(
AnnotationResult.project_id == project_id,
AnnotationResult.file_id.in_(file_ids),
)
)
for file_id, updated_at in ann_result.all():
if file_id and updated_at:
updated_map[str(file_id)] = updated_at
rows = files_result.all()
items: List[EditorTaskListItem] = []
for f in files:
fid = str(f.id) # type: ignore[arg-type]
for file_record, annotation_id, annotation_updated_at in rows:
fid = str(file_record.id) # type: ignore[arg-type]
items.append(
EditorTaskListItem(
fileId=fid,
fileName=str(getattr(f, "file_name", "")),
fileType=getattr(f, "file_type", None),
hasAnnotation=fid in updated_map,
annotationUpdatedAt=updated_map.get(fid),
fileName=str(getattr(file_record, "file_name", "")),
fileType=getattr(file_record, "file_type", None),
hasAnnotation=annotation_id is not None,
annotationUpdatedAt=annotation_updated_at,
)
)