/**
* 我的任务管理模块 JavaScript
* 提供已领取任务的查看和跳转标注功能
*/
(function() {
'use strict';
// 引用全局的翻译函数
// 翻译函数由 i18n-helper.js 提供
// 模块私有状态
let listPaginator = null;
let container = null;
// 我的任务管理模块
const UserMyTasks = {
init: function(containerElement) {
container = containerElement;
this.initPaginators();
this.initEventListeners();
this.loadMyTasks();
},
initPaginators: function() {
// 初始化我的任务列表分页器
listPaginator = createPaginator('myTasks', {
initialPage: 1,
initialPageSize: 20,
onPageChange: (page, pageSize) => {
this.loadMyTasks();
},
onPageSizeChange: (pageSize) => {
this.loadMyTasks();
}
});
},
initEventListeners: function() {
// 刷新列表
const refreshBtn = container.querySelector('#refreshMyTasksBtn');
if (refreshBtn) {
refreshBtn.addEventListener('click', () => {
this.loadMyTasks();
});
}
// 使用说明按钮
const showUsageBtn = container.querySelector('#showMyTasksUsageBtn');
if (showUsageBtn) {
showUsageBtn.addEventListener('click', () => {
this.showMyTasksUsage();
});
}
},
loadMyTasks: async function() {
if (!listPaginator) return;
const tbody = container.querySelector('#myTasksTableBody');
if (!tbody) return;
try {
tbody.innerHTML = '
| 加载中... |
';
const skip = listPaginator.getSkip();
const limit = listPaginator.getLimit();
const tasks = await apiGet(`/datasets/tasks/my?skip=${skip}&limit=${limit}`);
const emptyState = container.querySelector('#myTasksEmptyState');
const paginationContainer = container.querySelector('#myTasksPaginationContainer');
if (tasks.length === 0) {
tbody.innerHTML = '';
if (emptyState) emptyState.classList.remove('hidden');
if (paginationContainer) paginationContainer.classList.add('hidden');
return;
}
if (emptyState) emptyState.classList.add('hidden');
if (paginationContainer) paginationContainer.classList.remove('hidden');
tbody.innerHTML = tasks.map(task => {
const category = task.category
? `${escapeHtml(task.category)}`
: '-';
const evaluationDimensions = task.evaluation_dimensions && task.evaluation_dimensions.length > 0
? `${task.evaluation_dimensions.map(dim =>
`${escapeHtml(dim.name)}`
).join('')}
`
: '-';
const deadlineInfo = this.formatDeadline(task.deadline);
const taskDescription = task.task_description
? `${escapeHtml(task.task_description)}
`
: '-';
const evaluationPurpose = task.evaluation_purpose
? `${escapeHtml(task.evaluation_purpose)}
`
: '-';
// 渲染进度
const progressHtml = this.renderProgress(task);
return `
| ${escapeHtml(task.dataset_name)} |
${taskDescription} |
${category} |
${task.target_annotation_count}${t('task.qaUnit')} |
${progressHtml} |
${escapeHtml(task.project_name || '-')} |
${evaluationPurpose} |
${deadlineInfo} |
${evaluationDimensions} |
|
`;
}).join('');
// 更新分页信息
const hasMore = tasks.length === limit;
listPaginator.setTotalCount((listPaginator.currentPage - 1) * limit + tasks.length + (hasMore ? 1 : 0));
listPaginator.render();
} catch (error) {
console.error('加载我的任务列表失败:', error);
tbody.innerHTML = '| 加载失败,请刷新重试 |
';
showError('加载我的任务列表失败: ' + (error.message || '未知错误'));
}
},
startAnnotation: function(datasetId) {
// 跳转到标注工作台
window.location.href = `/annotation?dataset_id=${datasetId}`;
},
releaseTask: async function(datasetId) {
// 确认退回任务
if (!confirm(t('task.releaseConfirm'))) {
return;
}
try {
// 调用退回任务API
await apiPost(`/datasets/tasks/${datasetId}/release`, {});
// 显示成功消息
showSuccess(t('task.taskReleased'));
// 刷新任务列表
this.loadMyTasks();
} catch (error) {
console.error(t('task.releaseFailed') + ':', error);
showError(t('task.releaseFailed') + ': ' + (error.message || t('common.unknownError')));
}
},
formatDeadline: function(deadlineString) {
if (!deadlineString) return '-';
try {
const deadline = new Date(deadlineString);
const now = new Date();
const diff = deadline - now;
const formattedDate = this.formatDateTime(deadlineString);
if (diff < 0) {
// 已过期
return `${formattedDate} (${t('task.expired')})`;
} else if (diff < 24 * 60 * 60 * 1000) {
// 少于24小时
const hours = Math.floor(diff / (60 * 60 * 1000));
const minutes = Math.floor((diff % (60 * 60 * 1000)) / (60 * 1000));
const timeLeft = t('task.expiresInMinutes', { hours: hours, minutes: minutes });
return `${formattedDate}
${timeLeft}`;
} else if (diff < 3 * 24 * 60 * 60 * 1000) {
// 少于3天
const days = Math.floor(diff / (24 * 60 * 60 * 1000));
const hours = Math.floor((diff % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000));
const timeLeft = t('task.expiresInHours', { days: days, hours: hours });
return `${formattedDate}
${timeLeft}`;
} else {
// 还有充足时间
return formattedDate;
}
} catch (e) {
return deadlineString;
}
},
formatDateTime: function(dateTimeString) {
if (!dateTimeString) return '-';
try {
const date = new Date(dateTimeString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
} catch (e) {
return dateTimeString;
}
},
renderProgress: function(task) {
if (task.annotated_count === undefined || task.annotated_count === null) {
return '-';
}
const total = task.target_annotation_count || 0;
const annotated = task.annotated_count || 0;
const rate = task.progress_rate || 0;
if (total === 0) {
return '-';
}
const percentage = Math.round(rate);
const progressBarClass = percentage === 100 ? 'progress-bar-complete' :
percentage >= 80 ? 'progress-bar-high' :
percentage >= 50 ? 'progress-bar-medium' :
'progress-bar-low';
return `
${annotated} / ${total} (${percentage}%)
`;
},
showMyTasksUsage: function() {
// 构建t('task.usageGuideTitle')内容
const usageContent = `
t('task.usageGuideTitle')
1. 任务查看
- 显示您已领取的所有标注任务
- 可以查看任务的详细信息,包括数据集名称、任务描述、分类、目标标注数量等
- 显示任务所属的项目名称、评估目的、要求完成时间等元数据
- 显示任务的评估维度,帮助您了解标注要求
2. 任务进度
- 实时显示每个任务的标注进度(已标注数量/目标数量)
- 进度条颜色表示完成情况:绿色(完成)、蓝色(高进度)、黄色(中等进度)、红色(低进度)
- 进度计算基于必填标注配置,只有完成所有必填配置才算完成一个QA对的标注
3. 任务分类
- 任务可能包含分类标签,表示该任务需要特定领域的专业知识
- 只有匹配您账户物种标签的任务才会显示在可领取任务列表中
- 没有分类标签的任务,所有用户都可以领取
4. 开始标注
- 点击"开始标注"按钮可以跳转到标注工作台
- 在标注工作台中,您可以看到该数据集的所有QA对和标注配置
- 根据评估维度和标注配置完成标注工作
- 标注完成后,进度会自动更新
5. 完成时间
- 如果任务设置了完成时间,会显示在任务列表中
- 接近或超过完成时间的任务会有颜色提示(红色表示已过期或即将过期)
- 请合理安排时间,按时完成标注任务
6. 任务刷新
- 点击"刷新"按钮可以更新任务列表和进度信息
- 建议在完成标注后刷新页面,查看最新的进度
使用建议
- 任务优先级:根据完成时间合理安排任务优先级,优先处理即将到期的任务
- 进度跟踪:定期查看任务进度,确保按时完成标注工作
- 标注质量:仔细阅读任务描述和评估维度,确保标注质量符合要求
- 必填配置:注意必填标注配置,必须完成所有必填配置才能算完成一个QA对的标注
- 任务理解:在开始标注前,仔细阅读任务描述、评估目的和评估维度,充分理解标注要求
`;
// 显示对话框(隐藏提交按钮,只显示关闭按钮)
openModal(t('task.usageGuideTitle'), usageContent, null, true);
}
};
// 导出到全局
window.UserMyTasks = UserMyTasks;
})();