天气缓存机制

Maziang 3 months ago
parent c1d1ebdec6
commit c23347f7f9

@ -29,6 +29,7 @@ from services.network_service import NetworkService
from file_manager.file_operations import FileManager
from learning_mode_window import LearningModeWindow
from ui.theme_manager import ThemeManager
from ui.ai_chat_panel import AIChatPanel
class MarkTextEditor(QPlainTextEdit):
@ -446,8 +447,13 @@ class MarkTextMainWindow(QMainWindow):
editor_container.setLayout(editor_layout)
splitter.addWidget(editor_container)
# AI对话面板
self.ai_chat_panel = AIChatPanel(self)
self.ai_chat_panel.setMinimumWidth(320)
splitter.addWidget(self.ai_chat_panel)
# 设置分割器比例
splitter.setSizes([250, 950])
splitter.setSizes([250, 700, 300])
main_layout.addWidget(splitter)
central_widget.setLayout(main_layout)
@ -1148,7 +1154,7 @@ class MarkTextMainWindow(QMainWindow):
QMessageBox.warning(self, "提示", "请先打开一个文档")
def show_weather_info(self):
"""显示天气信息 - 优化错误处理"""
"""显示天气信息 - 包含生活提示的详细信息"""
if not self.network_service:
QMessageBox.warning(self, "提示", "网络服务正在初始化中,请稍后再试")
return
@ -1156,8 +1162,21 @@ class MarkTextMainWindow(QMainWindow):
try:
weather_info = self.network_service.get_weather_info()
if weather_info:
# 基础天气信息
weather_text = f"{weather_info['city']}: {weather_info['temperature']}°C, {weather_info['description']}"
QMessageBox.information(self, "天气信息", weather_text)
# 添加详细信息
weather_text += f"\n湿度: {weather_info['humidity']}%"
weather_text += f"\n风速: {weather_info['wind_speed']}m/s"
# 添加生活提示
lifetips = weather_info.get('lifetips', [])
if lifetips:
weather_text += "\n\n🌟 生活提示:"
for tip in lifetips:
weather_text += f"\n{tip}"
QMessageBox.information(self, "天气详细信息", weather_text)
else:
QMessageBox.warning(self, "提示", "无法获取天气信息")
except Exception as e:
@ -1179,7 +1198,7 @@ class MarkTextMainWindow(QMainWindow):
QMessageBox.critical(self, "错误", f"获取名言信息失败: {str(e)}")
def insert_weather_to_editor(self):
"""将天气信息插入到编辑器 - 优化错误处理"""
"""将天气信息插入到编辑器 - 包含生活提示的详细信息"""
if not self.network_service:
QMessageBox.warning(self, "提示", "网络服务正在初始化中,请稍后再试")
return
@ -1189,7 +1208,17 @@ class MarkTextMainWindow(QMainWindow):
try:
weather_info = self.network_service.get_weather_info()
if weather_info:
weather_text = f"\n\n🌤 今日天气: {weather_info['city']} {weather_info['temperature']}°C, {weather_info['description']}\n\n"
weather_text = f"\n\n🌤 今日天气: {weather_info['city']} {weather_info['temperature']}°C, {weather_info['description']}\n"
weather_text += f"湿度: {weather_info['humidity']}% | 风速: {weather_info['wind_speed']}m/s\n\n"
# 添加生活提示
lifetips = weather_info.get('lifetips', [])
if lifetips:
weather_text += "🌟 生活提示:\n"
for tip in lifetips:
weather_text += f"{tip}\n"
weather_text += "\n"
cursor = editor.textCursor()
cursor.insertText(weather_text)
else:

