feat&fix: add brief task status retrieval and improve task status update mechanism
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
// filepath: /home/adlsdztony/codes/OSWorld/monitor/static/index.js
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
fetchTasks();
|
||||
// 筛选功能绑定
|
||||
// Bind filter functionality
|
||||
document.getElementById('total-tasks').parentElement.addEventListener('click', () => setTaskFilter('all'));
|
||||
document.getElementById('active-tasks').parentElement.addEventListener('click', () => setTaskFilter('active'));
|
||||
document.getElementById('completed-tasks').parentElement.addEventListener('click', () => setTaskFilter('completed'));
|
||||
@@ -24,11 +23,118 @@ function refreshPage() {
|
||||
// Store in sessionStorage
|
||||
sessionStorage.setItem('expandedTaskTypes', JSON.stringify(expandedTaskTypes));
|
||||
|
||||
fetchTasks();
|
||||
// Only fetch brief data for update to improve refresh speed
|
||||
fetchTasksForRefresh();
|
||||
}
|
||||
|
||||
function fetchTasksForRefresh() {
|
||||
fetch('/api/tasks/brief')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Update stored data
|
||||
allTaskData = data;
|
||||
// Only update statistics and task status, do not fully re-render
|
||||
updateStatistics(data);
|
||||
updateTaskStatus(data);
|
||||
})
|
||||
.catch(error => console.error('Error refreshing tasks:', error));
|
||||
}
|
||||
|
||||
// New function: only update task status, do not re-render the entire list
|
||||
function updateTaskStatus(data) {
|
||||
// Update the status display of each task
|
||||
Object.entries(data).forEach(([taskType, tasks]) => {
|
||||
tasks.forEach(task => {
|
||||
// Find the corresponding task card
|
||||
const taskCard = document.querySelector(`.task-card[data-task-id="${task.id}"][data-task-type="${taskType}"]`);
|
||||
if (!taskCard) return;
|
||||
|
||||
// Update status display
|
||||
const statusElement = taskCard.querySelector('.task-status');
|
||||
if (statusElement) {
|
||||
// Remove all status classes
|
||||
statusElement.classList.remove('status-not-started', 'status-preparing', 'status-running', 'status-completed', 'status-error', 'status-unknown');
|
||||
|
||||
// Set new status class and icon
|
||||
let statusClass = '';
|
||||
let statusIcon = '';
|
||||
|
||||
switch(task.status.status) {
|
||||
case 'Not Started':
|
||||
statusClass = 'status-not-started';
|
||||
statusIcon = 'fa-hourglass-start';
|
||||
break;
|
||||
case 'Preparing':
|
||||
case 'Initializing':
|
||||
statusClass = 'status-preparing';
|
||||
statusIcon = 'fa-spinner fa-pulse';
|
||||
break;
|
||||
case 'Running':
|
||||
statusClass = 'status-running';
|
||||
statusIcon = 'fa-running';
|
||||
break;
|
||||
case 'Done':
|
||||
case 'Done (Message Exit)':
|
||||
case 'Done (Max Steps)':
|
||||
statusClass = 'status-completed';
|
||||
statusIcon = 'fa-check-circle';
|
||||
break;
|
||||
case 'Error':
|
||||
statusClass = 'status-error';
|
||||
statusIcon = 'fa-exclamation-circle';
|
||||
break;
|
||||
default:
|
||||
statusClass = 'status-unknown';
|
||||
statusIcon = 'fa-question-circle';
|
||||
break;
|
||||
}
|
||||
|
||||
statusElement.classList.add(statusClass);
|
||||
statusElement.innerHTML = `<i class="fas ${statusIcon}"></i> ${task.status.status}`;
|
||||
}
|
||||
|
||||
// Update progress bar
|
||||
if (task.status.progress > 0) {
|
||||
const progressText = taskCard.querySelector('.task-details div:first-child');
|
||||
if (progressText) {
|
||||
progressText.innerHTML = `<i class="fas fa-chart-line"></i> Progress: ${task.status.progress}/${task.status.max_steps} step(s)`;
|
||||
}
|
||||
|
||||
const progressFill = taskCard.querySelector('.progress-fill');
|
||||
if (progressFill) {
|
||||
const percentage = (task.status.progress / task.status.max_steps) * 100;
|
||||
progressFill.style.width = `${percentage}%`;
|
||||
}
|
||||
|
||||
const progressPercentage = taskCard.querySelector('.progress-percentage');
|
||||
if (progressPercentage) {
|
||||
const percentage = (task.status.progress / task.status.max_steps) * 100;
|
||||
progressPercentage.textContent = `${Math.round(percentage)}%`;
|
||||
}
|
||||
}
|
||||
|
||||
// Update last update time
|
||||
const timestamp = taskCard.querySelector('.timestamp');
|
||||
if (timestamp && task.status.last_update) {
|
||||
timestamp.innerHTML = `<i class="far fa-clock"></i> Last Update: ${task.status.last_update}`;
|
||||
}
|
||||
|
||||
// Update result info
|
||||
if (task.status.result) {
|
||||
let resultDiv = taskCard.querySelector('.task-result');
|
||||
if (!resultDiv) {
|
||||
resultDiv = document.createElement('div');
|
||||
resultDiv.className = 'task-result';
|
||||
taskCard.querySelector('.task-details').appendChild(resultDiv);
|
||||
}
|
||||
resultDiv.innerHTML = `<strong><i class="fas fa-flag-checkered"></i> Result:</strong> ${task.status.result}`;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fetchTasks() {
|
||||
fetch('/api/tasks')
|
||||
fetch('/api/tasks/brief')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
allTaskData = data;
|
||||
@@ -42,7 +148,7 @@ function setTaskFilter(filter) {
|
||||
currentFilter = filter;
|
||||
if (!allTaskData) return;
|
||||
renderTasks(allTaskData);
|
||||
// 高亮选中卡片
|
||||
// Highlight selected card
|
||||
document.querySelectorAll('.stat-card').forEach(card => card.classList.remove('selected'));
|
||||
if (filter === 'all') {
|
||||
document.getElementById('total-tasks').parentElement.classList.add('selected');
|
||||
@@ -55,7 +161,7 @@ function setTaskFilter(filter) {
|
||||
}
|
||||
}
|
||||
|
||||
// 更新统计信息
|
||||
// Update statistics info
|
||||
function updateStatistics(data) {
|
||||
let totalTasks = 0;
|
||||
let activeTasks = 0;
|
||||
@@ -80,7 +186,7 @@ function updateStatistics(data) {
|
||||
document.getElementById('completed-tasks').textContent = completedTasks;
|
||||
document.getElementById('error-tasks').textContent = errorTasks;
|
||||
|
||||
// 高亮显示当前选中的统计卡片
|
||||
// Highlight the currently selected statistics card
|
||||
document.querySelectorAll('.stat-card').forEach(card => card.classList.remove('selected'));
|
||||
if (currentFilter === 'all') {
|
||||
document.getElementById('total-tasks').parentElement.classList.add('selected');
|
||||
@@ -176,6 +282,9 @@ function renderTasks(data) {
|
||||
tasks.forEach(task => {
|
||||
const taskCard = document.createElement('div');
|
||||
taskCard.className = 'task-card';
|
||||
// Add data attributes for later updates
|
||||
taskCard.setAttribute('data-task-id', task.id);
|
||||
taskCard.setAttribute('data-task-type', taskType);
|
||||
|
||||
const taskHeader = document.createElement('div');
|
||||
taskHeader.className = 'task-header';
|
||||
|
||||
Reference in New Issue
Block a user