# 标注结果持久化修复 ## 问题描述 1. **标注结果没有加载**:用户保存标注后,再次打开标注界面时,之前的标注结果没有被加载 2. **任务状态没有更新**:保存标注后,任务列表中的状态没有正确显示为"已完成" ## 问题根源 ### 1. 前端没有加载已有标注 在 `annotation-view.tsx` 中,编辑器初始化时: - 只创建了新的空白标注 (`as.createAnnotation()`) - 没有检查是否已有标注结果 - 没有将已有标注加载到编辑器中 ### 2. 保存逻辑不正确 保存标注时: - 每次都创建新的标注记录,而不是更新已有的 - 任务状态更新逻辑不正确(只是增加进度,而不是直接标记为完成) ## 修复方案 ### 1. 加载已有标注 (annotation-view.tsx) #### 修改数据加载逻辑 ```typescript // 在 loadData 函数中添加 const existingAnnotations = await getTaskAnnotations(id); console.log('Existing annotations:', existingAnnotations); // Store existing annotations for later use if (existingAnnotations.length > 0) { // Use the most recent annotation const latestAnnotation = existingAnnotations[0]; annotationResultRef.current = latestAnnotation.result; console.log('Loaded existing annotation:', latestAnnotation); } ``` #### 修改编辑器初始化逻辑 ```typescript onStorageInitialized: (LS: any) => { const initAnnotation = () => { const as = LS.annotationStore; // Check if we have existing annotation data const existingResult = annotationResultRef.current; if (existingResult && existingResult.result && Array.isArray(existingResult.result)) { console.log('Loading existing annotation:', existingResult); // Create annotation with existing data const annotation = as.createAnnotation({ userGenerate: false, result: existingResult.result, }); as.selectAnnotation(annotation.id); // Set up snapshot listener // ... } else { console.log('Creating new annotation'); // Create new empty annotation const annotation = as.createAnnotation(); as.selectAnnotation(annotation.id); // ... } }; setTimeout(initAnnotation, 100); } ``` ### 2. 修复保存逻辑 #### 检查并更新已有标注 ```typescript // Check if annotation already exists for this task const existingAnnotations = await getTaskAnnotations(id); if (existingAnnotations.length > 0) { // Update existing annotation const existingAnnotation = existingAnnotations[0]; await updateAnnotation(existingAnnotation.id, { result: resultData, }); console.log('Updated existing annotation:', existingAnnotation.id); } else { // Create new annotation await createAnnotation({ task_id: id, user_id: 'current_user', result: resultData, }); console.log('Created new annotation'); } ``` #### 直接标记任务为已完成 ```typescript // Update task status to completed await updateTask(id, { status: 'completed', }); console.log('Task marked as completed'); ``` ### 3. 添加必要的 API 导入 ```typescript import { getTask, getProject, createAnnotation, updateTask, getTaskAnnotations, // 新增 updateAnnotation // 新增 } from '../../services/api'; ``` ## 修复效果 ### 修复前 - ❌ 再次打开标注界面时,之前的标注结果丢失 - ❌ 每次保存都创建新的标注记录(数据库中有重复) - ❌ 任务状态不会变为"已完成" ### 修复后 - ✅ 再次打开标注界面时,自动加载之前的标注结果 - ✅ 保存时更新已有标注,而不是创建新记录 - ✅ 保存后任务状态正确显示为"已完成" - ✅ 任务列表中的进度和状态正确更新 ## 测试步骤 1. **创建新任务并标注** - 打开一个待处理的任务 - 完成标注 - 点击"保存"按钮 - 验证:返回任务列表后,任务状态显示为"已完成" 2. **重新打开已标注的任务** - 在任务列表中点击已完成的任务 - 验证:编辑器中显示之前保存的标注结果 - 修改标注 - 再次保存 - 验证:修改被正确保存(没有创建重复记录) 3. **检查数据库** - 查看 `annotations` 表 - 验证:每个任务只有一条标注记录 - 验证:`updated_at` 字段在修改后正确更新 ## 相关文件 - `web/apps/lq_label/src/views/annotation-view/annotation-view.tsx` - 标注视图组件 - `web/apps/lq_label/src/services/api.ts` - API 服务层 - `backend/routers/annotation.py` - 标注 API 路由 - `backend/routers/task.py` - 任务 API 路由 ## 注意事项 1. **LabelStudio 数据格式** - `createAnnotation()` 的 `userGenerate: false` 参数表示使用预加载的数据 - `result` 字段必须是数组格式 2. **并发问题** - 当前实现假设一个任务只有一个标注者 - 如果需要支持多人标注,需要修改逻辑(根据 user_id 过滤) 3. **性能优化** - 当前每次保存都会查询已有标注 - 可以考虑在组件状态中缓存标注 ID,避免重复查询 ## 后续优化建议 1. **添加用户认证** - 当前使用硬编码的 `'current_user'` - 应该从认证上下文中获取真实的用户 ID 2. **支持多人标注** - 根据用户 ID 加载和保存标注 - 显示其他用户的标注(只读模式) 3. **添加自动保存** - 定期自动保存标注结果 - 避免用户忘记保存导致数据丢失 4. **添加版本历史** - 保存标注的历史版本 - 支持回退到之前的版本