diff --git a/app.py b/app.py index 207ec5d..25d7bf1 100644 --- a/app.py +++ b/app.py @@ -13,6 +13,8 @@ import time import os import json import traceback +import requests +from datetime import datetime app = Flask(__name__) socketio = SocketIO(app, cors_allowed_origins="*", ping_timeout=30, ping_interval=5, max_http_buffer_size=50 * 1024 * 1024) @@ -64,7 +66,14 @@ def create_tray_icon(): @app.route('/') def index(): local_ip = get_local_ip() - return render_template('index.html', local_ip=local_ip) + + # 检查更新 + try: + update_info = check_for_updates() + except: + update_info = {'has_update': False} + + return render_template('index.html', local_ip=local_ip, update_info=update_info) @socketio.on('connect') def handle_connect(): @@ -490,6 +499,99 @@ def before_request_handler(): init_model_config() app._model_config_initialized = True +# 版本检查函数 +def check_for_updates(): + """检查GitHub上是否有新版本""" + try: + # 读取当前版本信息 + version_file = os.path.join(CONFIG_DIR, 'version.json') + with open(version_file, 'r', encoding='utf-8') as f: + version_info = json.load(f) + + current_version = version_info.get('version', '0.0.0') + repo = version_info.get('github_repo', 'Zippland/Snap-Solver') + + # 请求GitHub API获取最新发布版本 + api_url = f"https://api.github.com/repos/{repo}/releases/latest" + + # 添加User-Agent以符合GitHub API要求 + headers = {'User-Agent': 'Snap-Solver-Update-Checker'} + + response = requests.get(api_url, headers=headers, timeout=5) + if response.status_code == 200: + latest_release = response.json() + latest_version = latest_release.get('tag_name', '').lstrip('v') + + # 如果版本号为空,尝试从名称中提取 + if not latest_version and 'name' in latest_release: + import re + version_match = re.search(r'v?(\d+\.\d+\.\d+)', latest_release['name']) + if version_match: + latest_version = version_match.group(1) + + # 比较版本号(简单比较,可以改进为更复杂的语义版本比较) + has_update = compare_versions(latest_version, current_version) + + update_info = { + 'has_update': has_update, + 'current_version': current_version, + 'latest_version': latest_version, + 'release_url': latest_release.get('html_url', f"https://github.com/{repo}/releases/latest"), + 'release_date': latest_release.get('published_at', ''), + 'release_notes': latest_release.get('body', ''), + } + + # 缓存更新信息 + update_info_file = os.path.join(CONFIG_DIR, 'update_info.json') + with open(update_info_file, 'w', encoding='utf-8') as f: + json.dump(update_info, f, ensure_ascii=False, indent=2) + + return update_info + + # 如果无法连接GitHub,尝试读取缓存的更新信息 + update_info_file = os.path.join(CONFIG_DIR, 'update_info.json') + if os.path.exists(update_info_file): + with open(update_info_file, 'r', encoding='utf-8') as f: + return json.load(f) + + return {'has_update': False, 'current_version': current_version} + + except Exception as e: + print(f"检查更新失败: {str(e)}") + # 出错时返回一个默认的值 + return {'has_update': False, 'error': str(e)} + +def compare_versions(version1, version2): + """比较两个版本号,如果version1比version2更新,则返回True""" + try: + v1_parts = [int(x) for x in version1.split('.')] + v2_parts = [int(x) for x in version2.split('.')] + + # 确保两个版本号的组成部分长度相同 + while len(v1_parts) < len(v2_parts): + v1_parts.append(0) + while len(v2_parts) < len(v1_parts): + v2_parts.append(0) + + # 逐部分比较 + for i in range(len(v1_parts)): + if v1_parts[i] > v2_parts[i]: + return True + elif v1_parts[i] < v2_parts[i]: + return False + + # 完全相同的版本 + return False + except: + # 如果解析出错,默认不更新 + return False + +@app.route('/api/check-update', methods=['GET']) +def api_check_update(): + """检查更新的API端点""" + update_info = check_for_updates() + return jsonify(update_info) + if __name__ == '__main__': local_ip = get_local_ip() print(f"Local IP Address: {local_ip}") diff --git a/config/version.json b/config/version.json new file mode 100644 index 0000000..2414ade --- /dev/null +++ b/config/version.json @@ -0,0 +1,5 @@ +{ + "version": "1.0.0", + "build_date": "2025-03-27", + "github_repo": "Zippland/Snap-Solver" +} \ No newline at end of file diff --git a/static/style.css b/static/style.css index 3ad6ca1..39bf139 100644 --- a/static/style.css +++ b/static/style.css @@ -1515,3 +1515,78 @@ button:disabled { .footer-link.xiaohongshu-link:hover i { color: #ff4d6d; } + +/* 更新通知样式 */ +.update-notice { + background-color: rgba(var(--primary-rgb), 0.1); + border-bottom: 1px solid rgba(var(--primary-rgb), 0.2); + padding: 0.5rem 0; + transition: all 0.3s ease; + overflow: hidden; + max-height: 3rem; +} + +.update-notice.hidden { + max-height: 0; + padding: 0; + border-bottom: none; +} + +.update-notice-content { + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + font-size: 0.85rem; + color: var(--text-secondary); +} + +.update-notice-content i { + color: var(--primary); +} + +.update-link { + color: var(--primary); + text-decoration: none; + font-weight: 500; + padding: 0.25rem 0.75rem; + border-radius: 3rem; + background: rgba(var(--primary-rgb), 0.1); + transition: all 0.2s ease; +} + +.update-link:hover { + background: rgba(var(--primary-rgb), 0.2); + transform: translateY(-1px); +} + +/* 版本徽章样式 */ +.version-badge { + font-size: 0.75rem; + opacity: 0.6; + margin-left: 0.5rem; + padding: 0.1rem 0.35rem; + border-radius: 3rem; + background-color: rgba(var(--surface-rgb), 0.3); +} + +/* 媒体查询 */ +@media (max-width: 768px) { + .update-notice-content { + font-size: 0.75rem; + } + + .update-link { + padding: 0.2rem 0.5rem; + } +} + +@media (max-width: 480px) { + .update-notice-content > span:not(#updateVersion) { + display: none; + } + + .update-notice-content { + gap: 0.5rem; + } +} diff --git a/templates/index.html b/templates/index.html index 80aa863..28db3f2 100644 --- a/templates/index.html +++ b/templates/index.html @@ -26,6 +26,18 @@ + + +
@@ -261,7 +273,7 @@