const WeatherApp = { cachedHistoryData: [], cachedForecastData: [], currentPage: 1, itemsPerPage: 10, filteredDevices: [], init() { WeatherUtils.initializeDateInputs(); WeatherMap.init(window.TIANDITU_KEY || ''); WeatherMap.loadStations(); setInterval(() => this.updateOnlineDevices(), 30000); this.bindUI(); window.addEventListener('query-history-data', () => this.queryHistoryData()); }, bindUI() { const stationInput = document.getElementById('stationInput'); if (stationInput) { stationInput.addEventListener('input', function() { this.value = this.value.toUpperCase().replace(/[^0-9A-F]/g, ''); }); stationInput.addEventListener('change', function() { const value = this.value.trim(); if (!value) return; if (/^[0-9A-F]+$/i.test(value)) { if (value.length <= 6) this.value = WeatherUtils.hexToDecimal(value); } else { const num = parseInt(value); if (!isNaN(num)) this.value = num.toString(); } }); } const showDeviceListBtn = document.getElementById('showDeviceList'); const modal = document.getElementById('deviceModal'); const closeBtn = document.querySelector('.close-modal'); const prevPageBtn = document.getElementById('prevPage'); const nextPageBtn = document.getElementById('nextPage'); const deviceListEl = document.getElementById('deviceList'); if (deviceListEl && modal) { deviceListEl.addEventListener('click', (e) => { const deviceItem = e.target.closest('.device-item'); if (!deviceItem) return; const decimalId = deviceItem.getAttribute('data-decimal-id'); const input = document.getElementById('stationInput'); if (input) input.value = decimalId; window.dispatchEvent(new CustomEvent('close-device-modal')); this.queryHistoryData(); }); } const showPastForecast = document.getElementById('showPastForecast'); if (showPastForecast) { showPastForecast.addEventListener('change', () => { WeatherTable.display(this.cachedHistoryData, this.cachedForecastData); }); } const legendMode = document.getElementById('legendMode'); if (legendMode) { legendMode.addEventListener('change', (e) => { const mode = e.target.value; if (window.WeatherChart && typeof window.WeatherChart.applyLegendMode === 'function') { window.WeatherChart.applyLegendMode(mode); } }); } window.switchLayer = (type) => WeatherMap.switchLayer(type); window.toggleMap = () => WeatherMap.toggleMap(); window.queryHistoryData = () => this.queryHistoryData(); }, updateDeviceList(page = 1) { const deviceListContainer = document.getElementById('deviceList'); if (!deviceListContainer) return; deviceListContainer.innerHTML = ''; this.filteredDevices = (WeatherMap.stations || []) .filter(station => station.device_type === 'WH65LP') .sort((a, b) => { const aOnline = WeatherUtils.isDeviceOnline(a.last_update); const bOnline = WeatherUtils.isDeviceOnline(b.last_update); if (aOnline === bOnline) return 0; return aOnline ? -1 : 1; }); const totalPages = Math.ceil(this.filteredDevices.length / this.itemsPerPage) || 1; this.currentPage = Math.min(Math.max(1, page), totalPages); const currentPageEl = document.getElementById('currentPage'); const totalPagesEl = document.getElementById('totalPages'); const prevBtn = document.getElementById('prevPage'); const nextBtn = document.getElementById('nextPage'); if (currentPageEl) currentPageEl.textContent = this.currentPage; if (totalPagesEl) totalPagesEl.textContent = totalPages; if (prevBtn) prevBtn.disabled = this.currentPage <= 1; if (nextBtn) nextBtn.disabled = this.currentPage >= totalPages; const startIndex = (this.currentPage - 1) * this.itemsPerPage; const endIndex = startIndex + this.itemsPerPage; const currentDevices = this.filteredDevices.slice(startIndex, endIndex); currentDevices.forEach(device => { const isOnline = WeatherUtils.isDeviceOnline(device.last_update); const deviceItem = document.createElement('div'); deviceItem.className = 'device-item'; deviceItem.setAttribute('data-decimal-id', device.decimal_id); deviceItem.innerHTML = `
${device.decimal_id} | ${device.name} | ${device.location || '未知位置'}
${isOnline ? '在线' : '离线'} `; deviceListContainer.appendChild(deviceItem); }); if (this.filteredDevices.length === 0) { deviceListContainer.innerHTML = '
暂无WH65LP设备
'; } }, async updateOnlineDevices() { try { const response = await fetch('/api/system/status'); const data = await response.json(); const onlineEl = document.getElementById('onlineDevices'); if (onlineEl) onlineEl.textContent = data.online_devices; } catch (error) { console.error('更新在线设备数量失败:', error); } }, async queryHistoryData() { const decimalId = (document.getElementById('stationInput')?.value || '').trim(); if (!decimalId) { alert('请输入站点编号'); return; } if (!/^\d+$/.test(decimalId)) { alert('请输入有效的十进制编号'); return; } const startTime = document.getElementById('startDate').value; const endTime = document.getElementById('endDate').value; const interval = document.getElementById('interval').value; const forecastProvider = document.getElementById('forecastProvider').value; if (!startTime || !endTime) { alert('请选择开始和结束时间'); return; } try { const historyParams = new URLSearchParams({ decimal_id: decimalId, start_time: startTime.replace('T', ' ') + ':00', end_time: endTime.replace('T', ' ') + ':00', interval: interval }); const historyResponse = await fetch(`/api/data?${historyParams}`); if (!historyResponse.ok) throw new Error('查询历史数据失败'); const responseData = await historyResponse.json(); const historyData = Array.isArray(responseData) ? responseData : []; let forecastData = []; if (forecastProvider && interval === '1hour') { try { const hexID = WeatherUtils.decimalToHex(decimalId); const stationID = `RS485-${hexID}`; const forecastParams = new URLSearchParams({ station_id: stationID, from: startTime.replace('T', ' ') + ':00', to: endTime.replace('T', ' ') + ':00', provider: forecastProvider, versions: '3' }); const forecastResponse = await fetch(`/api/forecast?${forecastParams}`); if (forecastResponse.ok) { const responseData = await forecastResponse.json(); forecastData = Array.isArray(responseData) ? responseData : []; console.log(`查询到 ${forecastData.length} 条预报数据`); } } catch (e) { console.warn('查询预报数据失败:', e); } } this.cachedHistoryData = historyData; this.cachedForecastData = forecastData; if (historyData.length === 0 && forecastData.length === 0) { alert('该时间段内无数据'); return; } const station = (WeatherMap.stations || []).find(s => s.decimal_id == decimalId); const stationInfoTitle = document.getElementById('stationInfoTitle'); if (stationInfoTitle) { if (station) { stationInfoTitle.innerHTML = ` ${station.location || '未知位置'} · 编号 ${decimalId} · 坐标 ${station.latitude ? station.latitude.toFixed(6) : '未知'}, ${station.longitude ? station.longitude.toFixed(6) : '未知'} `; } else { stationInfoTitle.innerHTML = `编号 ${decimalId}`; } } if (!WeatherMap.isMapCollapsed) WeatherMap.toggleMap(); WeatherChart.display(historyData, forecastData); WeatherTable.display(historyData, forecastData); const chartContainer = document.getElementById('chartContainer'); const tableContainer = document.getElementById('tableContainer'); if (chartContainer) chartContainer.classList.add('show'); if (tableContainer) tableContainer.classList.add('show'); setTimeout(() => { chartContainer?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 300); const legendMode = document.getElementById('legendMode'); if (legendMode) { WeatherChart.applyLegendMode(legendMode.value); } } catch (error) { console.error('查询数据失败:', error); alert('查询数据失败: ' + error.message); } } }; window.WeatherApp = WeatherApp; document.addEventListener('DOMContentLoaded', () => { WeatherApp.init(); });