[{"data":1,"prerenderedAt":143},["ShallowReactive",2],{"/2025/hexo-with-qweather":3,"surround-/2025/hexo-with-qweather":137},{"id":4,"title":5,"body":6,"categories":113,"date":115,"description":52,"draft":116,"extension":117,"image":118,"meta":119,"navigation":122,"path":123,"permalink":118,"published":118,"readingTime":124,"recommend":118,"references":118,"seo":129,"sitemap":130,"stem":131,"tags":132,"type":134,"updated":135,"__hash__":136},"content/posts/2025/hexo-with-qweather.md","在你的导航栏加入一个天气小组件",{"type":7,"value":8,"toc":105},"minimark",[9,23,27,37,40,45,56,60,68,72,80,83,86,92,95],[10,11,12],"blockquote",{},[13,14,15,16],"p",{},"灵感源于",[17,18,22],"a",{"href":19,"rel":20},"https://moonshuo.cn",[21],"nofollow","偷掉月亮",[24,25,26],"h1",{"id":26},"准备工作",[28,29,30,34],"ul",{},[31,32,33],"li",{},"和风天气账号",[31,35,36],{},"你的站点",[24,38,39],{"id":39},"开始作业",[41,42,44],"h2",{"id":43},"html直接实现","HTML直接实现",[46,47,53],"pre",{"className":48,"code":50,"language":51,"meta":52},[49],"language-html","\u003C!DOCTYPE html>\n\u003Chtml lang=\"zh-CN\">\n\u003Chead>\n    \u003Cmeta charset=\"UTF-8\">\n    \u003Cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    \u003Ctitle>简约天气小组件\u003C/title>\n    \u003Cstyle>\n        /* 天气小组件样式 */\n        .weather-widget {\n            display: flex;\n            align-items: center;\n            font-family: 'Arial', sans-serif;\n            background-color: rgba(255, 255, 255, 0.2);\n            border-radius: 15px;\n            padding: 5px 12px;\n            color: #fff;\n            backdrop-filter: blur(5px);\n            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n            transition: all 0.3s ease;\n        }\n    \n        .weather-widget:hover {\n            background-color: rgba(255, 255, 255, 0.3);\n        }\n    \n        .weather-icon {\n            width: 30px;\n            height: 30px;\n            margin-right: 8px;\n        }\n    \n        .weather-temp {\n            font-size: 16px;\n            font-weight: bold;\n            margin-right: 8px;\n        }\n    \n        .weather-desc {\n            font-size: 12px;\n            opacity: 0.9;\n        }\n    \n        /* 加载动画 */\n        @keyframes pulse {\n            0% { opacity: 0.6; }\n            50% { opacity: 1; }\n            100% { opacity: 0.6; }\n        }\n    \n        .weather-loading {\n            animation: pulse 1.5s infinite;\n        }\n    \u003C/style>\n\u003C/head>\n\u003Cbody>\n    \u003C!-- 导航栏示例 -->\n    \u003Cnav style=\"display: flex; justify-content: space-between; align-items: center; padding: 10px 20px; background-color: #333; color: white;\">\n        \u003Cdiv>网站Logo\u003C/div>\n        \u003Cdiv class=\"weather-widget\" id=\"weatherWidget\">\n            \u003Cdiv class=\"weather-loading\">加载天气...\u003C/div>\n        \u003C/div>\n    \u003C/nav>\n\n    \u003Cscript>\n        // 和风天气API配置\n        const weatherConfig = {\n            key: 'YOUR_HEFENG_API_KEY', // 替换为你的和风天气API Key\n            location: '101010100', // 默认北京的城市代码，可以根据需要修改\n            unit: 'c' // 温度单位: c-摄氏度, f-华氏度\n        };\n    \n        // 天气图标映射表 (根据和风天气的天气代码)\n        const weatherIcons = {\n            '100': '☀️', // 晴\n            '101': '🌤️', // 多云\n            '102': '⛅', // 少云\n            '103': '☁️', // 阴\n            '104': '🌫️', // 雾\n            '200': '💨', // 有风\n            '201': '🌬️', // 平静\n            '202': '🌀', // 台风\n            '203': '🌪️', // 龙卷风\n            '300': '🌧️', // 雨\n            '301': '⛈️', // 雷雨\n            '302': '🌩️', // 雷暴\n            '303': '❄️', // 雪\n            '304': '🌨️', // 雨夹雪\n            '305': '🌦️', // 阵雨\n            '306': '🌧️', // 大雨\n            '307': '🌧️', // 暴雨\n            '308': '🌊', // 大暴雨\n            '309': '☔', // 特大暴雨\n            '400': '❄️', // 小雪\n            '401': '❄️', // 中雪\n            '402': '❄️', // 大雪\n            '403': '❄️', // 暴雪\n            '404': '🌨️', // 雨夹雪\n            '405': '🌨️', // 阵雪\n            '500': '🌫️', // 薄雾\n            '501': '🌫️', // 雾\n            '502': '🌫️', // 霾\n            '503': '💨', // 扬沙\n            '504': '💨', // 浮尘\n            '507': '💨', // 沙尘暴\n            '508': '💨'  // 强沙尘暴\n        };\n    \n        // 天气描述映射表\n        const weatherDescriptions = {\n            '100': '晴',\n            '101': '多云',\n            '102': '少云',\n            '103': '阴',\n            '104': '雾',\n            '200': '有风',\n            '201': '平静',\n            '202': '台风',\n            '203': '龙卷风',\n            '300': '雨',\n            '301': '雷雨',\n            '302': '雷暴',\n            '303': '雪',\n            '304': '雨夹雪',\n            '305': '阵雨',\n            '306': '大雨',\n            '307': '暴雨',\n            '308': '大暴雨',\n            '309': '特大暴雨',\n            '400': '小雪',\n            '401': '中雪',\n            '402': '大雪',\n            '403': '暴雪',\n            '404': '雨夹雪',\n            '405': '阵雪',\n            '500': '薄雾',\n            '501': '雾',\n            '502': '霾',\n            '503': '扬沙',\n            '504': '浮尘',\n            '507': '沙尘暴',\n            '508': '强沙尘暴'\n        };\n    \n        // 获取天气数据\n        async function fetchWeather() {\n            const url = `https://devapi.qweather.com/v7/weather/now?location=${weatherConfig.location}&key=${weatherConfig.key}`;\n        \n            try {\n                const response = await fetch(url);\n                const data = await response.json();\n            \n                if (data.code === '200') {\n                    updateWeatherWidget(data.now);\n                } else {\n                    console.error('天气数据获取失败:', data);\n                    document.getElementById('weatherWidget').innerHTML = '\u003Cdiv class=\"weather-error\">天气数据获取失败\u003C/div>';\n                }\n            } catch (error) {\n                console.error('获取天气数据时出错:', error);\n                document.getElementById('weatherWidget').innerHTML = '\u003Cdiv class=\"weather-error\">天气服务不可用\u003C/div>';\n            }\n        }\n    \n        // 更新天气小组件\n        function updateWeatherWidget(weatherData) {\n            const widget = document.getElementById('weatherWidget');\n            const weatherCode = weatherData.icon;\n            const temp = weatherData.temp;\n            const icon = weatherIcons[weatherCode] || '🌍';\n            const desc = weatherDescriptions[weatherCode] || '未知';\n        \n            widget.innerHTML = `\n                \u003Cspan class=\"weather-icon\">${icon}\u003C/span>\n                \u003Cspan class=\"weather-temp\">${temp}°${weatherConfig.unit.toUpperCase()}\u003C/span>\n                \u003Cspan class=\"weather-desc\">${desc}\u003C/span>\n            `;\n        }\n    \n        // 页面加载时获取天气\n        document.addEventListener('DOMContentLoaded', fetchWeather);\n    \n        // 每小时更新一次天气\n        setInterval(fetchWeather, 3600000);\n    \u003C/script>\n\u003C/body>\n\u003C/html>\n","html","",[54,55,50],"code",{"__ignoreMap":52},[41,57,59],{"id":58},"js分离","JS分离",[46,61,66],{"className":62,"code":64,"language":65,"meta":52},[63],"language-JavaScript","// 和风天气API配置\nconst weatherConfig = {\n    key: 'YOUR_HEFENG_API_KEY', // 替换为你的和风天气API Key\n    location: '101010100', // 默认北京的城市代码\n    unit: 'c' // 温度单位: c-摄氏度, f-华氏度\n};\n\n// 天气图标映射表 (根据和风天气的天气代码)\nconst weatherIcons = {\n    '100': '☀️', // 晴\n    '101': '🌤️', // 多云\n    '102': '⛅', // 少云\n    '103': '☁️', // 阴\n    '104': '🌫️', // 雾\n    '200': '💨', // 有风\n    '201': '🌬️', // 平静\n    '202': '🌀', // 台风\n    '203': '🌪️', // 龙卷风\n    '300': '🌧️', // 雨\n    '301': '⛈️', // 雷雨\n    '302': '🌩️', // 雷暴\n    '303': '❄️', // 雪\n    '304': '🌨️', // 雨夹雪\n    '305': '🌦️', // 阵雨\n    '306': '🌧️', // 大雨\n    '307': '🌧️', // 暴雨\n    '308': '🌊', // 大暴雨\n    '309': '☔', // 特大暴雨\n    '400': '❄️', // 小雪\n    '401': '❄️', // 中雪\n    '402': '❄️', // 大雪\n    '403': '❄️', // 暴雪\n    '404': '🌨️', // 雨夹雪\n    '405': '🌨️', // 阵雪\n    '500': '🌫️', // 薄雾\n    '501': '🌫️', // 雾\n    '502': '🌫️', // 霾\n    '503': '💨', // 扬沙\n    '504': '💨', // 浮尘\n    '507': '💨', // 沙尘暴\n    '508': '💨'  // 强沙尘暴\n};\n\n// 天气描述映射表\nconst weatherDescriptions = {\n    '100': '晴',\n    '101': '多云',\n    '102': '少云',\n    '103': '阴',\n    '104': '雾',\n    '200': '有风',\n    '201': '平静',\n    '202': '台风',\n    '203': '龙卷风',\n    '300': '雨',\n    '301': '雷雨',\n    '302': '雷暴',\n    '303': '雪',\n    '304': '雨夹雪',\n    '305': '阵雨',\n    '306': '大雨',\n    '307': '暴雨',\n    '308': '大暴雨',\n    '309': '特大暴雨',\n    '400': '小雪',\n    '401': '中雪',\n    '402': '大雪',\n    '403': '暴雪',\n    '404': '雨夹雪',\n    '405': '阵雪',\n    '500': '薄雾',\n    '501': '雾',\n    '502': '霾',\n    '503': '扬沙',\n    '504': '浮尘',\n    '507': '沙尘暴',\n    '508': '强沙尘暴'\n};\n\n// 获取天气数据\nasync function fetchWeather() {\n    const url = `https://devapi.qweather.com/v7/weather/now?location=${weatherConfig.location}&key=${weatherConfig.key}`;\n  \n    try {\n        const response = await fetch(url);\n        const data = await response.json();\n    \n        if (data.code === '200') {\n            updateWeatherWidget(data.now);\n        } else {\n            console.error('天气数据获取失败:', data);\n            showWeatherError('天气数据获取失败');\n        }\n    } catch (error) {\n        console.error('获取天气数据时出错:', error);\n        showWeatherError('天气服务不可用');\n    }\n}\n\n// 更新天气小组件\nfunction updateWeatherWidget(weatherData) {\n    const widget = document.getElementById('weatherWidget');\n    const weatherCode = weatherData.icon;\n    const temp = weatherData.temp;\n    const icon = weatherIcons[weatherCode] || '🌍';\n    const desc = weatherDescriptions[weatherCode] || '未知';\n  \n    widget.innerHTML = `\n        \u003Cspan class=\"weather-icon\">${icon}\u003C/span>\n        \u003Cspan class=\"weather-temp\">${temp}°${weatherConfig.unit.toUpperCase()}\u003C/span>\n        \u003Cspan class=\"weather-desc\">${desc}\u003C/span>\n    `;\n}\n\n// 显示错误信息\nfunction showWeatherError(message) {\n    const widget = document.getElementById('weatherWidget');\n    widget.innerHTML = `\u003Cdiv class=\"weather-error\">${message}\u003C/div>`;\n}\n\n// 页面加载时获取天气\ndocument.addEventListener('DOMContentLoaded', () => {\n    fetchWeather();\n  \n    // 每小时更新一次天气\n    setInterval(fetchWeather, 3600000);\n});\n","JavaScript",[54,67,64],{"__ignoreMap":52},[41,69,71],{"id":70},"css分离","CSS分离",[46,73,78],{"className":74,"code":76,"language":77,"meta":52},[75],"language-css","/* 天气小组件样式 */\n.weather-widget {\n    display: flex;\n    align-items: center;\n    font-family: 'Arial', sans-serif;\n    background-color: rgba(255, 255, 255, 0.2);\n    border-radius: 15px;\n    padding: 5px 12px;\n    color: #fff;\n    backdrop-filter: blur(5px);\n    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);\n    transition: all 0.3s ease;\n}\n\n.weather-widget:hover {\n    background-color: rgba(255, 255, 255, 0.3);\n}\n\n.weather-icon {\n    width: 30px;\n    height: 30px;\n    margin-right: 8px;\n    font-size: 20px;\n    text-align: center;\n}\n\n.weather-temp {\n    font-size: 16px;\n    font-weight: bold;\n    margin-right: 8px;\n}\n\n.weather-desc {\n    font-size: 12px;\n    opacity: 0.9;\n}\n\n/* 加载状态样式 */\n.weather-loading {\n    animation: pulse 1.5s infinite;\n}\n\n.weather-error {\n    color: #ff6b6b;\n    font-size: 12px;\n}\n\n/* 加载动画 */\n@keyframes pulse {\n    0% { opacity: 0.6; }\n    50% { opacity: 1; }\n    100% { opacity: 0.6; }\n}\n","css",[54,79,76],{"__ignoreMap":52},[24,81,82],{"id":82},"下一步",[41,84,85],{"id":85},"自动检测城市",[46,87,90],{"className":88,"code":89,"language":65,"meta":52},[63],"// 和风天气API配置\nconst weatherConfig = {\n    key: 'YOUR_HEFENG_API_KEY', // 替换为你的和风天气API Key\n    defaultLocation: '101010100', // 默认北京的城市代码\n    unit: 'c' // 温度单位: c-摄氏度, f-华氏度\n};\n\n// 天气图标和描述映射表\nconst weatherIcons = {\n    '100': '☀️', '101': '🌤️', '102': '⛅', '103': '☁️', '104': '🌫️',\n    '200': '💨', '201': '🌬️', '202': '🌀', '203': '🌪️',\n    '300': '🌧️', '301': '⛈️', '302': '🌩️', '303': '❄️', '304': '🌨️',\n    '305': '🌦️', '306': '🌧️', '307': '🌧️', '308': '🌊', '309': '☔',\n    '400': '❄️', '401': '❄️', '402': '❄️', '403': '❄️', '404': '🌨️', '405': '🌨️',\n    '500': '🌫️', '501': '🌫️', '502': '🌫️', '503': '💨', '504': '💨',\n    '507': '💨', '508': '💨'\n};\n\nconst weatherDescriptions = {\n    '100': '晴', '101': '多云', '102': '少云', '103': '阴', '104': '雾',\n    '200': '有风', '201': '平静', '202': '台风', '203': '龙卷风',\n    '300': '雨', '301': '雷雨', '302': '雷暴', '303': '雪', '304': '雨夹雪',\n    '305': '阵雨', '306': '大雨', '307': '暴雨', '308': '大暴雨', '309': '特大暴雨',\n    '400': '小雪', '401': '中雪', '402': '大雪', '403': '暴雪', '404': '雨夹雪', '405': '阵雪',\n    '500': '薄雾', '501': '雾', '502': '霾', '503': '扬沙', '504': '浮尘',\n    '507': '沙尘暴', '508': '强沙尘暴'\n};\n\n// 获取地理位置\nfunction getLocation() {\n    return new Promise((resolve, reject) => {\n        if (!navigator.geolocation) {\n            reject(new Error('Geolocation not supported'));\n            return;\n        }\n\n        navigator.geolocation.getCurrentPosition(\n            position => resolve(position),\n            error => reject(error),\n            { enableHighAccuracy: true, timeout: 5000 }\n        );\n    });\n}\n\n// 根据经纬度获取城市信息\nasync function getCityByLocation(lat, lon) {\n    const url = `https://geoapi.qweather.com/v2/city/lookup?location=${lon},${lat}&key=${weatherConfig.key}`;\n  \n    try {\n        const response = await fetch(url);\n        const data = await response.json();\n      \n        if (data.code === '200' && data.location && data.location.length > 0) {\n            return data.location[0].id; // 返回城市ID\n        }\n        throw new Error('City not found');\n    } catch (error) {\n        console.error('获取城市信息失败:', error);\n        throw error;\n    }\n}\n\n// 获取天气数据\nasync function fetchWeather(locationId) {\n    const url = `https://devapi.qweather.com/v7/weather/now?location=${locationId}&key=${weatherConfig.key}`;\n  \n    try {\n        const response = await fetch(url);\n        const data = await response.json();\n      \n        if (data.code === '200') {\n            return data.now;\n        }\n        throw new Error(data.message || 'Weather data error');\n    } catch (error) {\n        console.error('获取天气数据时出错:', error);\n        throw error;\n    }\n}\n\n// 更新天气小组件\nfunction updateWeatherWidget(weatherData) {\n    const widget = document.getElementById('weatherWidget');\n    const weatherCode = weatherData.icon;\n    const temp = weatherData.temp;\n    const icon = weatherIcons[weatherCode] || '🌍';\n    const desc = weatherDescriptions[weatherCode] || '未知';\n  \n    widget.innerHTML = `\n        \u003Cspan class=\"weather-icon\">${icon}\u003C/span>\n        \u003Cspan class=\"weather-temp\">${temp}°${weatherConfig.unit.toUpperCase()}\u003C/span>\n        \u003Cspan class=\"weather-desc\">${desc}\u003C/span>\n    `;\n}\n\n// 使用默认城市显示天气\nasync function showDefaultWeather() {\n    try {\n        const weatherData = await fetchWeather(weatherConfig.defaultLocation);\n        updateWeatherWidget(weatherData);\n    } catch (error) {\n        console.error('使用默认城市获取天气失败:', error);\n    }\n}\n\n// 初始化天气小组件\nasync function initWeatherWidget() {\n    try {\n        // 尝试获取当前位置\n        const position = await getLocation();\n        const cityId = await getCityByLocation(position.coords.latitude, position.coords.longitude);\n        const weatherData = await fetchWeather(cityId);\n        updateWeatherWidget(weatherData);\n      \n        // 保存城市ID到本地存储\n        localStorage.setItem('lastKnownCity', cityId);\n    } catch (error) {\n        console.log('自动定位失败，使用默认城市:', error);\n      \n        // 尝试使用上次成功的城市\n        const lastKnownCity = localStorage.getItem('lastKnownCity');\n        if (lastKnownCity) {\n            try {\n                const weatherData = await fetchWeather(lastKnownCity);\n                updateWeatherWidget(weatherData);\n                return;\n            } catch (e) {\n                console.error('使用上次城市获取天气失败:', e);\n            }\n        }\n      \n        // 最后使用默认城市\n        showDefaultWeather();\n    }\n  \n    // 每小时更新一次天气\n    setInterval(async () => {\n        const lastKnownCity = localStorage.getItem('lastKnownCity') || weatherConfig.defaultLocation;\n        try {\n            const weatherData = await fetchWeather(lastKnownCity);\n            updateWeatherWidget(weatherData);\n        } catch (error) {\n            console.error('定时更新天气失败:', error);\n        }\n    }, 3600000);\n}\n\n// 页面加载时初始化天气小组件\ndocument.addEventListener('DOMContentLoaded', initWeatherWidget);\n",[54,91,89],{"__ignoreMap":52},[13,93,94],{},"OK，改导航栏，嵌入，收工",[10,96,97],{},[13,98,99,100],{},"嵌入引用偷掉月亮大佬的:",[17,101,104],{"href":102,"rel":103},"https://moonshuo.cn/posts/50269.html?highlight=%E5%A4%A9%E6%B0%94#%E6%96%87%E4%BB%B6%E9%85%8D%E7%BD%AE-1",[21],"Hexo中Buttefly主题功能增强（九）- 偷掉月亮（moonshuo.cn）",{"title":52,"searchDepth":106,"depth":106,"links":107},4,[108,110,111,112],{"id":43,"depth":109,"text":44},2,{"id":58,"depth":109,"text":59},{"id":70,"depth":109,"text":71},{"id":85,"depth":109,"text":85},[114],"前端","2025-07-17",false,"md",null,{"cover":120,"slots":121},"https://dev.qweather.com/assets/images/hp-feat-data.png",{},true,"/2025/hexo-with-qweather",{"text":125,"minutes":126,"time":127,"words":128},"11 min read",10.97,658200,2194,{"title":5,"description":52},{"loc":123},"posts/2025/hexo-with-qweather",[133],"Butterfly美化","tech","2025-08-05 09:35:26","RL3GZ1ZNntLL80f2NIk14RGVPkSA93_iMpmC5IT7TWM",[138,118],{"title":139,"path":140,"stem":141,"date":142,"type":134,"children":-1},"AList+Bitiful自建网盘","/2025/deploy-alist-and-bitiful-to-build-cloud-disk","posts/2025/deploy-alist-and-bitiful-to-build-cloud-disk","2025-07-13",1772374724944]