// 表格渲染功能 const WeatherTable = { display(historyData = [], forecastData = []) { const tbody = document.getElementById('tableBody'); if (!tbody) return; tbody.innerHTML = ''; historyData = Array.isArray(historyData) ? historyData : []; forecastData = Array.isArray(forecastData) ? forecastData : []; const nowTs = Date.now(); const future3hTs = nowTs + 3 * 60 * 60 * 1000; const showPastForecastEl = document.getElementById('showPastForecast'); const shouldShowPast = !!(showPastForecastEl && showPastForecastEl.checked); const displayedForecast = forecastData.filter(item => { const t = new Date(item.date_time).getTime(); const isFuture3h = t > nowTs && t <= future3hTs; const isPast = t <= nowTs; return isFuture3h || (shouldShowPast && isPast); }); const hasForecast = displayedForecast.length > 0; const forecastToggleContainer = document.getElementById('forecastToggleContainer'); if (forecastToggleContainer) { forecastToggleContainer.style.display = forecastData.length > 0 ? 'block' : 'none'; } const thead = document.getElementById('tableHeader'); if (thead) { thead.innerHTML = ''; const fixedHeaders = ['时间', '温度 (°C)', '湿度 (%)', '气压 (hPa)', '风速 (m/s)', '风向 (°)', '雨量 (mm)']; fixedHeaders.forEach(text => { const th = document.createElement('th'); th.textContent = text; th.className = 'bg-gray-50 font-semibold'; thead.appendChild(th); }); if (hasForecast) { const th = document.createElement('th'); th.textContent = '降水概率 (%)'; th.className = 'bg-gray-50 font-semibold'; thead.appendChild(th); } const remainingHeaders = ['光照 (lux)', '紫外线']; remainingHeaders.forEach(text => { const th = document.createElement('th'); th.textContent = text; th.className = 'bg-gray-50 font-semibold'; thead.appendChild(th); }); } const allData = []; historyData.forEach(item => { allData.push({ ...item, source: '实测' }); }); displayedForecast.forEach(item => { allData.push({ ...item, source: '预报', light: null, wind_speed: item.wind_speed !== null ? item.wind_speed : 0, wind_direction: item.wind_direction !== null ? item.wind_direction : 0 }); }); allData.sort((a, b) => new Date(b.date_time) - new Date(a.date_time)); const fmt2 = v => (v === null || v === undefined ? '-' : Number(v).toFixed(2)); const fmt3 = v => (v === null || v === undefined ? '-' : Number(v).toFixed(3)); allData.forEach(item => { const row = document.createElement('tr'); if (item.source === '预报') { row.style.backgroundColor = 'rgba(255, 165, 0, 0.08)'; } const columns = [ `${item.date_time}${hasForecast ? ` [${item.source}]` : ''}`, `${fmt2(item.temperature)}`, `${fmt2(item.humidity)}`, `${fmt2(item.pressure)}`, `${fmt2(item.wind_speed)}`, `${fmt2(item.wind_direction)}`, `${fmt3(item.rainfall)}` ]; if (hasForecast) { columns.push(`${item.source === '预报' && item.precip_prob !== null && item.precip_prob !== undefined ? item.precip_prob : '-'}`); } columns.push( `${(item.light !== null && item.light !== undefined) ? Number(item.light).toFixed(2) : '-'}`, `${(item.uv !== null && item.uv !== undefined) ? Number(item.uv).toFixed(2) : '-'}` ); row.innerHTML = columns.join(''); tbody.appendChild(row); }); } }; window.WeatherTable = WeatherTable;