### Run Project with Node.js Source: https://github.com/jermen592/hk-dashboard/blob/master/README.md Use the serve package to host the project locally. ```bash npx serve . ``` -------------------------------- ### Fetch Parking Vacancy and Information Source: https://context7.com/jermen592/hk-dashboard/llms.txt Integrates parking vacancy and static information APIs. Use window.Parking.refresh() to load data and window.Parking.applyFilter() to apply UI filters. ```javascript // data.gov.hk 停車場 API const API_VACANCY = 'https://api.data.gov.hk/v1/carpark-info-vacancy?data=vacancy&lang=zh_TW'; const API_INFO = 'https://api.data.gov.hk/v1/carpark-info-vacancy?data=info&lang=zh_TW'; // 同時獲取空位及停車場資料 const [vacRes, infoRes] = await Promise.all([ fetch(API_VACANCY), fetch(API_INFO) ]); const vacData = await vacRes.json(); const infoData = await infoRes.json(); // 空位數據結構 // { // results: [{ // park_Id: 'tdc-cwb-cps-00001', // privateCar: [{ vacancy: 45, lastupdate: '2025-04-04T17:30:00' }], // motorCycle: [{ vacancy: 10 }], // LGV: [{ vacancy: 5 }] // }] // } // 停車場資料結構 // { // results: [{ // park_Id: 'tdc-cwb-cps-00001', // name: '銅鑼灣中心停車場', // district: 'WC', // 地區代碼 // latitude: '22.2775', // longitude: '114.1836', // displayAddress: '銅鑼灣道XX號' // }] // } // 空位顏色標示 function vacancyTag(vac) { if (vac === null) return ''; if (vac === 0) return '滿'; if (vac <= 10) return '' + vac + ''; if (vac <= 50) return '' + vac + ''; return '' + vac + ''; } // 使用方式 window.Parking.refresh(); // 載入全部停車場 window.Parking.applyFilter(); // 應用篩選條件 ``` -------------------------------- ### Git Contribution Workflow Source: https://github.com/jermen592/hk-dashboard/blob/master/README.md Standard commands for contributing to the repository. ```bash # Fork 這個 repo # 建立你的 feature branch git checkout -b feature/amazing-feature # Commit 你的改動 git commit -m 'Add some amazing feature' # Push 到 branch git push origin feature/amazing-feature # 開一個 Pull Request ``` -------------------------------- ### Project Directory Structure Source: https://github.com/jermen592/hk-dashboard/blob/master/README.md Overview of the file organization for the dashboard application. ```text hk-dashboard/ ├── index.html # 主頁面(15個分頁) ├── manifest.json # PWA 設定 ├── sw.js # Service Worker(離線緩存) ├── css/ │ ├── tokens.css # CSS 設計 tokens(顏色/字體/間距) │ └── base.css # 基礎樣式 + 響應式 └── js/ ├── core.js # 主題切換、時鐘、農曆、導航 ├── weather.js # 天氣模組(HKO) ├── transport.js # 交通模組(MTR/LRT) ├── bus.js # 巴士 ETA(KMB/CTB/GMB) ├── tides.js # 潮汐 + 地震 + 天氣展望 ├── health.js # 急症室等候時間 ├── environment.js # AQHI 空氣質素 ├── parking.js # 停車場空位 ├── cctv.js # 道路快拍 ├── ferry.js # NLB 嶼巴路線 ├── holidays.js # 公眾假期 + 節氣 ├── climate.js # 氣候數據 ├── beach.js # 泳灘水質 ├── map.js # 互動地圖(Leaflet.js) ├── finance.js # 恒指 + 匯率 ├── waste.js # 回收資訊 └── app.js # 主入口(初始化 + 自動刷新) ``` -------------------------------- ### 初始化互動地圖 (Leaflet.js) Source: https://context7.com/jermen592/hk-dashboard/llms.txt MapView 模組封裝了地圖初始化與圖層載入邏輯,支援根據主題切換底圖並透過 fetch 載入停車場數據。 ```javascript // 初始化地圖 (使用 Leaflet.js) const MapView = (function() { let _map = null; function createMap(container) { // 使用 CartoDB 深色/淺色地圖底圖 const isDark = document.documentElement.getAttribute('data-theme') === 'dark'; const darkTile = 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png'; const lightTile = 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png'; _map = L.map(container, { center: [22.3193, 114.1694], // 香港中心 zoom: 11 }); L.tileLayer(isDark ? darkTile : lightTile, { attribution: '© OSM © CARTO', maxZoom: 18 }).addTo(_map); } // 停車場圖層 async function loadParkingLayer() { const [vacRes, infoRes] = await Promise.all([ fetch('https://api.data.gov.hk/v1/carpark-info-vacancy?data=vacancy&lang=zh_TW'), fetch('https://api.data.gov.hk/v1/carpark-info-vacancy?data=info&lang=zh_TW') ]); // 建立 markers const markers = []; vacData.results.forEach(vac => { const info = infoMap[vac.park_Id]; const marker = L.circleMarker([info.latitude, info.longitude], { radius: 8, fillColor: getVacancyColor(vac.privateCar?.[0]?.vacancy), fillOpacity: 0.85 }); marker.bindPopup(`${info.name}
空位: ${vac.privateCar?.[0]?.vacancy || '—'}`); markers.push(marker); }); L.layerGroup(markers).addTo(_map); } return { refresh, switchLayer }; })(); // 使用方式 window.MapView.refresh(); // 初始化/刷新地圖 window.MapView.switchLayer('parking'); // 切換至停車場圖層 window.MapView.switchLayer('aqhi'); // 切換至 AQHI 圖層 window.MapView.switchLayer('beach'); // 切換至泳灘圖層 window.MapView.switchLayer('aed'); // 切換至 AED 圖層 ``` -------------------------------- ### Fetch Tide and Earthquake Data Source: https://context7.com/jermen592/hk-dashboard/llms.txt Retrieves meteorological data from the Hong Kong Observatory. Supports station switching and earthquake monitoring. ```javascript // 潮汐數據 (香港天文台) const now = new Date(); const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); // 獲取屯門測潮站數據 const tideUrl = `https://data.weather.gov.hk/weatherAPI/opendata/opendata.php?dataType=HHOT&station=TMW&year=${year}&month=${month}&rformat=json`; const tideRes = await fetch(tideUrl); const tideData = await tideRes.json(); // 返回數據結構 // { // fields: ['MM', 'DD', '01', '02', ..., '24'], // 月、日、1-24時 // data: [ // ['04', '01', '1.06', '0.74', '0.58', ...], // 4月1日各小時潮汐高度(米) // ['04', '02', '1.12', '0.81', '0.62', ...] // ] // } // 地震數據 const eqUrl = 'https://data.weather.gov.hk/weatherAPI/opendata/earthquake.php?dataType=qem&lang=tc'; const eqRes = await fetch(eqUrl); const eqData = await eqRes.json(); // 返回數據結構 // { // latitude: '22.15', // longitude: '114.20', // mag: '3.2', // 黎克特制震級 // depth: '10', // 深度(公里) // region: '香港東南面約50公里', // ptime: '2025-04-04 15:23' // } // 香港有感地震 const feltUrl = 'https://data.weather.gov.hk/weatherAPI/opendata/earthquake.php?dataType=feltearthquake&lang=tc'; // 使用方式 window.Tides.refresh(); // 刷新所有數據 window.Tides.changeStation(); // 切換測潮站 (讀取 #tide-station 值) ``` -------------------------------- ### 獲取巴士與小巴到站時間 Source: https://context7.com/jermen592/hk-dashboard/llms.txt 整合九巴、城巴及專線小巴 API,提供路線詳情、站點資訊及實時到站時間查詢。 ```javascript // KMB 九巴 API const KMB_BASE = 'https://data.etabus.gov.hk/v1/transport/kmb'; // 1. 獲取路線資料 const routeRes = await fetch(`${KMB_BASE}/route/60X/outbound/1`); const routeData = await routeRes.json(); // { data: { route: '60X', orig_tc: '屯門市中心', dest_tc: '旺角東站' } } // 2. 獲取路線站點列表 const stopsRes = await fetch(`${KMB_BASE}/route-stop/60X/outbound/1`); const stops = await stopsRes.json(); // { data: [{ route: '60X', stop: 'B3B0EF2BC688751D', seq: 1 }] } // 3. 獲取站點名稱 const stopRes = await fetch(`${KMB_BASE}/stop/B3B0EF2BC688751D`); const stopInfo = await stopRes.json(); // { data: { name_tc: '屯門市中心總站', lat: '22.3908', long: '114.0068' } } // 4. 獲取到站時間 const etaRes = await fetch(`${KMB_BASE}/eta/B3B0EF2BC688751D/60X/1`); const eta = await etaRes.json(); // { // data: [ // { eta: '2025-04-04T17:35:00+08:00', dest_tc: '旺角東站', rmk_tc: '' }, // { eta: '2025-04-04T17:50:00+08:00', dest_tc: '旺角東站', rmk_tc: '' } // ] // } // CTB 城巴 API const CTB_BASE = 'https://rt.data.gov.hk/v2/transport/citybus'; const ctbEta = await fetch(`${CTB_BASE}/eta/CTB/001939/962X`); const ctbData = await ctbEta.json(); // { data: [{ eta: '...', dest_tc: '銅鑼灣', rmk_tc: '' }] } // GMB 專線小巴 API const GMB_BASE = 'https://data.etagmb.gov.hk'; // 獲取新界區路線列表 const gmbRoutes = await fetch(`${GMB_BASE}/route/NT`); // 獲取路線詳情 const gmbRoute = await fetch(`${GMB_BASE}/route/NT/403`); // 獲取到站時間 const gmbEta = await fetch(`${GMB_BASE}/eta/route-stop/403/1`); // 使用方式 window.Bus.refresh(); // 刷新預設常用站點 window.BusSearch.search(); // 搜尋路線 (讀取 #bus-search-input 值) window.Bus_GMB.loadRoutes(); // 載入小巴路線 ``` -------------------------------- ### 自動刷新機制與離線偵測 Source: https://context7.com/jermen592/hk-dashboard/llms.txt 利用 setInterval 定時觸發模組刷新,並監聽瀏覽器在線狀態以自動恢復數據同步。 ```javascript // 初始化載入所有數據 async function loadAllData() { await Promise.allSettled([ Weather.refresh(), Transport.refresh(), Health.refresh(), Environment.refresh(), Finance.refresh() // 恒生指數 + 匯率 ]); } // 自動刷新間隔 function startAutoRefresh() { // 天氣、醫療、環境 — 每 60 秒 setInterval(() => { Weather.refresh(); Health.refresh(); Environment.refresh(); }, 60000); // 交通 — 每 10 秒 setInterval(() => Transport.refresh(), 10000); // 巴士預設站點 — 每 45 秒 setInterval(() => Bus.refresh(), 45000); // 停車場 — 每 5 分鐘 (僅在停車場頁面) setInterval(() => { if (window._currentPage === 'parking') { Parking.refresh(); } }, 300000); } // 離線/在線偵測 window.addEventListener('offline', () => { document.getElementById('offline-banner').style.display = 'block'; }); window.addEventListener('online', () => { document.getElementById('offline-banner').style.display = 'none'; loadAllData(); // 重新載入數據 }); ``` -------------------------------- ### 獲取香港天文台天氣數據 Source: https://context7.com/jermen592/hk-dashboard/llms.txt 使用香港天文台 API 獲取實時天氣、九天天氣預報及警告摘要。數據以 JSON 格式返回,包含溫度、濕度、紫外線指數及預報資訊。 ```javascript // 獲取當前天氣數據 const WX_BASE = 'https://data.weather.gov.hk/weatherAPI/opendata/weather.php'; // 實時天氣 (rhrread) const response = await fetch(`${WX_BASE}?dataType=rhrread&lang=tc`); const data = await response.json(); // 返回數據結構 // { // temperature: { data: [{ place: '香港天文台', value: 28, unit: 'C' }] }, // humidity: { data: [{ value: 75 }] }, // icon: [51], // 天氣圖標代碼 // uvindex: { data: [{ value: 6, desc: '高' }] }, // rainfall: { data: [{ place: '屯門', max: 0.5 }] }, // warningMessage: ['黃色暴雨警告現正生效'] // } // 九天天氣預報 (fnd) const forecastRes = await fetch(`${WX_BASE}?dataType=fnd&lang=tc`); const forecast = await forecastRes.json(); // 返回數據結構 // { // weatherForecast: [{ // forecastDate: '20250404', // week: '星期五', // forecastMaxtemp: { value: 29 }, // forecastMintemp: { value: 24 }, // ForecastIcon: 53, // PSR: '中高' // 降雨概率 // }], // seaTemp: { value: 23 }, // generalSituation: '一道低壓槽會在今明兩日為華南沿岸帶來驟雨...' // } // 天氣警告摘要 (warnsum) const warnRes = await fetch(`${WX_BASE}?dataType=warnsum&lang=tc`); const warnings = await warnRes.json(); // 返回: { WRAIN: { name: '暴雨警告', code: 'WAMB' }, WTCSGNL: { code: 'T8' } } // 使用方式 window.Weather.refresh(); // 刷新所有天氣數據 ``` -------------------------------- ### 查詢港鐵及輕鐵班次 Source: https://context7.com/jermen592/hk-dashboard/llms.txt 通過港鐵 API 獲取指定路線與車站的實時班次資訊。輕鐵查詢需使用 station_id 參數。 ```javascript // MTR 港鐵班次 API const MTR_API = 'https://rt.data.gov.hk/v1/transport/mtr/getSchedule.php'; // 查詢屯馬線屯門站班次 const response = await fetch(`${MTR_API}?line=TML&sta=TUM`); const data = await response.json(); // 返回數據結構 // { // status: 1, // 1=正常, 0=服務受阻 // data: { // 'TML-TUM': { // UP: [ // 上行列車 // { dest: 'WKS', ttnt: '3', plat: '1' }, // 往烏溪沙, 3分鐘後 // { dest: 'WKS', ttnt: '10', plat: '1' } // ], // DOWN: [] // 下行(屯門為總站無下行) // } // } // } // 輕鐵班次 API const LRT_API = 'https://rt.data.gov.hk/v1/transport/mtr/lrt/getSchedule'; // 查詢屯門碼頭站 (站號 001) const lrtRes = await fetch(`${LRT_API}?station_id=001`); const lrtData = await lrtRes.json(); // 返回數據結構 // { // platform_list: [{ // platform_id: '1', // route_list: [ // { route_no: '507', dest_ch: '田景', time_ch: '3 分鐘' }, // { route_no: '610', dest_ch: '元朗', time_ch: '即將抵達' } // ] // }] // } // 使用方式 window.Transport.refresh(); // 刷新港鐵及輕鐵數據 window.fetchMTRCustom(); // 根據選擇的路線/車站查詢 window.fetchLRTCustom(); // 根據選擇的輕鐵站查詢 ``` -------------------------------- ### 頁面導航與主題切換 Source: https://context7.com/jermen592/hk-dashboard/llms.txt 透過 DOM 操作管理頁面顯示狀態,並支援透過 URL hash 進行深淺色主題切換。 ```javascript // 頁面導航 function showPage(name) { // 隱藏所有頁面 document.querySelectorAll('.page').forEach(p => p.classList.remove('active')); // 顯示目標頁面 document.getElementById(`page-${name}`).classList.add('active'); // 更新導航高亮 document.querySelectorAll('.nav-tab').forEach(t => t.classList.remove('active')); document.querySelector(`.nav-tab[data-page="${name}"]`).classList.add('active'); // 追蹤當前頁面 window._currentPage = name; } // 可用頁面: home, weather, transport, bus, tides, health, environment, // parking, beach, map, ferry, holidays, climate, cctv, waste // 主題切換 (支援 URL hash: #dark / #light) document.querySelector('[data-theme-toggle]').addEventListener('click', function() { const current = document.documentElement.getAttribute('data-theme'); const next = current === 'dark' ? 'light' : 'dark'; document.documentElement.setAttribute('data-theme', next); history.replaceState(null, '', '#' + next); }); // 農曆日期 API async function loadLunarDate() { const now = new Date(); const url = `https://data.weather.gov.hk/weatherAPI/opendata/lunardate.php?date=${now.toISOString().slice(0,10).replace(/-/g,'')}`; const data = await fetch(url).then(r => r.json()); // { LunarYear: '乙巳年', LunarMonth: '三月', LunarDate: '初七' } } // 使用方式 window.showPage('weather'); // 切換至天氣頁面 ``` -------------------------------- ### Fetch Environmental Protection Department AQHI Forecast Source: https://context7.com/jermen592/hk-dashboard/llms.txt Retrieves air quality health index forecasts. The riskClass function maps risk strings to CSS classes. ```javascript // 環保署 AQHI 預報 const AQHI_URL = 'https://datagovhk.blob.core.windows.net/dataset/aqhi/aqhi-forecast.json'; const response = await fetch(AQHI_URL); const data = await response.json(); // 返回數據結構 (陣列) // [ // { // type: 'general', // 一般監測站 // date: '2025-04-04', // time: 'AM', // health_risk_min: 'Low', // health_risk_max: 'Moderate', // publish_date: '2025-04-04' // }, // { // type: 'roadside', // 路邊監測站 // date: '2025-04-04', // time: 'PM', // health_risk_min: 'Moderate', // health_risk_max: 'High' // } // ] // AQHI 等級顏色 function riskClass(str) { const n = riskToNum(str); // Low=1, Moderate=5, High=7, Very High=8 if (n <= 3) return 'tag-green'; // 低 if (n <= 6) return 'tag-yellow'; // 中 return 'tag-red'; // 高/甚高/嚴重 } // 使用方式 window.Environment.refresh(); ``` -------------------------------- ### Register Service Worker for PWA Source: https://github.com/jermen592/hk-dashboard/blob/master/index.html Registers a service worker for Progressive Web App (PWA) functionality. This code should be placed in your main JavaScript file or an entry point that runs on page load. ```javascript // Register Service Worker (PWA) if ('serviceWorker' in navigator) { window.addEventListener('load', () => { navigator.serviceWorker.register('/sw.js').then(reg => { console.log('Saving Service Worker registered:', reg.scope); }).catch(err => { console.log('Saving SW registration failed:', err); }); }); } ``` -------------------------------- ### Fetch Hospital Authority AED Wait Times Source: https://context7.com/jermen592/hk-dashboard/llms.txt Retrieves real-time emergency department wait times. Use window.Health.refresh() to update the data. ```javascript // 醫院管理局急症室等候時間 const AED_URL = 'https://www.ha.org.hk/opendata/aed/aedwtdata2-tc.json'; const response = await fetch(AED_URL); const data = await response.json(); // 返回數據結構 // { // updateTime: '2025-04-04T17:30:00', // waitTime: [ // { // hospName: '屯門醫院', // t3p50: '1 小時', // T3 甲類急症等候中位數 // t45p50: '3 小時', // T4/T5 乙丙類急症等候中位數 // t2wt: '30 分鐘' // T2 危急等候時間 // }, // { hospName: '瑪嘉烈醫院', t3p50: '45 分鐘', t45p50: '2 小時' } // ] // } // 醫院地區映射 const HOSP_REGION = { '屯門醫院': '新界', '廣華醫院': '九龍', '瑪麗醫院': '港島' }; // 使用方式 window.Health.refresh(); // 刷新急症室數據 ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.