Files
blog-source/usr/themes/HarmonyHues/components/widgets/widget-weather.php
2026-03-04 00:23:03 +08:00

112 lines
4.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* 天气小部件
*
* @author 星语社长
* @link https://biibii.cn
* @update 2026-03-03
*/
if ( ! defined('__TYPECHO_ROOT_DIR__')) {
exit;
}
// 只有在侧边栏开启且不是文章页面时显示
if ( ! empty($this->options->sidebarBlock) && in_array('ShowSidebarWeather', $this->options->sidebarBlock) && ! $this->is('post')): ?>
<?php
// 获取配置信息
$city = trim($this->options->weatherCity ?: 'Beijing');
$apiKey = trim($this->options->weatherApiKey ?: '');
$cacheFile = dirname(__DIR__, 2) . '/assets/weather_cache.json';
// 缓存机制:记录城市和时间,过期 1 小时,城市变更时自动失效
function hh_fetch_weather($city, $apiKey, $cacheFile) {
if (file_exists($cacheFile)) {
$raw = @file_get_contents($cacheFile);
$cached = $raw ? json_decode($raw, true) : null;
// 缓存结构:{"city":"xxx","timestamp":12345678,"data":{…}}
if ($cached && isset($cached['city'], $cached['timestamp'], $cached['data'])) {
if ($cached['city'] === $city && time() - $cached['timestamp'] < 3600) {
return $cached['data'];
}
}
}
if (empty($apiKey) || empty($city)) {
return null;
}
$url = 'https://api.openweathermap.org/data/2.5/weather?q=' . urlencode($city)
. '&appid=' . $apiKey . '&units=metric&lang=zh_cn';
$json = @file_get_contents($url);
if ($json) {
$payload = json_encode([
'city' => $city,
'timestamp' => time(),
'data' => json_decode($json, true),
]);
@file_put_contents($cacheFile, $payload);
return json_decode($json, true);
}
return null;
}
$weather = hh_fetch_weather($city, $apiKey, $cacheFile);
// 用于调试:在 HTML 注释中输出参数和值,方便查看
$reqUrl = 'https://api.openweathermap.org/data/2.5/weather?q=' . urlencode($city)
. '&appid=' . $apiKey . '&units=metric&lang=zh_cn';
?>
<!-- weather widget debug: city=<?php echo htmlspecialchars($city, ENT_QUOTES); ?>, key_len=<?php echo strlen($apiKey); ?>, url=<?php echo htmlspecialchars($reqUrl, ENT_QUOTES); ?>, allow_url_fopen=<?php echo ini_get('allow_url_fopen') ? 'on' : 'off'; ?>, last_err=<?php $e = error_get_last(); echo $e ? htmlspecialchars($e['message'], ENT_QUOTES) : 'none'; ?> -->
<div class="hh-widget mt-3 weather-widget" style="font-size:0.9rem;line-height:1.4;">
<?php if ($weather && isset($weather['weather'][0])): ?>
<?php
// 语言友好的城市显示(中英文互译)
function hh_display_city($inputCity, $weather) {
static $map = [
'Beijing' => '北京',
'Guangzhou' => '广州',
'Shenzhen' => '深圳',
'Shanghai' => '上海',
'Chengdu' => '成都',
// 可根据需要继续添加
];
if (isset($map[$inputCity])) {
return $map[$inputCity];
}
if (isset($map[$weather['name']])) {
return $map[$weather['name']];
}
return $weather['name'];
}
$displayCity = hh_display_city($city, $weather);
$w = $weather['weather'][0];
$m = $weather['main'];
$wind = $weather['wind'] ?? [];
$iconUrl = 'https://openweathermap.org/img/wn/' . $w['icon'] . '@2x.png';
?>
<div class="weather-header" style="display:flex;align-items:center;justify-content:center;">
<img src="<?php echo $iconUrl; ?>"
alt="<?php echo htmlspecialchars($w['description'], ENT_QUOTES); ?>"
style="width:48px;height:48px;margin-right:8px;">
<div style="text-align:left;">
<p style="margin:0;font-weight:bold;line-height:1;"><?php echo $displayCity; ?></p>
<p style="margin:0;line-height:1;"><?php echo $w['description']; ?> <?php echo $m['temp']; ?>°C</p>
</div>
</div>
<div class="weather-details" style="font-size:0.85rem;color:#555;text-align:center;margin-top:4px;">
<p style="margin:0;">体感:<?php echo $m['feels_like']; ?>°C湿度<?php echo $m['humidity']; ?>%;气压:<?php echo $m['pressure']; ?> hPa</p>
<?php if (!empty($wind)): ?>
<p style="margin:0;">风速:<?php echo $wind['speed']; ?> m/s<?php
if (isset($wind['deg'])) echo ',方向:' . $wind['deg'] . '°'; ?></p>
<?php endif; ?>
</div>
<?php elseif ($weather && isset($weather['cod']) && $weather['cod'] != 200): ?>
<p>天气接口错误:<?php echo htmlspecialchars($weather['message'] ?? '未知', ENT_QUOTES); ?></p>
<?php else: ?>
<p>天气获取失败</p>
<?php endif; ?>
</div>
<?php endif; ?>