[] = [
{
title: "任务名称",
dataIndex: "name",
@@ -173,7 +181,7 @@ export default function DataAnnotation() {
key: "annotatedCount",
width: 100,
align: "center" as const,
- render: (value: number, record: any) => {
+ render: (value: number, record: AnnotationTaskListItem) => {
const total = record.totalCount || 0;
const annotated = value || 0;
const percent = total > 0 ? Math.round((annotated / total) * 100) : 0;
@@ -184,6 +192,23 @@ export default function DataAnnotation() {
);
},
},
+ {
+ title: "标注中",
+ dataIndex: "inProgressCount",
+ key: "inProgressCount",
+ width: 100,
+ align: "center" as const,
+ render: (value: number, record: AnnotationTaskListItem) => {
+ const segmentationEnabled =
+ record.segmentationEnabled ?? record.segmentation_enabled;
+ if (!segmentationEnabled) return "-";
+ const resolved =
+ Number.isFinite(value)
+ ? value
+ : record.inProgressCount ?? record.in_progress_count ?? 0;
+ return resolved;
+ },
+ },
{
title: "创建时间",
dataIndex: "createdAt",
@@ -202,14 +227,14 @@ export default function DataAnnotation() {
fixed: "right" as const,
width: 150,
dataIndex: "actions",
- render: (_: any, task: any) => (
+ render: (_value: unknown, task: AnnotationTaskListItem) => (
{operations.map((operation) => (
);
-}
\ No newline at end of file
+}
diff --git a/frontend/src/pages/DataAnnotation/annotation.const.tsx b/frontend/src/pages/DataAnnotation/annotation.const.tsx
index 7310547..77b5ba9 100644
--- a/frontend/src/pages/DataAnnotation/annotation.const.tsx
+++ b/frontend/src/pages/DataAnnotation/annotation.const.tsx
@@ -6,6 +6,64 @@ import {
CloseCircleOutlined,
} from "@ant-design/icons";
+type AnnotationTaskStatistics = {
+ accuracy?: number | string;
+ averageTime?: number | string;
+ reviewCount?: number | string;
+};
+
+type AnnotationTaskPayload = {
+ id?: string;
+ labelingProjId?: string;
+ labelingProjectId?: string;
+ projId?: string;
+ labeling_project_id?: string;
+ name?: string;
+ description?: string;
+ datasetId?: string;
+ datasetName?: string;
+ dataset_name?: string;
+ totalCount?: number;
+ total_count?: number;
+ annotatedCount?: number;
+ annotated_count?: number;
+ inProgressCount?: number;
+ in_progress_count?: number;
+ segmentationEnabled?: boolean;
+ segmentation_enabled?: boolean;
+ createdAt?: string;
+ created_at?: string;
+ updatedAt?: string;
+ updated_at?: string;
+ status?: string;
+ statistics?: AnnotationTaskStatistics;
+ [key: string]: unknown;
+};
+
+export type AnnotationTaskListItem = {
+ id?: string;
+ labelingProjId?: string;
+ projId?: string;
+ name?: string;
+ description?: string;
+ datasetId?: string;
+ datasetName?: string;
+ totalCount?: number;
+ annotatedCount?: number;
+ inProgressCount?: number;
+ segmentationEnabled?: boolean;
+ createdAt?: string;
+ updatedAt?: string;
+ icon?: JSX.Element;
+ iconColor?: string;
+ status?: {
+ label: string;
+ color: string;
+ };
+ statistics?: { label: string; value: string | number }[];
+ [key: string]: unknown;
+};
+
export const AnnotationTaskStatusMap = {
[AnnotationTaskStatus.ACTIVE]: {
label: "活跃",
@@ -27,9 +85,11 @@ export const AnnotationTaskStatusMap = {
},
};
-export function mapAnnotationTask(task: any) {
+export function mapAnnotationTask(task: AnnotationTaskPayload): AnnotationTaskListItem {
// Normalize labeling project id from possible backend field names
const labelingProjId = task?.labelingProjId || task?.labelingProjectId || task?.projId || task?.labeling_project_id || "";
+ const segmentationEnabled = task?.segmentationEnabled ?? task?.segmentation_enabled ?? false;
+ const inProgressCount = task?.inProgressCount ?? task?.in_progress_count ?? 0;
const statsArray = task?.statistics
? [
@@ -45,6 +105,8 @@ export function mapAnnotationTask(task: any) {
// provide consistent field for components
labelingProjId,
projId: labelingProjId,
+ segmentationEnabled,
+ inProgressCount,
name: task.name,
description: task.description || "",
datasetName: task.datasetName || task.dataset_name || "-",
@@ -478,4 +540,4 @@ export const TemplateTypeMap = {
label: "自定义",
value: TemplateType.CUSTOM
},
-}
\ No newline at end of file
+}
diff --git a/runtime/datamate-python/app/module/annotation/schema/mapping.py b/runtime/datamate-python/app/module/annotation/schema/mapping.py
index f094c55..7e7ef6c 100644
--- a/runtime/datamate-python/app/module/annotation/schema/mapping.py
+++ b/runtime/datamate-python/app/module/annotation/schema/mapping.py
@@ -61,6 +61,7 @@ class DatasetMappingResponse(BaseModel):
)
total_count: int = Field(0, alias="totalCount", description="数据集总数据量")
annotated_count: int = Field(0, alias="annotatedCount", description="已标注数据量")
+ in_progress_count: int = Field(0, alias="inProgressCount", description="分段标注中数据量")
created_at: datetime = Field(..., alias="createdAt", description="创建时间")
updated_at: Optional[datetime] = Field(None, alias="updatedAt", description="更新时间")
deleted_at: Optional[datetime] = Field(None, alias="deletedAt", description="删除时间")
diff --git a/runtime/datamate-python/app/module/annotation/service/mapping.py b/runtime/datamate-python/app/module/annotation/service/mapping.py
index 5df9ab1..9bf51e8 100644
--- a/runtime/datamate-python/app/module/annotation/service/mapping.py
+++ b/runtime/datamate-python/app/module/annotation/service/mapping.py
@@ -8,6 +8,7 @@ import uuid
from app.core.logging import get_logger
from app.db.models import LabelingProject, AnnotationTemplate, AnnotationResult, LabelingProjectFile
+from app.db.models.annotation_management import ANNOTATION_STATUS_IN_PROGRESS
from app.db.models.dataset_management import Dataset, DatasetFiles
from app.module.annotation.schema import (
DatasetMappingCreateRequest,
@@ -40,7 +41,7 @@ class DatasetMappingService:
self,
project_id: str,
dataset_id: str
- ) -> Tuple[int, int]:
+ ) -> Tuple[int, int, int]:
"""
获取项目的统计数据
@@ -49,7 +50,7 @@ class DatasetMappingService:
dataset_id: 数据集ID
Returns:
- (total_count, annotated_count) 元组
+ (total_count, annotated_count, in_progress_count) 元组
"""
# 获取标注项目快照数据量(只统计快照内的文件)
total_result = await self.db.execute(
@@ -71,7 +72,16 @@ class DatasetMappingService:
)
annotated_count = int(annotated_result.scalar() or 0)
- return total_count, annotated_count
+ # 获取分段标注中数据量(标注状态为 IN_PROGRESS)
+ in_progress_result = await self.db.execute(
+ select(func.count(func.distinct(AnnotationResult.file_id))).where(
+ AnnotationResult.project_id == project_id,
+ AnnotationResult.annotation_status == ANNOTATION_STATUS_IN_PROGRESS,
+ )
+ )
+ in_progress_count = int(in_progress_result.scalar() or 0)
+
+ return total_count, annotated_count, in_progress_count
async def _to_response_from_row(
self,
@@ -110,7 +120,7 @@ class DatasetMappingService:
logger.debug(f"Included template details for template_id: {template_id}")
# 获取统计数据
- total_count, annotated_count = await self._get_project_stats(
+ total_count, annotated_count, in_progress_count = await self._get_project_stats(
mapping.id, mapping.dataset_id
)
@@ -127,6 +137,7 @@ class DatasetMappingService:
"segmentation_enabled": segmentation_enabled,
"total_count": total_count,
"annotated_count": annotated_count,
+ "in_progress_count": in_progress_count,
"created_at": mapping.created_at,
"updated_at": mapping.updated_at,
"deleted_at": mapping.deleted_at,
@@ -177,9 +188,9 @@ class DatasetMappingService:
logger.debug(f"Included template details for template_id: {template_id}")
# 获取统计数据
- total_count, annotated_count = 0, 0
+ total_count, annotated_count, in_progress_count = 0, 0, 0
if dataset_id:
- total_count, annotated_count = await self._get_project_stats(
+ total_count, annotated_count, in_progress_count = await self._get_project_stats(
mapping.id, dataset_id
)
@@ -197,6 +208,7 @@ class DatasetMappingService:
"segmentation_enabled": segmentation_enabled,
"total_count": total_count,
"annotated_count": annotated_count,
+ "in_progress_count": in_progress_count,
"created_at": mapping.created_at,
"updated_at": mapping.updated_at,
"deleted_at": mapping.deleted_at,