@ -2,6 +2,7 @@
import requests
import json
import os
import time
from typing import Optional, Dict, Any
class NetworkService:
@ -11,6 +12,36 @@ class NetworkService:
self.api_key = None
self.cache = {}
self.session = requests.Session()
# 天气缓存相关属性
self._cached_weather_data = None # 缓存的天气数据
self._cached_location = None # 缓存的定位信息
self._weather_cache_timestamp = None # 缓存时间戳
def get_cached_weather_data(self):
"""获取缓存的天气数据"""
return self._cached_weather_data
def get_cached_location(self):
"""获取缓存的定位信息"""
return self._cached_location
def set_weather_cache(self, weather_data, location):
"""设置天气缓存"""
self._cached_weather_data = weather_data
self._cached_location = location
self._weather_cache_timestamp = time.time()
def clear_weather_cache(self):
"""清除天气缓存"""
self._cached_weather_data = None
self._cached_location = None
self._weather_cache_timestamp = None
def is_weather_cache_valid(self):
"""检查天气缓存是否有效30分钟内"""
if self._weather_cache_timestamp is None:
return False
return (time.time() - self._weather_cache_timestamp) < 1800 # 30分钟
def get_user_ip(self):
"""获取用户IP地址 - 使用多个备用服务"""
@ -59,7 +90,13 @@ class NetworkService:
"wind_speed": 3.5
}
def get_weather_info(self) -> Optional[Dict[str, Any]]:
def get_weather_info(self, use_cache: bool = True) -> Optional[Dict[str, Any]]:
"""获取天气信息,支持缓存机制"""
# 如果启用缓存且缓存有效,直接返回缓存数据
if use_cache and self.is_weather_cache_valid():
print("使用缓存的天气数据")
return self._cached_weather_data
# 实现天气信息获取逻辑
# 1. 获取用户IP地址 - 使用多个备用服务
@ -91,6 +128,14 @@ class NetworkService:
print("无法获取城市名称,使用默认天气数据")
return self.get_default_weather()
# 保存定位信息到缓存
self._cached_location = {
"ip": ip,
"city": city,
"country": location_data.get("country", "Unknown"),
"region": location_data.get("regionName", "Unknown")
}
# 3. 调用天气API获取天气数据
# 注意这里使用OpenWeatherMap API作为示例需要API密钥
# 在实际应用中需要设置有效的API密钥
@ -162,14 +207,47 @@ class NetworkService:
current_weather = forecast[0] if forecast else {}
weather_type = current_weather.get("type", "")
# 获取生活指数信息
lifetips = []
if current_weather:
# 从预报数据中提取生活提示
ganmao = current_weather.get("ganmao", "")
if ganmao:
lifetips.append(f"感冒指数: {ganmao}")
# 添加其他生活指数(基于天气类型推断)
if "" in weather_type:
lifetips.append("出行建议: 记得带伞")
elif "" in weather_type:
lifetips.append("出行建议: 适合户外活动")
elif "" in weather_type:
lifetips.append("出行建议: 注意防滑保暖")
elif "" in weather_type or "" in weather_type:
lifetips.append("健康提醒: 减少户外运动")
# 温度相关建议
temp = float(wendu) if wendu != "N/A" else 20
if temp > 30:
lifetips.append("穿衣建议: 注意防暑降温")
elif temp < 5:
lifetips.append("穿衣建议: 注意保暖防寒")
elif temp < 15:
lifetips.append("穿衣建议: 适当添加衣物")
else:
lifetips.append("穿衣建议: 天气舒适")
formatted_weather = {
"city": city,
"temperature": float(wendu) if wendu != "N/A" else 20,
"description": weather_type,
"humidity": shidu.replace("%", "") if shidu != "N/A" else "60",
"wind_speed": "3.5" # 默认风速
"wind_speed": "3.5", # 默认风速
"lifetips": lifetips # 生活提示列表
}
print(f"成功获取天气数据: {formatted_weather}")
# 缓存天气数据
self.set_weather_cache(formatted_weather, self._cached_location)
return formatted_weather
else:
print(f"天气API返回错误状态: {weather_data.get('status')}")
@ -178,44 +256,60 @@ class NetworkService:
print(f"获取免费天气数据时出错: {e}")
# 如果以上都失败,返回默认数据
print(f"使用默认天气数据 for {city}")
return {
default_weather = {
"city": city,
"temperature": 20,
"description": "晴天",
"humidity": 60,
"wind_speed": 3.5
"wind_speed": 3.5,
"lifetips": [
"穿衣建议: 天气舒适",
"出行建议: 适合户外活动",
"健康提醒: 保持良好心情"
]
}
print(f"使用默认天气数据 for {city}")
# 缓存默认天气数据
self.set_weather_cache(default_weather, self._cached_location)
return default_weather
except Exception as e:
print(f"获取天气信息时出错: {e}")
return None
def get_daily_quote(self) -> Optional[str]:
# 实现每日一句获取逻辑
# 1. 调用名言API
# 实现每日一句获取逻辑 - 使用古诗词API
try:
# 使用一个免费的名言API禁用SSL验证以避免证书问题
response = self.session.get("https://api.quotable.io/random", timeout=5, verify=False)
# 使用古诗词·一言API - 每次返回随机不同的诗词
response = self.session.get("https://v1.jinrishici.com/all.json", timeout=5, verify=False)
# 2. 解析返回的名言数据
# 2. 解析返回的古诗词数据
if response.status_code == 200:
quote_data = response.json()
content = quote_data.get("content", "")
author = quote_data.get("author", "")
poetry_data = response.json()
content = poetry_data.get('content', '')
author = poetry_data.get('author', '')
title = poetry_data.get('origin', '')
# 3. 格式化名言文本
formatted_quote = f'"{content}" - {author}'
# 3. 格式化古诗词文本
if content and author and title:
formatted_poetry = f"{content}{author}{title}"
elif content and author:
formatted_poetry = f"{content}{author}"
elif content:
formatted_poetry = content
else:
formatted_poetry = "暂无古诗词"
# 4. 返回名言字符串
return formatted_quote
# 4. 返回古诗词字符串
return formatted_poetry
else:
# 如果API调用失败返回默认名言
return "书山有路勤为径,学海无涯苦作舟。"
# 如果API调用失败返回默认古诗词
return "山重水复疑无路,柳暗花明又一村"
except Exception as e:
print(f"获取每日一句时出错: {e}")
# 出错时返回默认名言
return "书山有路勤为径,学海无涯苦作舟"
print(f"获取古诗词时出错: {e}")
# 出错时返回默认古诗词
return "山重水复疑无路,柳暗花明又一村"
def download_image(self, url: str) -> Optional[bytes]:

@ -168,6 +168,10 @@ class WordStyleMainWindow(QMainWindow):
# 初始化时刷新天气
self.refresh_weather()
# 初始化天气缓存相关属性
self.cached_weather_data = None
self.cached_location = None
def init_theme(self):
"""初始化主题"""
@ -933,6 +937,9 @@ class WordStyleMainWindow(QMainWindow):
self.quote_thread = QuoteFetchThread()
self.quote_thread.quote_fetched.connect(self.update_quote_display)
self.quote_thread.start()
# 获取初始天气数据并缓存
self.init_weather_data()
def init_typing_logic(self):
@ -1777,6 +1784,48 @@ class WordStyleMainWindow(QMainWindow):
self.current_weather_data = weather_data
print(f"update_weather_display - 存储的current_weather_data包含life_tips: {self.current_weather_data.get('life_tips', [])}")
def init_weather_data(self):
"""初始化天气数据,使用缓存机制"""
try:
print("初始化天气数据,使用缓存机制")
# 尝试从网络服务获取缓存的天气数据
cached_weather = self.network_service.get_cached_weather_data()
cached_location = self.network_service.get_cached_location()
if cached_weather and cached_location:
print(f"使用缓存的天气数据: {cached_weather}")
print(f"使用缓存的定位数据: {cached_location}")
# 格式化缓存数据
formatted_data = {
'city': cached_weather.get('city', cached_location.get('city', '未知城市')),
'current': cached_weather.get('current', {}),
'forecast': cached_weather.get('forecast', []),
'life_tips': cached_weather.get('life_tips', [])
}
# 更新显示
self.update_weather_display(formatted_data)
# 同步更新天气悬浮窗口
if hasattr(self, 'weather_floating_widget') and self.weather_floating_widget.isVisible():
self.weather_floating_widget.update_weather(formatted_data)
# 保存到本地缓存
self.cached_weather_data = cached_weather
self.cached_location = cached_location
self.status_bar.showMessage("使用缓存天气数据", 2000)
else:
print("没有缓存数据,使用网络获取")
# 没有缓存数据,使用网络获取
self.refresh_weather()
except Exception as e:
print(f"初始化天气数据失败: {e}")
# 如果缓存获取失败,回退到网络获取
self.refresh_weather()
def refresh_weather(self):
"""手动刷新天气信息"""
try:
@ -1796,10 +1845,10 @@ class WordStyleMainWindow(QMainWindow):
print(f"刷新天气 - 当前选择的城市: {current_city}")
if current_city == '自动定位':
# 使用自动定位
# 使用自动定位,启用缓存
weather_data = self.weather_api.get_weather_data()
else:
# 使用选中的城市
# 使用选中的城市,启用缓存
weather_data = self.weather_api.get_weather_data(current_city)
if weather_data:
@ -1816,6 +1865,12 @@ class WordStyleMainWindow(QMainWindow):
# 同步更新天气悬浮窗口
if hasattr(self, 'weather_floating_widget') and self.weather_floating_widget.isVisible():
self.weather_floating_widget.update_weather(formatted_data)
# 保存到网络服务缓存和本地缓存
self.network_service.set_weather_cache(weather_data, self.network_service.get_cached_location())
self.cached_weather_data = weather_data
self.cached_location = self.network_service.get_cached_location()
self.status_bar.showMessage("天气数据已刷新", 2000)
else:
self.status_bar.showMessage("天气数据刷新失败请检查API密钥", 3000)
@ -1829,14 +1884,17 @@ class WordStyleMainWindow(QMainWindow):
"""显示详细天气信息对话框"""
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTextEdit
# 检查是否有天气数据
if not hasattr(self, 'current_weather_data') or not self.current_weather_data:
# 首先尝试使用本地缓存的天气数据
if hasattr(self, 'cached_weather_data') and self.cached_weather_data:
weather_data = self.cached_weather_data
print(f"详细天气对话框 - 使用本地缓存天气数据: {weather_data}")
elif hasattr(self, 'current_weather_data') and self.current_weather_data:
weather_data = self.current_weather_data
print(f"详细天气对话框 - 使用当前天气数据: {weather_data}")
else:
QMessageBox.information(self, "附加工具", "暂无天气数据,请先刷新天气信息")
return
weather_data = self.current_weather_data
print(f"详细天气对话框 - 天气数据: {weather_data}")
# 创建对话框
dialog = QDialog(self)
dialog.setWindowTitle("详细天气")

@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""
测试天气生活提示功能
"""
import sys
import os
# 添加src目录到路径
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'src'))
from services.network_service import NetworkService
def test_weather_with_lifetips():
"""测试包含生活提示的天气功能"""
print("🌤 测试天气生活提示功能")
print("=" * 50)
# 创建网络服务实例
network_service = NetworkService()
# 获取天气信息
print("正在获取天气信息...")
weather_info = network_service.get_weather_info()
if weather_info:
print(f"✅ 成功获取天气数据:")
print(f"城市: {weather_info['city']}")
print(f"温度: {weather_info['temperature']}°C")
print(f"天气: {weather_info['description']}")
print(f"湿度: {weather_info['humidity']}%")
print(f"风速: {weather_info['wind_speed']}m/s")
# 显示生活提示
lifetips = weather_info.get('lifetips', [])
if lifetips:
print(f"\n🌟 生活提示 ({len(lifetips)}条):")
for i, tip in enumerate(lifetips, 1):
print(f" {i}. {tip}")
else:
print("⚠️ 未获取到生活提示")
# 模拟显示详细信息格式
print(f"\n📋 详细信息显示格式:")
weather_text = f"{weather_info['city']}: {weather_info['temperature']}°C, {weather_info['description']}"
weather_text += f"\n湿度: {weather_info['humidity']}%"
weather_text += f"\n风速: {weather_info['wind_speed']}m/s"
if lifetips:
weather_text += "\n\n🌟 生活提示:"
for tip in lifetips:
weather_text += f"\n{tip}"
print(weather_text)
else:
print("❌ 获取天气信息失败")
print("\n" + "=" * 50)
print("测试完成!")
if __name__ == "__main__":
test_weather_with_lifetips()
Loading…
Cancel
Save