89 lines
4.2 KiB
JavaScript
89 lines
4.2 KiB
JavaScript
const WeatherTable = {
|
||
display(historyData = [], forecastData = []) {
|
||
historyData = Array.isArray(historyData) ? historyData : [];
|
||
forecastData = Array.isArray(forecastData) ? forecastData : [];
|
||
|
||
if (historyData.length === 0 && forecastData.length === 0) {
|
||
return;
|
||
}
|
||
|
||
const showPastEl = document.getElementById('showPastForecast');
|
||
const nowTs = Date.now();
|
||
const future3hTs = nowTs + 3 * 60 * 60 * 1000;
|
||
const showPast = !!(showPastEl && showPastEl.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 || (showPast && isPast);
|
||
});
|
||
const taggedHistory = historyData.map(item => ({ ...item, __source: '实测' }));
|
||
const taggedForecast = displayedForecast.map(item => ({ ...item, __source: '预报' }));
|
||
const allData = [...taggedHistory, ...taggedForecast];
|
||
const hasForecast = taggedForecast.length > 0;
|
||
const sortedData = allData.sort((a, b) => new Date(b.date_time) - new Date(a.date_time));
|
||
|
||
const tableBody = document.getElementById('tableBody');
|
||
if (!tableBody) return;
|
||
|
||
tableBody.innerHTML = '';
|
||
|
||
// 动态表头:在有预报时加入“降水概率 (%)”
|
||
const headerRow = document.getElementById('tableHeader');
|
||
if (headerRow) {
|
||
headerRow.innerHTML = '';
|
||
const addTh = (text) => {
|
||
const th = document.createElement('th');
|
||
th.textContent = text;
|
||
headerRow.appendChild(th);
|
||
};
|
||
['时间','温度 (°C)','湿度 (%)','气压 (hPa)','风速 (m/s)','风向 (°)','雨量 (mm)'].forEach(addTh);
|
||
if (hasForecast) addTh('降水概率 (%)');
|
||
['光照 (lux)','紫外线'].forEach(addTh);
|
||
}
|
||
|
||
const fmt = (v, digits) => (v === null || v === undefined || v === '' || isNaN(Number(v))) ? '' : Number(v).toFixed(digits);
|
||
|
||
sortedData.forEach(row => {
|
||
const tr = document.createElement('tr');
|
||
const isForecast = row.__source === '预报';
|
||
if (isForecast) {
|
||
tr.style.backgroundColor = 'rgba(255, 165, 0, 0.08)';
|
||
}
|
||
const issuedBadge = (() => {
|
||
if (!isForecast) return '';
|
||
const lead = (typeof row.lead_hours === 'number' && row.lead_hours >= 0) ? ` +${row.lead_hours}h` : '';
|
||
const issued = row.issued_at ? new Date(String(row.issued_at).replace(' ', 'T')) : null;
|
||
const issuedStr = issued ? `${String(issued.getHours()).padStart(2,'0')}:${String(issued.getMinutes()).padStart(2,'0')}` : '-';
|
||
return `<span style="font-size: 12px; color: #6b7280;">(发布: ${issuedStr}${lead})</span>`;
|
||
})();
|
||
const timeCell = `${row.date_time || ''}${isForecast ? ' <span style=\"font-size: 12px; color: #ff8c00;\">[预报]</span>' : ''}${isForecast ? `<br>${issuedBadge}` : ''}`;
|
||
const columns = [
|
||
`<td>${timeCell}</td>`,
|
||
`<td>${fmt(row.temperature, 1)}</td>`,
|
||
`<td>${fmt(row.humidity, 1)}</td>`,
|
||
`<td>${fmt(row.pressure, 1)}</td>`,
|
||
`<td>${fmt(row.wind_speed, 1)}</td>`,
|
||
`<td>${fmt(row.wind_direction, 0)}</td>`,
|
||
`<td>${fmt(row.rainfall, 2)}</td>`
|
||
];
|
||
if (hasForecast) {
|
||
const val = isForecast && row.precip_prob !== null && row.precip_prob !== undefined ? row.precip_prob : '-';
|
||
columns.push(`<td>${val}</td>`);
|
||
}
|
||
columns.push(
|
||
`<td>${fmt(row.light, 0)}</td>`,
|
||
`<td>${fmt(row.uv, 1)}</td>`
|
||
);
|
||
tr.innerHTML = columns.join('');
|
||
tableBody.appendChild(tr);
|
||
});
|
||
|
||
const forecastToggleContainer = document.getElementById('forecastToggleContainer');
|
||
if (forecastToggleContainer) {
|
||
forecastToggleContainer.style.display = forecastData.length > 0 ? 'flex' : 'none';
|
||
}
|
||
}
|
||
};
|
||
|
||
window.WeatherTable = WeatherTable;
|