{"id":18660,"date":"2026-07-26T16:19:37","date_gmt":"2026-07-26T16:19:37","guid":{"rendered":"https:\/\/c.tunght.xyz\/?page_id=18660"},"modified":"2026-07-26T16:19:37","modified_gmt":"2026-07-26T16:19:37","slug":"weather","status":"publish","type":"page","link":"https:\/\/c.tunght.xyz\/index.php\/weather\/","title":{"rendered":"weather"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"zh-Hant\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<title>5\u65e5\u5929\u6c23\u9810\u5831<\/title>\n<style>\n* { box-sizing: border-box; }\nbody { font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; margin: 0; padding: 40px 20px; display: flex; justify-content: center; align-items: flex-start; }\n.container { background: rgba(255,255,255,0.95); border-radius: 20px; box-shadow: 0 20px 60px rgba(0,0,0,0.3); padding: 40px; max-width: 1000px; width: 100%; }\nh1 { text-align: center; color: #333; margin-bottom: 30px; font-size: 2em; }\n.search-box { display: flex; flex-direction: column; gap: 10px; margin-bottom: 30px; }\n#cityInput { width: 100%; padding: 12px 20px; font-size: 16px; border: 2px solid #ddd; border-radius: 30px; outline: none; transition: border-color 0.3s; }\n#cityInput:focus { border-color: #667eea; }\n#searchBtn { width: 100%; padding: 12px 30px; font-size: 16px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 30px; cursor: pointer; transition: transform 0.2s; }\n#searchBtn:hover { transform: scale(1.02); }\n#searchBtn:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }\n.error { background: #fee; color: #c33; padding: 15px; border-radius: 10px; margin-bottom: 20px; text-align: center; }\n.weather-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; margin-top: 20px; }\n.weather-card { background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); border-radius: 15px; padding: 18px; text-align: center; transition: transform 0.2s; }\n.weather-card:hover { transform: translateY(-5px); }\n.date { font-size: 0.8em; color: #666; margin-bottom: 8px; font-weight: 600; }\n.temp { font-size: 1.6em; font-weight: bold; color: #333; margin: 8px 0; }\n.desc { color: #555; margin-bottom: 8px; font-size: 0.9em; }\n.details { font-size: 0.75em; color: #777; line-height: 1.5; }\n.icon { font-size: 2.5em; margin: 8px 0; }\n.note { text-align: center; color: #888; font-size: 0.9em; margin-top: 20px; font-style: italic; }\n.loading { text-align: center; padding: 40px; color: #666; }\n@media (max-width: 768px) {\n  .weather-grid { grid-template-columns: repeat(2, 1fr); }\n}\n<\/style>\n<\/head>\n<body>\n<div class=\"container\">\n  <h1>\ud83c\udf24\ufe0f 5\u65e5\u5929\u6c23\u9810\u5831<\/h1>\n  <div class=\"search-box\">\n    <input type=\"text\" id=\"cityInput\" value=\"\u9999\u6e2f\" placeholder=\"\u8f38\u5165\u57ce\u5e02\u540d\u7a31\uff08\u4f8b\u5982\uff1aHong Kong\u3001London\u3001Tokyo\uff09\" \/>\n    <button id=\"searchBtn\" onclick=\"getWeather()\">\u67e5\u8a62<\/button>\n  <\/div>\n  <div id=\"result\"><\/div>\n<\/div>\n\n<script>\nconst WMO_ICONS = {\n  0: '\u2600\ufe0f', 1: '\ud83c\udf24\ufe0f', 2: '\u26c5', 3: '\u2601\ufe0f',\n  45: '\ud83c\udf2b\ufe0f', 48: '\ud83c\udf2b\ufe0f',\n  51: '\ud83c\udf26\ufe0f', 53: '\ud83c\udf26\ufe0f', 55: '\ud83c\udf27\ufe0f',\n  61: '\ud83c\udf27\ufe0f', 63: '\ud83c\udf27\ufe0f', 65: '\ud83c\udf27\ufe0f',\n  71: '\u2744\ufe0f', 73: '\u2744\ufe0f', 75: '\u2744\ufe0f',\n  80: '\ud83c\udf26\ufe0f', 81: '\ud83c\udf27\ufe0f', 82: '\ud83c\udf27\ufe0f',\n  95: '\u26c8\ufe0f', 96: '\u26c8\ufe0f', 99: '\u26c8\ufe0f',\n};\n\nfunction getWeatherIcon(code) { return WMO_ICONS[code] || '\ud83c\udf21\ufe0f'; }\n\nfunction getWeatherDesc(code) {\n  const map = {\n    0: '\u6674\u6717', 1: '\u5927\u81f4\u6674\u6717', 2: '\u591a\u96f2', 3: '\u9670\u5929',\n    45: '\u9727', 48: '\u9727\u6dde',\n    51: '\u5c0f\u6bdb\u6bdb\u96e8', 53: '\u6bdb\u6bdb\u96e8', 55: '\u5927\u6bdb\u6bdb\u96e8',\n    61: '\u5c0f\u96e8', 63: '\u4e2d\u96e8', 65: '\u5927\u96e8',\n    71: '\u5c0f\u96ea', 73: '\u4e2d\u96ea', 75: '\u5927\u96ea',\n    80: '\u5c0f\u9663\u96e8', 81: '\u9663\u96e8', 82: '\u5927\u9663\u96e8',\n    95: '\u96f7\u66b4', 96: '\u96f7\u66b4\u4f34\u5c0f\u51b0\u96f9', 99: '\u96f7\u66b4\u4f34\u5927\u51b0\u96f9',\n  };\n  return map[code] || '\u672a\u77e5';\n}\n\nasync function getWeather() {\n  const city = document.getElementById('cityInput').value.trim();\n  const result = document.getElementById('result');\n  const btn = document.getElementById('searchBtn');\n\n  if (!city) {\n    result.innerHTML = '<div class=\"error\">\u8acb\u8f38\u5165\u57ce\u5e02\u540d\u7a31<\/div>';\n    return;\n  }\n\n  btn.disabled = true;\n  result.innerHTML = '<div class=\"loading\">\u8f09\u5165\u4e2d...<\/div>';\n\n  try {\n    const geoRes = await fetch(`https:\/\/geocoding-api.open-meteo.com\/v1\/search?name=${encodeURIComponent(city)}&count=1&language=zh&format=json`);\n    if (!geoRes.ok) throw new Error('\u5730\u7406\u7f16\u7801\u670d\u52a1\u6682\u65f6\u4e0d\u53ef\u7528');\n    const geoData = await geoRes.json();\n    if (!geoData.results || geoData.results.length === 0) {\n      throw new Error('\u627e\u4e0d\u5230\u8be5\u57ce\u5e02\uff0c\u8bf7\u68c0\u67e5\u540d\u79f0');\n    }\n\n    const { latitude, longitude, name, country } = geoData.results[0];\n\n    const weatherRes = await fetch(`https:\/\/api.open-meteo.com\/v1\/forecast?latitude=${latitude}&longitude=${longitude}&daily=weathercode,temperature_2m_max,temperature_2m_min,precipitation_sum,windspeed_10m_max&timezone=auto&forecast_days=5`);\n    if (!weatherRes.ok) throw new Error('\u5929\u6c14\u6570\u636e\u83b7\u53d6\u5931\u8d25');\n    const weatherData = await weatherRes.json();\n\n    if (!weatherData.daily || !weatherData.daily.time || weatherData.daily.time.length === 0) {\n      throw new Error('\u672a\u80fd\u53d6\u5f97\u5929\u6c23\u8cc7\u6599');\n    }\n\n    const daily = weatherData.daily;\n    const daysCount = Math.min(daily.time.length, 5);\n\n    let html = '<div class=\"weather-grid\">';\n\n    for (let i = 0; i < daysCount; i++) {\n      const dateStr = i === 0\n        ? '\u4eca\u5929'\n        : new Date(Date.now() + i * 86400000).toLocaleDateString('zh-HK', { weekday: 'short', month: 'short', day: 'numeric' });\n      \n      const maxTemp = daily.temperature_2m_max[i];\n      const minTemp = daily.temperature_2m_min[i];\n      const precip = daily.precipitation_sum[i];\n      const wind = daily.windspeed_10m_max[i];\n      const code = daily.weathercode[i];\n      const icon = getWeatherIcon(code);\n      const desc = getWeatherDesc(code);\n\n      html += `\n        <div class=\"weather-card\">\n          <div class=\"date\">${dateStr}<\/div>\n          <div class=\"icon\">${icon}<\/div>\n          <div class=\"temp\">${maxTemp}\u00b0 \/ ${minTemp}\u00b0<\/div>\n          <div class=\"desc\">${desc}<\/div>\n          <div class=\"details\">\n            \ud83d\udca7 \u964d\u96e8: ${precip} mm<br>\n            \ud83d\udca8 \u98ce\u901f: ${wind} km\/h\n          <\/div>\n        <\/div>\n      `;\n    }\n\n    html += '<\/div>';\n    html += `<div class=\"note\">\ud83d\udccd ${name}\uff0c${country} \uff5c5\u65e5\u9810\u5831 \uff5c\u8cc7\u6599\u4f86\u6e90\uff1aOpen-Meteo<\/div>`;\n    result.innerHTML = html;\n\n  } catch (error) {\n    result.innerHTML = `<div class=\"error\">\u274c ${error.message}<\/div>`;\n  } finally {\n    btn.disabled = false;\n  }\n}\n\ndocument.getElementById('cityInput').addEventListener('keypress', function(e) {\n  if (e.key === 'Enter') getWeather();\n});\n\n\/\/ \u9801\u9762\u8f09\u5165\u6642\u81ea\u52d5\u67e5\u8a62\u9810\u8a2d\u57ce\u5e02\uff08\u9999\u6e2f\uff09\u7684\u5929\u6c23\nwindow.onload = function() {\n  getWeather();\n};\n<\/script>\n<\/body>\n<\/html>\n\n","protected":false},"excerpt":{"rendered":"<p>5\u65e5\u5929\u6c23\u9810\u5831 \ud83c\udf24\ufe0f 5\u65e5\u5929\u6c23\u9810\u5831 \u67e5\u8a62<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-18660","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/pages\/18660","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/comments?post=18660"}],"version-history":[{"count":1,"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/pages\/18660\/revisions"}],"predecessor-version":[{"id":18661,"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/pages\/18660\/revisions\/18661"}],"wp:attachment":[{"href":"https:\/\/c.tunght.xyz\/index.php\/wp-json\/wp\/v2\/media?parent=18660"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}