| |
| |
| |
| |
|
|
| (function() { |
| 'use strict'; |
|
|
| |
| |
|
|
| |
| let listPaginator = null; |
| let container = null; |
|
|
| |
| const UserAvailableTasks = { |
| init: function(containerElement) { |
| container = containerElement; |
| this.initPaginators(); |
| this.initEventListeners(); |
| this.loadAvailableTasks(); |
| }, |
|
|
| initPaginators: function() { |
| |
| listPaginator = createPaginator('availableTasks', { |
| initialPage: 1, |
| initialPageSize: 20, |
| onPageChange: (page, pageSize) => { |
| this.loadAvailableTasks(); |
| }, |
| onPageSizeChange: (pageSize) => { |
| this.loadAvailableTasks(); |
| } |
| }); |
| }, |
|
|
| initEventListeners: function() { |
| |
| const refreshBtn = container.querySelector('#refreshAvailableTasksBtn'); |
| if (refreshBtn) { |
| refreshBtn.addEventListener('click', () => { |
| this.loadAvailableTasks(); |
| }); |
| } |
| }, |
|
|
| loadAvailableTasks: async function() { |
| if (!listPaginator) return; |
|
|
| const tbody = container.querySelector('#availableTasksTableBody'); |
| if (!tbody) return; |
|
|
| try { |
| tbody.innerHTML = '<tr><td colspan="9" class="loading">加载中...</td></tr>'; |
|
|
| const skip = listPaginator.getSkip(); |
| const limit = listPaginator.getLimit(); |
|
|
| const tasks = await apiGet(`/datasets/tasks/available?skip=${skip}&limit=${limit}`); |
|
|
| const emptyState = container.querySelector('#availableTasksEmptyState'); |
| const paginationContainer = container.querySelector('#availableTasksPaginationContainer'); |
|
|
| 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 categoryRequirement = task.category |
| ? `<span class="category-requirement has-category">${t('task.categoryRequirementPrefix')}${escapeHtml(task.category)}</span>` |
| : `<span class="category-requirement no-category">${t('task.noCategoryRestriction')}</span>`; |
|
|
| const evaluationDimensions = task.evaluation_dimensions && task.evaluation_dimensions.length > 0 |
| ? `<div class="evaluation-dimension-tags">${task.evaluation_dimensions.map(dim => |
| `<span class="evaluation-dimension-tag" title="${escapeHtml(dim.description || '')}">${escapeHtml(dim.name)}</span>` |
| ).join('')}</div>` |
| : '-'; |
|
|
| const deadline = task.deadline |
| ? this.formatDateTime(task.deadline) |
| : '-'; |
|
|
| const taskDescription = task.task_description |
| ? `<div class="task-description" title="${escapeHtml(task.task_description)}">${escapeHtml(task.task_description)}</div>` |
| : '-'; |
|
|
| const evaluationPurpose = task.evaluation_purpose |
| ? `<div class="evaluation-purpose" title="${escapeHtml(task.evaluation_purpose)}">${escapeHtml(task.evaluation_purpose)}</div>` |
| : '-'; |
|
|
| return ` |
| <tr> |
| <td>${escapeHtml(task.dataset_name)}</td> |
| <td>${taskDescription}</td> |
| <td>${categoryRequirement}</td> |
| <td>${task.target_annotation_count}${t('task.qaUnit')}</td> |
| <td>${escapeHtml(task.project_name || '-')}</td> |
| <td>${evaluationPurpose}</td> |
| <td>${deadline}</td> |
| <td>${evaluationDimensions}</td> |
| <td> |
| <div class="action-buttons"> |
| <button class="btn btn-sm btn-primary" onclick="window.UserAvailableTasks.claimTask(${task.dataset_id})">${t('task.claim')}</button> |
| </div> |
| </td> |
| </tr> |
| `; |
| }).join(''); |
|
|
| |
| |
| const hasMore = tasks.length === limit; |
| listPaginator.setTotalCount((listPaginator.currentPage - 1) * limit + tasks.length + (hasMore ? 1 : 0)); |
| listPaginator.render(); |
|
|
| } catch (error) { |
| console.error('Failed to load available tasks:', error); |
| tbody.innerHTML = `<tr><td colspan="9" class="loading">${t('task.loadFailed') || '加载失败,请刷新重试'}</td></tr>`; |
| showError((t('task.loadListFailed') || '加载可领取任务列表失败') + ': ' + (error.message || t('common.unknownError'))); |
| } |
| }, |
|
|
| claimTask: async function(datasetId) { |
| if (!confirm(t('task.claimConfirm'))) { |
| return; |
| } |
|
|
| try { |
| await apiPost(`/datasets/tasks/${datasetId}/claim`, {}); |
| showSuccess(t('task.claimSuccess')); |
| |
| this.loadAvailableTasks(); |
| } catch (error) { |
| console.error('Failed to claim task:', error); |
| const errorMessage = error.data?.detail || error.message || t('common.unknownError'); |
| showError(t('task.claimFailed') + ': ' + errorMessage); |
| } |
| }, |
|
|
| 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; |
| } |
| } |
| }; |
|
|
| |
| window.UserAvailableTasks = UserAvailableTasks; |
| })(); |
|
|