// 首页面板JavaScript // 页面加载时初始化 document.addEventListener('DOMContentLoaded', function() { loadDashboardStats(); loadRecentRecords(); }); // 加载仪表板统计数据 async function loadDashboardStats() { try { // 并行加载项目和工时统计 const [projectsResponse, recentRecordsResponse] = await Promise.all([ apiGet('/api/projects'), loadThisWeekHours() ]); // 更新活跃项目数 const activeProjects = projectsResponse.data.filter(p => p.is_active).length; updateStatValue('total-projects', activeProjects); // 更新本周工时 updateStatValue('this-week-hours', recentRecordsResponse.weeklyHours || '0:00'); // 加载本月记录数 const thisMonthCount = await loadThisMonthRecordsCount(); updateStatValue('this-month-records', thisMonthCount); } catch (error) { console.error('加载仪表板统计失败:', error); // 显示默认值 updateStatValue('total-projects', '0'); updateStatValue('this-week-hours', '0:00'); updateStatValue('this-month-records', '0'); } } // 更新统计值 function updateStatValue(elementId, value) { const element = document.getElementById(elementId); if (element) { element.textContent = value; } } // 加载本周工时 async function loadThisWeekHours() { try { const weekRange = getThisWeekRange(); const url = `/api/timerecords?start_date=${weekRange.start}&end_date=${weekRange.end}`; const response = await apiGet(url); // 计算本周总工时 let totalHours = 0; response.data.forEach(record => { if (record.hours && record.hours !== '-') { totalHours += hoursToDecimal(record.hours); } }); return { weeklyHours: decimalToHours(totalHours), recordCount: response.data.length }; } catch (error) { console.error('加载本周工时失败:', error); return { weeklyHours: '0:00', recordCount: 0 }; } } // 加载本月记录数 async function loadThisMonthRecordsCount() { try { const today = new Date(); const firstDayOfMonth = new Date(today.getFullYear(), today.getMonth(), 1); const lastDayOfMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0); const startDate = firstDayOfMonth.toISOString().split('T')[0]; const endDate = lastDayOfMonth.toISOString().split('T')[0]; const url = `/api/timerecords?start_date=${startDate}&end_date=${endDate}`; const response = await apiGet(url); return response.data.length; } catch (error) { console.error('加载本月记录数失败:', error); return 0; } } // 加载最近记录 async function loadRecentRecords() { try { // 获取最近7天的记录 const endDate = new Date(); const startDate = new Date(); startDate.setDate(endDate.getDate() - 6); // 最近7天 const url = `/api/timerecords?start_date=${startDate.toISOString().split('T')[0]}&end_date=${endDate.toISOString().split('T')[0]}`; const response = await apiGet(url); renderRecentRecords(response.data.slice(0, 5)); // 只显示最近5条 } catch (error) { console.error('加载最近记录失败:', error); const container = document.getElementById('recent-records-list'); if (container) { container.innerHTML = '

加载失败

'; } } } // 渲染最近记录 function renderRecentRecords(records) { const container = document.getElementById('recent-records-list'); if (!container) return; if (records.length === 0) { container.innerHTML = '

暂无最近记录

'; return; } container.innerHTML = `
${records.map(record => { const projectDisplay = record.project ? (record.project.project_type === 'traditional' ? `${record.project.customer_name} ${record.project.project_code}` : `${record.project.customer_name} ${record.project.contract_number}`) : '-'; const rowClass = getRowClass(record); return ` `; }).join('')}
日期 事件 项目 工时
${formatDate(record.date)} ${isToday(record.date) ? '今天' : ''} ${escapeHtml(record.event_description || '-')} ${escapeHtml(projectDisplay)} ${record.hours || '-'}
`; } // 获取行的CSS类名(根据是否为休息日) function getRowClass(record) { if (record.is_holiday) { if (record.is_working_on_holiday) { return 'working-holiday-row'; // 休息日工作 } else { return 'holiday-row'; // 休息日休息 } } return ''; } // HTML转义函数 function escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } // 添加今天徽章样式 if (!document.querySelector('#today-badge-styles')) { const style = document.createElement('style'); style.id = 'today-badge-styles'; style.textContent = ` .today-badge { background-color: #3498db; color: white; padding: 2px 6px; border-radius: 3px; font-size: 10px; font-weight: 600; margin-left: 5px; } .recent-records-table { overflow-x: auto; } .recent-records-table .data-table { margin-bottom: 0; } .recent-records-table .data-table td { font-size: 13px; padding: 10px 8px; } `; document.head.appendChild(style); }