// 应用主控制器 const WeatherApp = { cachedHistoryData: [], cachedForecastData: [], currentPage: 1, itemsPerPage: 10, filteredDevices: [], init() { // 初始化日期 WeatherUtils.initializeDateInputs(); // 初始化地图 WeatherMap.init(window.TIANDITU_KEY || ''); WeatherMap.loadStations(); // 定时刷新在线设备数 setInterval(() => this.updateOnlineDevices(), 30000); // 绑定 UI 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'); // 由 Alpine 管理设备列表弹窗开关与分页,不再绑定以下事件 // if (showDeviceListBtn && modal) { // showDeviceListBtn.addEventListener('click', (e) => { // e.preventDefault(); // modal.style.display = 'block'; // this.updateDeviceList(1); // }); // } // if (prevPageBtn) { // prevPageBtn.addEventListener('click', () => { // if (this.currentPage > 1) this.updateDeviceList(this.currentPage - 1); // }); // } // if (nextPageBtn) { // nextPageBtn.addEventListener('click', () => { // const totalPages = Math.ceil(this.filteredDevices.length / this.itemsPerPage); // if (this.currentPage < totalPages) this.updateDeviceList(this.currentPage + 1); // }); // } // if (closeBtn && modal) { // closeBtn.addEventListener('click', () => modal.style.display = 'none'); // window.addEventListener('click', (e) => { if (e.target === modal) modal.style.display = 'none'; }); // } 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; // 关闭交给 Alpine: deviceModalOpen = false 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); }); } // 提供全局函数以兼容现有 HTML on* 绑定 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 = `